services: # B-91 (SEC-51): one-shot, as root, so the bind-mounted ./data belongs to the non-root # user the app runs as (uid 1000) and is closed to everyone else — also the first time # after an older root-owned install, with no sudo on the host. data-permissions: build: . image: plm-lottery-app:local user: "0:0" entrypoint: ["/bin/sh", "-c", "chown -R 1000:1000 /data && chmod -R go-rwx /data"] volumes: - ./data:/data restart: "no" app: build: . image: plm-lottery-app:local restart: unless-stopped env_file: .env environment: - DATABASE_URL=sqlite+aiosqlite:////app/db_data/plm_lottery.db - MASTER_KEY_PATH=/app/key_data/master.xprv.enc - XPRV_ENCRYPTION_KEY_FILE=/run/secrets/xprv_encryption_key # B-92 (ARC-02): uvicorn trusts X-Forwarded-For from Caddy's fixed address only, so the access # log records the client's IP instead of Caddy's. - FORWARDED_ALLOW_IPS=172.28.0.10 secrets: - xprv_encryption_key volumes: - ./data/db:/app/db_data - ./data/keys:/app/key_data - ./data/logs:/app/logs expose: - "8123" # B-92 (ARC-61): ready = Electrum connected, a recent header, a live scheduler. Docker does not # restart an unhealthy container (the process exiting does); the state is for monitoring. healthcheck: test: - CMD - python - -c - "import urllib.request as u; u.urlopen('http://127.0.0.1:8123/health/ready', timeout=4)" interval: 30s timeout: 5s retries: 3 start_period: 60s depends_on: data-permissions: condition: service_completed_successfully caddy: image: caddy:2-alpine@sha256:d8542f48d34a9cf4e4c11a478865229840e87e4c96ea3f439101f31a5d35f75f restart: unless-stopped ports: - "80:80" - "443:443" environment: - SITE_ADDRESS=${SITE_ADDRESS:-localhost} volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config networks: default: ipv4_address: 172.28.0.10 depends_on: - app # A fixed subnet and a fixed address for Caddy, so uvicorn can trust exactly that one proxy (ARC-02). networks: default: ipam: config: - subnet: 172.28.0.0/24 # The Fernet key that protects the master key lives in its own file, outside ./data (a backup of # the data does not carry both) and in no environment variable (SEC-53). secrets: xprv_encryption_key: file: ./secrets/xprv_encryption.key volumes: caddy_data: caddy_config: