Skip to content

Deployment

This document describes the Docker Compose topology defined in Sectorwars2102/docker-compose.yml. It is the single source of truth for which services run, how they are wired, and what they need from the environment.

Profiles

Compose profiles select which subset of services starts. Multiple profiles can be combined.

Profile Services started Use case
development / default database, redis-cache, gameserver, player-client, admin-ui, nginx-gateway, region-manager Local development with hot-reload volumes.
multi-regional central-nexus-db, redis-cache, redis-nexus, central-nexus-server, player-client, admin-ui, nginx-gateway, region-manager Testing the full multi-region topology.
production central-nexus-db, redis-cache, redis-nexus, central-nexus-server, player-client, admin-ui, nginx-gateway Hardened deployment without dev DB or region-manager.
monitoring prometheus, grafana Add to any other profile.
regional-template regional-db-template, regional-server-template Template definitions used by region-manager to clone a new region. Not started directly.

Run with e.g.:

docker compose up                                   # default / development
docker compose --profile multi-regional up
docker compose --profile production --profile monitoring up

The compose file has no version: key (modern Compose). Trust docker-compose.yml as the source of truth for the service list.

Networks

Three bridge networks segment traffic:

Network Subnet Used by
sectorwars-network default bridge database, redis-cache, gameserver, player-client, admin-ui, nginx-gateway, region-manager
nexus-network ${NEXUS_SUBNET:-172.20.0.0/16} central-nexus-db, redis-cache, redis-nexus, central-nexus-server, regional-*, nginx-gateway, prometheus, grafana
regional-network ${REGIONAL_SUBNET:-172.21.0.0/16} central-nexus-server, regional-server-template, nginx-gateway

redis-cache straddles sectorwars-network and nexus-network so dev and multi-regional services can share it. nginx-gateway is on all three so it can route to any backend.

Volumes

All named volumes are local Docker volumes. Grouped roughly by purpose:

  • Dev persistence: postgres_data, postgres_backups, redis_cache_data, gameserver_data, gameserver_logs, nginx_logs.
  • Multi-regional: central_nexus_data, redis_nexus_data, nexus_assets, regional_assets, admin_ui_assets, player_client_assets.
  • Monitoring: prometheus_data, grafana_data.

Bind mounts worth knowing about:

  • ./services/<svc>:/app on gameserver, player-client, admin-ui enables live reload by mounting source over the image.
  • ./services/database/init:/docker-entrypoint-initdb.d runs SQL on first boot.
  • ./services/gameserver/sql/init-central-nexus.sql initializes the Nexus DB.
  • /var/run/docker.sock:/var/run/docker.sock is mounted into region-manager so it can launch sibling containers. Treat this as a privileged surface.

Healthchecks

Every long-running service defines a healthcheck:

Service Test Interval / start
database, central-nexus-db, regional-db-template pg_isready -U $USER -d $DB 10 s / 30 s start
redis-cache, redis-nexus redis-cli -a $PWD ping (port 6380 for nexus) 10 s
gameserver, central-nexus-server, regional-server-template curl -f http://localhost:8080/api/v1/status/health 30 s / 40 s start
region-manager curl -f http://localhost:8080/health 30 s
player-client, admin-ui Node http.get('/index.html') returns 200 30 s

Compose uses these for depends_on: condition: service_healthy so the gameserver waits for Postgres + Redis to report healthy before starting.

Environment variables

All configuration is environment-driven; secrets live in a .env file at the repo root (gitignored). services/gameserver/src/core/config.py is the authority for what the backend reads.

Required

  • DATABASE_URL — full Postgres URL.
  • JWT_SECRET — must be ≥32 characters; the gameserver refuses to start otherwise (config.py raises ValueError).
  • SECRET_KEY — generic app secret.
  • ADMIN_USERNAME, ADMIN_PASSWORD — bootstrap admin credentials, hashed with Argon2 on first boot.

OAuth (optional but used in real environments)

  • CLIENT_ID_GITHUB, CLIENT_SECRET_GITHUB — note: not GITHUB_* because GitHub reserves that prefix in Codespaces.
  • GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET.
  • STEAM_API_KEY.

URLs and environment detection

  • API_BASE_URL (default http://localhost:8080).
  • FRONTEND_URL (default http://localhost:3000).
  • ENVIRONMENTdevelopment | production | test.
  • DEBUG — toggles /docs, /redoc, /openapi.json exposure (gated in main.py).
  • DEV_ENVIRONMENT, CODESPACE_NAME, GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN — picked up by settings.detect_environment() to switch between local and Codespaces.

AI / payments / multi-regional

  • OPENAI_API_KEY, ANTHROPIC_API_KEY, OPENAI_MODEL, ANTHROPIC_MODEL, AI_DIALOGUE_ENABLED, AI_PROVIDER_PRIMARY, AI_PROVIDER_SECONDARY, AI_PROVIDER_FALLBACK.
  • PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PAYPAL_WEBHOOK_ID, PAYPAL_MODE, PAYPAL_GALACTIC_CITIZEN_PLAN_ID, PAYPAL_REGIONAL_OWNER_PLAN_ID.
  • NEXUS_DB_NAME, NEXUS_DB_USER, NEXUS_DB_PASSWORD, NEXUS_DB_PORT.
  • REGION_NAME, REGION_DB_USER, REGION_DB_PASSWORD, REGION_OWNER_ID, CENTRAL_NEXUS_URL, ENABLE_CROSS_REGIONAL_API, REGIONAL_ISOLATION.

Ports / networking

GAMESERVER_PORT (8080), PLAYER_CLIENT_PORT (3000), ADMIN_UI_PORT (3001), REGION_MANAGER_PORT (8081), DB_PORT (5433), REDIS_PORT (6379), REDIS_NEXUS_PORT (6380), HTTP_PORT (80), HTTPS_PORT (443), PROMETHEUS_PORT (9090), GRAFANA_PORT (3002).

A working .env.example lives at Sectorwars2102/.env.example.

Dev vs prod differences

Drawn directly from docker-compose.yml:

Concern Dev (development / default) Prod (production)
Database Local database service (Postgres in container) central-nexus-db plus per-region DBs
Redis redis-cache only redis-cache + redis-nexus for cross-region pub/sub
Game server Single gameserver container with bind-mounted source central-nexus-server (read-only image, no source bind), plus regional servers spun up by region-manager
region-manager Present (so you can prototype provisioning) Absent in production profile; provisioning happens out-of-band
FastAPI docs /docs, /redoc, /openapi.json enabled when DEBUG=true Disabled when DEBUG=false (see services/gameserver/src/main.py)
CORS allow_origins=["*"] when DEVELOPMENT_MODE Restricted to FRONTEND_URL plus Codespaces / Repl.co wildcards
Trusted hosts ["*"] in dev localhost, *.app.github.dev, *.repl.co
Nginx Optional in dev Required entry point; TLS via mounted certs in services/nginx-gateway/ssl/
Volumes Bind-mounted source for hot reload Named volumes for built assets only (player_client_assets, admin_ui_assets)
Logging DEBUG level when DEBUG=true INFO level

docker-compose.yml ships local Postgres containers for both dev and the Nexus. A remote Postgres (e.g. Neon) can be used by overriding DATABASE_URL.

Operational notes

  • The gameserver's startup_event (in src/main.py) runs Base.metadata.create_all, so a fresh DB will be schema-populated on first boot — Alembic migrations are still the source of truth for schema evolution (services/gameserver/alembic/).
  • A background heartbeat task (_heartbeat_cleanup_loop) runs every 30 s to evict WebSocket connections idle for more than 5 minutes.
  • Prometheus scrapes are configured via monitoring/prometheus.yml (mounted into the prometheus container). Grafana provisioning lives under monitoring/grafana/.