Files
DoGaMa-serv/docs/operations/deployment-and-release.md
codex e42ce9184e
CI / validate (pull_request) Successful in 20m51s
feat(auth): simplify bootstrap and initial database schema
2026-08-14 08:36:52 +02:00

6.8 KiB

Deployment and release

Production deployment

DoGaMa V1 targets one Linux Docker host with the Compose plugin. Use the root compose.yaml, place the public HTTP service behind a trusted TLS reverse proxy, and never publish the agent port.

cp .env.example .env
docker compose config --quiet
docker compose pull
docker compose up -d

The deployment has exactly two services: dogama and agent. On first start, the agent creates its shared token in the internal agent_auth volume and the application creates its master encryption key below DOGAMA_DATA_PATH. Both use the operating system cryptographic random source, atomic create-without-replacement behavior and restrictive modes. Existing files are validated and reused; an invalid file stops the owning service and is never silently replaced. Secret values never enter .env, Compose values, logs, APIs or the UI.

The services may start in either order. The application waits up to 60 seconds for the token and an authenticated agent health response. Compose restart policy provides a clean subsequent attempt if the agent or Docker daemon takes longer. An interrupted atomic write leaves no installed partial secret; the next start retries creation. No initializer, setup command or host permission repair is part of this workflow.

The application data path contains SQLite, import staging and the application-only master key. The internal agent_state volume contains the authenticated container-binding registry; the separate internal agent_auth volume contains only the shared token and is mounted read-only at the application's token directory. Both volumes are durable security state: losing either makes existing containers unknown rather than silently adopting them. The application cannot read the registry and the agent never receives the master key.

Only host-side storage locations, image version, web port, timezone and the two Docker network names are public Compose settings. DOGAMA_NETWORK names the application-facing network used by a reverse proxy. DOGAMA_GAMES_NETWORK names the sole network that the restricted agent attaches to created and recreated game containers. API plans contain no caller-selectable network. Container paths and allowed agent roots remain fixed internal contracts. Back up the application data, game servers, backups, agent_state and agent_auth together.

Both services use root inside their container namespaces so Docker-created bind directories and ordinary administrator-selected paths work without knowledge of an image-specific UID/GID. They keep read-only root filesystems, no-new-privileges, an empty Linux capability set and a 0077 process umask for new files. The main application never receives the Docker socket. DoGaMa creates only directories it needs below the configured roots and never performs an automatic recursive chown of application, server or backup data. Game-container UID/GID selection remains a separate per-instance setting.

For NAS or server-style paths, set ordinary writable locations in .env, for example /srv/apps/dogama/data, /srv/games and /srv/backups, then run docker compose up -d. No /etc or host /var/lib setup, system user, systemd unit or bootstrap script is required.

Upgrade and rollback

The two-service deployment validates and reuses secrets created by its normal first-start contract. The v0.1.0 initializer used a different application-image identity, so do not claim an unverified in-place migration for a v0.1.0 deployment where initialization completed; preserve all five stores and validate that case on a copy before changing production. For normal updates after this correction, stop DoGaMa, take a filesystem-consistent backup of all five persistent stores, replace the canonical compose.yaml, change only DOGAMA_VERSION, then run docker compose pull and docker compose up -d.

Startup initializes a new SQLite database directly from the current schema before serving requests. Development databases from older revisions are intentionally unsupported for now: schema changes can require starting again with an empty application database. Versioned migrations will be introduced before production stabilization. Never remove or recreate agent_state or agent_auth, and never replace an existing master key: doing so would invalidate the agent registry or make encrypted notification data unreadable.

Release pipeline

Normal CI runs for pull requests and pushes to main; it does not publish images. .gitea/workflows/release.yml runs only for tags matching v*.*.*, validates the exact tag commit, then publishes the dogama and dogama-agent images for Linux amd64 and arm64.

The external tag keeps its v (v0.1.0), while container images use 0.1.0. Stable releases also update latest; prerelease tags containing a hyphen never do. Images are published to:

git.zaynet.fr/dogama/dogama:<version>
git.zaynet.fr/dogama/dogama-agent:<version>

The workflow uses the protected Gitea Actions secret REGISTRY_TOKEN for registry login and Gitea Release creation. After all validations and both image pushes succeed, it creates DoGaMa <tag> against the exact tagged commit with notes derived from actual commit subjects. Tokens are never stored in the repository or printed.

The repository owner should protect the Gitea tag pattern v* so only authorized accounts can trigger production publication. Do not create a release tag until the candidate commit has passed the full disposable-host verification below.

Release verification

Run the complete validation gate in AGENTS.md, then verify the release artifacts and both image targets:

make release VERSION=v0.1.0
(cd dist/dogama-v0.1.0 && sha256sum -c SHA256SUMS)
make images VERSION=v0.1.0

On an isolated Docker host, start with empty application paths and no agent_state or agent_auth, then run only docker compose up -d. Confirm automatic secret initialization and reuse, authenticated agent health, application bootstrap, Palworld draft/install, lifecycle operations, backup/restore, failed-update rollback, configured game-network attachment and denial against unrelated containers or caller-selected networks. Confirm that only the web port is published, the main application lacks the Docker socket and agent registry, the agent cannot access the master key, and player/backup data survive docker compose down followed by docker compose up -d without -v.

Web access policy

HTTP is supported by default for LAN and first-install use. Deploy a trusted TLS reverse proxy for production, then enable Require HTTPS in Settings / Web access if the UI must be HTTPS-only. A canonical base URL is an optional validated HTTP(S) origin without a path. Safe navigation to a noncanonical origin redirects to that origin; mutating requests are refused. Restrict direct backend access when relying on proxy-provided X-Forwarded-Proto.