Deployment Compose
Language
- Docker Compose YAML and shell scripts.
Runtime Context
- Supported production server deployment path.
Purpose
- Defines and validates the deployable server stack composed of Phoenix, Caddy, FRPS, and optional PostgreSQL.
Key Files
deploy/compose/docker-compose.ymldeploy/compose/.env.exampledeploy/compose/dev.envdeploy/compose/README.mddeploy/compose/caddy/Caddyfile.laptopdeploy/compose/scripts/dev-lab.shdeploy/compose/scripts/check_runtime_contract.shdeploy/compose/scripts/validate_stack.shprod.env
Public Interfaces
- Services:
nixstasiscaddyfrpspostgresclient
- Public published ports:
- Caddy
80:80 - Caddy
443:443 - FRPS bind, HTTP vhost, and TCP mux ports.
- Caddy
- Required operator inputs documented in
deploy/compose/README.md:DATABASE_URLSECRET_KEY_BASEPHX_HOSTPORTBASE_DOMAINCLIENT_IDCLIENT_SECRETTENANT_IDJWT_KEYFRPS_BIND_PORTFRPS_AUTH_TOKENFRPS_HTTP_PORTFRPS_DASHBOARD_PORTFRPS_DASHBOARD_USERFRPS_DASHBOARD_PASSWORDFRPS_TCPMUX_PORT
Runtime Contract
DATABASE_URL: PostgreSQL connection URL consumed by the Phoenixnixstasisservice. It may point at bundled PostgreSQL or an external PostgreSQL host.SECRET_KEY_BASE: Phoenix release secret consumed bynixstasis.PHX_HOST: Public Phoenix host behind Caddy.PORT: Phoenix container port. The supported Compose deployment uses4000.BASE_DOMAIN: Root domain used fornixstasis,auth,frp-admin, and wildcard device hostnames.CLIENT_ID: Entra application client identifier consumed by Caddy auth.CLIENT_SECRET: Entra application secret consumed by Caddy auth.TENANT_ID: Entra tenant identifier consumed by Caddy auth.JWT_KEY: Caddy auth JWT signing key.FRPS_BIND_PORT: FRPS bind port for client tunnel connections.FRPS_AUTH_TOKEN: Shared FRPS auth token consumed byfrps,nixstasis, and managed clients when remote access is requested.FRPS_HTTP_PORT: FRPS HTTP virtual host port used by Caddy wildcard proxying.FRPS_DASHBOARD_PORT: FRPS dashboard port used behind authenticated Caddy ingress.FRPS_DASHBOARD_USER: FRPS dashboard username.FRPS_DASHBOARD_PASSWORD: FRPS dashboard password.FRPS_TCPMUX_PORT: FRPS TCP mux port for TCP remote access.
Hostnames
nixstasis.<base-domain>: public Phoenix application host behind Caddy.auth.<base-domain>: AuthCrunch/OIDC callback and auth host.frp-admin.<base-domain>: authenticated FRPS dashboard host.atom-<normalized-device-id>.<base-domain>: device remote-access host pattern routed through Caddy wildcard TLS and FRPS HTTP vhost support.
Endpoints
check_domain: Phoenix ask endpoint used by Caddy on-demand TLS to authorize wildcard device hostnames before proxying to FRPS.
Artifact Rules
- Server startup and database migrations are separate operations; application startup must not implicitly run migrations.
- Externally sourced runtime artifacts must be pinned by digest or checksum.
- Client release artifacts install bundled
frpcat/usr/libexec/nixstasis/frpcso managed devices do not depend on a separate FRP package.
Dependencies
Internal
packages/server/Dockerfilepackages/caddy/Dockerfilepackages/frp/Dockerfiledeploy/compose/caddy/Caddyfiledeploy/compose/frps/frps.tomlpackages/frp/bin/download_frp.sh
External
- Docker Compose or rendered config for Apple Container
container-compose. - PostgreSQL image (always included; production can override
DATABASE_URL). - Pinned release image references from Compose configuration.
Client-Server Interaction Details
- Compose deployment exposes the Phoenix app only through Caddy for HTTP ingress.
- Client configuration points at the public Caddy host.
- Bundled PostgreSQL starts automatically; production can override
DATABASE_URLto point at an external managed database. - Release image references are pinned in Compose configuration; local development
builds images locally with
devtags. packages/frpcurrently provides FRPS image build assets and the shared FRP binary acquisition script used by server/client packaging flows.- E2E endpoints are disabled by default in production and can be enabled for staging validation with
NIXSTASIS_E2E_ENABLED=true. - Development laptop mode uses the same single
docker-compose.ymlwith a trackeddev.envfile passed viadocker compose --env-file dev.env. deploy/compose/scripts/dev-lab.shstarts the full stack, runs migrations, and seeds virtual devices for UI testing.deploy/compose/caddy/Caddyfile.laptopprovides Caddy internal/local certificates for local HTTPS without public DNS.- The
clientservice is a device simulator running Ubuntu with systemd as PID 1, sshd, frpc, and the Go client binary — matching real device lifecycle. - Default laptop mode uses
BASE_DOMAIN=localhostwithnixstasis.localhost,auth.localhost,frp-admin.localhost, andatom-<normalized-device-id>.localhost. - Laptop-mode TLS uses Caddy internal/local certificates while preserving the same
Phoenix ask endpoint at
GET /api/v1/check_domain. - Environment variables are passed to containers via explicit
environment:blocks in the compose file;--env-filehandles compose-time interpolation.
Traceable references:
deploy/compose/docker-compose.yml:1-129deploy/compose/README.md:1-117deploy/compose/scripts/check_runtime_contract.sh