# Production Installation ## Supported installation paths Conductor supports: 1. A public container installation using `compose.production.yml` and a pinned release image. 2. A reproducible source build using `Dockerfile.production` and `compose.production.build.yml`. 3. SkeletonWorks deployment through `setup-conductor.sh` in the `skeletonworks-scripts` repository. The production distribution is one same-origin service. Express serves the compiled React application, `/api`, and refreshable published routes such as `/apps/inventory/details` on internal port 8080. The development-only frontend/backend containers are not production artifacts. ## Requirements - Docker Engine with Compose v2 - Approximately 1 GiB memory and 1.5 CPU available by default - A persistent Docker volume or host directory for `/data` - TLS reverse proxy for internet-facing deployments - Two independently generated persistent keys ## Public container installation Download `compose.production.yml` and `.env.production.example` from the same tagged release. Do not mix files from different releases. ```bash mkdir conductor && cd conductor curl -O https://gitea.skeletonworks.online/vwiebe/conductor/raw/tag/v0.1.0/compose.production.yml curl -o .env https://gitea.skeletonworks.online/vwiebe/conductor/raw/tag/v0.1.0/.env.production.example ``` Edit `.env`: ```dotenv CONDUCTOR_SECRET_KEY= CONDUCTOR_SESSION_KEY= CONDUCTOR_IMAGE=gitea.skeletonworks.online/vwiebe/conductor CONDUCTOR_VERSION=v0.1.0 CONDUCTOR_BIND_ADDRESS=127.0.0.1 CONDUCTOR_PORT=8080 ``` `CONDUCTOR_SECRET_KEY` encrypts stored REST credentials. Losing or changing it makes those credentials unrecoverable. `CONDUCTOR_SESSION_KEY` protects sessions; changing it logs everyone out. Neither belongs in source control. Start and verify: ```bash docker compose --env-file .env -f compose.production.yml pull docker compose --env-file .env -f compose.production.yml up -d docker compose --env-file .env -f compose.production.yml ps curl --fail http://127.0.0.1:8080/api/health ``` Open the configured URL. A new database presents the browser first-run administrator screen. Conductor never ships a default username or password. ## Build from source Use a tagged source archive or checkout: ```bash git clone https://gitea.skeletonworks.online/vwiebe/conductor.git cd conductor git checkout v0.1.0 cp .env.production.example .env # Replace both key placeholders. docker compose --env-file .env \ -f compose.production.yml -f compose.production.build.yml \ up -d --build ``` The multi-stage build compiles frontend and backend code, prunes development dependencies, includes the matching project schema, and runs as UID/GID 10001. ## Caddy Bind Conductor to loopback and proxy it through Caddy: ```caddyfile conductor.example.com { reverse_proxy 127.0.0.1:8080 encode zstd gzip } ``` Caddy provides TLS automatically when DNS and ports 80/443 are correctly configured. ## NGINX ```nginx server { listen 443 ssl http2; server_name conductor.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` Configure certificates using the operator's normal NGINX/TLS process. ## Internal REST destinations The proxy denies private/internal destinations by default. `CONDUCTOR_PROXY_INTERNAL_ORIGINS` is an optional comma-separated allowlist of exact origins. Add only reviewed origins, for example `https://api.internal.example.com:443`. It does not accept wildcard hosts. ## SkeletonWorks On a prepared SkeletonWorks host: ```bash sudo bash /opt/skeletonworks/scripts/setup-conductor.sh \ --domain example.com \ --image gitea.skeletonworks.online/vwiebe/conductor:v0.1.0 \ --restartcaddy ``` The script creates `/opt/skeletonworks/conductor/conductor.example.com`, preserves keys across reruns, joins `skeletonworks_net`, installs a Caddy block and backup cron entry, waits for health, and emits a JSON result. Prefer immutable version, Git-SHA, or digest references over `latest`. ## Uninstalling Stopping/removing containers does not remove the named data volume: ```bash docker compose --env-file .env -f compose.production.yml down ``` Do not add `--volumes` unless a verified backup exists and permanent data deletion is intended.