Self-hosted deployment
Minimum requirements
Section titled “Minimum requirements”- A Linux host with Docker and Docker Compose v2, supporting
docker compose -f a.yml -f b.yml. - A public DNS name pointing to the host and open ports 80/443 if the bundled Caddy terminates TLS.
- Outbound internet access for images and Let’s Encrypt certificates.
- For AI workers:
/var/run/docker.sockon the same host, used by the supervisor, and an LLM endpoint with an OpenAI-compatible API (LiteLLM in the default configuration).
The control plane neither updates itself nor initiates connections to machines. Agents connect to it through WebSocket, so managed machines need no inbound ports.
Docker Compose stack
Section titled “Docker Compose stack”The reference stack is in deploy/docker/docker-compose.yml:
| Service | Purpose |
|---|---|
control-plane |
HTTP/WS API, authentication, chat, memory, and audit; serves the SPA from /app/dist. Listens on 18181. |
postgres |
Postgres 15, used when NYTHRONIX_STORAGE=postgres is enabled. By default, state is stored as JSON in nythronix_state. |
redis |
Included in the stack; connected through NYTHRONIX_REDIS_URL for temporary download tokens. |
minio + minio-init |
S3-compatible release bundle storage; creates the nythronix-bundles bucket automatically. |
supervisor |
Worker reconciler, the only service with docker.sock access, with no inbound ports. Starts and stops workers according to desired state from the control plane. |
First start:
cd deploy/dockercp .env.example .env$EDITOR .env # secrets, public URL, LLMecho '{}' > llm-profiles.jsondocker compose up --build -dEach container start runs preflight (NYTHRONIX_REQUIRE_PREFLIGHT=true). A weak pepper, missing public URL, or http:// without NYTHRONIX_ALLOW_HTTP_FOR_STAGING=true keeps the container restarting until .env is fixed.
Check health:
curl -fsS http://127.0.0.1:18181/api/healthz # {"status":"ok"}: process is alivecurl -fsS http://127.0.0.1:18181/api/readyz # {"status":"ready"}: storage available, bootstrap completeKey environment variables
Section titled “Key environment variables”| Variable | Meaning |
|---|---|
NYTHRONIX_MODE |
self-hosted (default) or saas. Self-hosted enables NX endpoints and administrator bootstrap from environment variables. |
NYTHRONIX_PUBLIC_URL |
Public control plane URL (https://cp.example.com, no trailing /). Must match the browser address exactly: used for WebSocket Origin checks, the canonical /agent/ws, and supervisor URLs. |
NYTHRONIX_EXTRA_ORIGINS |
Additional comma-separated origins, such as https://app.cp.example.com when the dashboard uses a separate host. |
NYTHRONIX_PASSWORD_PEPPER |
Argon2 secret, at least 32 characters. Losing it makes all passwords unverifiable. |
NYTHRONIX_BOOTSTRAP_EMAIL, NYTHRONIX_BOOTSTRAP_PASSWORD |
First administrator, used only with empty storage. |
NYTHRONIX_RUNTIME_TOKEN |
Shared secret between the control plane and supervisor. If unset, runtime API is disabled and workers do not start. |
LITELLM_BASE_URL, LITELLM_API_KEY, LITELLM_MODEL |
Default worker LLM, read by the supervisor, not the control plane. |
NYX_LLM_PROFILES_FILE, NYX_POOL, NYX_WORKER_NETWORK, NYX_HUNG_GRACE_SECS |
Supervisor settings: per-organization LLM profiles, pool name, isolated worker network, and hung-worker threshold. |
NYTHRONIX_SMTP_URL, NYTHRONIX_SMTP_FROM, NYTHRONIX_BETA_NOTIFY_TO |
Outbound beta-request notifications: smtps://user%40example.com:pass@smtp.example.com:465 (implicit TLS) or smtp://…:587 (STARTTLS). Encode @ in usernames as %40. |
NYTHRONIX_STORAGE, NYTHRONIX_DATABASE_URL |
json (default), or postgres with a DSN. |
NYTHRONIX_HOST_PORT |
Host port for the control plane, default 18181. |
See deploy/docker/.env.example for the full list. nythronix-server config-show prints the effective configuration; nythronix-server preflight --strict checks it before startup.
TLS with Caddy or nginx
Section titled “TLS with Caddy or nginx”The shortest path on a fresh VPS is Caddy in the same stack, with automatic certificates:
# in .env: NYTHRONIX_DOMAIN=cp.example.com, NYTHRONIX_PUBLIC_URL=https://cp.example.comdocker compose -f docker-compose.yml -f docker-compose.caddy.yml up --build -dThe overlay removes host publication of port 18181, making Caddy the only entry point. Block direct port access in the firewall.
For an existing reverse proxy, use deploy/caddy/Caddyfile or deploy/nginx/nythronix.conf. Forward /api/* and /proxy/* over HTTP and allow WebSocket upgrades for /agent/ws, /nx/ws, /ws/remote, /ws/nx, /ws/relay, and /ws/control. Pass X-Forwarded-Proto. Caddy handles upgrades transparently; nginx requires proxy_set_header Upgrade / Connection. Agent connections last for hours, so increase read/write timeouts (1–2 hours in the examples).
First administrator
Section titled “First administrator”With empty storage, the server creates the default organization and an owner from NYTHRONIX_BOOTSTRAP_EMAIL / NYTHRONIX_BOOTSTRAP_PASSWORD. Remove these variables after the first successful startup; they are ignored for nonempty storage. SaaS mode does not perform bootstrap.
See Administration for further operator management.
Serving /downloads
Section titled “Serving /downloads”The server serves everything in the SPA directory as static files. To host the Windows installer at https://<cp>/downloads/<file>, mount a directory into control-plane:
services: control-plane: volumes: - nythronix_state:/var/lib/nythronix - ./downloads:/app/dist/downloads:roDownload the Windows agent on the sign-in page and Agents section points to /downloads/nythronix-agent-setup.exe. Place the file under that name. Build it with scripts/build-agent-windows-installer.sh.
Updates
Section titled “Updates”There are two independent paths.
Control plane does not update itself. Rebuild the image and restart the stack:
docker compose -f docker-compose.yml -f docker-compose.caddy.yml up --build -dStartup order matters: the control plane with runtime API must start before the supervisor and workers. The supervisor retries, so a brief startup race only produces a log warning.
Agents, NX endpoints, and the nx CLI update over the connection. Build and sign releases on a separate build machine, not the control plane, and publish with scripts/release.sh. Agents with auto policy receive an offer on their next connection, verify SHA-256 and Ed25519, and restart into the new binary. See Administration and Security model.