# Panel — PRODUCTION single-box compose (postgres + controller + agent).
# (Dev Postgres-only compose lives at ../docker-compose.dev.yml.)
#
# Usage, from the repo root:
#   cp deploy/.env.example deploy/.env   # then edit deploy/.env
#   docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d --build
#
# First run: watch `docker compose logs controller` for the ADMIN BOOTSTRAP
# banner (generated admin password), then create a pair token in the UI
# (or via POST /api/admin/pair-tokens) — the agent pairs itself on start
# only if you exec the pairing step; see README / install.sh for the flow.

services:
  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: panel
      POSTGRES_PASSWORD: ${PANEL_DB_PASSWORD:?set PANEL_DB_PASSWORD in deploy/.env}
      POSTGRES_DB: panel
    volumes:
      - panel_pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U panel -d panel"]
      interval: 5s
      timeout: 3s
      retries: 10

  controller:
    build:
      context: ..
      dockerfile: deploy/Dockerfile.controller
      args:
        VERSION: ${PANEL_VERSION:-dev}
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      PANEL_DB_URL: postgres://panel:${PANEL_DB_PASSWORD}@postgres:5432/panel?sslmode=disable
      # Optional: stable first-boot admin password instead of a generated one.
      PANEL_ADMIN_PASSWORD: ${PANEL_ADMIN_PASSWORD:-}
    ports:
      - "${PANEL_HTTP_PORT:-8080}:8080"   # dashboard + REST API
      - "${PANEL_GRPC_PORT:-8443}:8443"   # agent gRPC (mTLS)
    volumes:
      - panel_controller_data:/opt/panel/data

  agent:
    build:
      context: ..
      dockerfile: deploy/Dockerfile.agent
      args:
        VERSION: ${PANEL_VERSION:-dev}
    restart: unless-stopped
    depends_on:
      - controller
    # ┌────────────────────────────── SECURITY ──────────────────────────────┐
    # │ The agent mounts the HOST Docker socket to create and manage game-   │
    # │ server containers. Docker-socket access is ROOT-EQUIVALENT on the    │
    # │ host: anyone who can reach this container's filesystem or process    │
    # │ can own the machine. Run this stack only on a host you fully trust,  │
    # │ keep the panel dashboard behind auth/TLS, and never re-export the    │
    # │ socket from this container.                                          │
    # └───────────────────────────────────────────────────────────────────────┘
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      # IMPORTANT: the agent passes instance paths to the HOST docker daemon
      # as bind mounts, so the host path and in-container path MUST match.
      # Keep both sides of this mapping identical.
      - ${PANEL_AGENT_DATA:-/opt/panel/data}:${PANEL_AGENT_DATA:-/opt/panel/data}
    environment:
      PANEL_GRPC_PORT: "8443"
    command:
      - "--controller"
      - "controller:8443"
      - "--modules-dir"
      - "./modules"
      - "--data-root"
      - "${PANEL_AGENT_DATA:-/opt/panel/data}/instances"
      - "--meta-dir"
      - "${PANEL_AGENT_DATA:-/opt/panel/data}/instance-meta"
      - "--backup-dir"
      - "${PANEL_AGENT_DATA:-/opt/panel/data}/backups"
      - "--cert-dir"
      - "${PANEL_AGENT_DATA:-/opt/panel/data}/certs"

volumes:
  panel_pgdata:
  panel_controller_data:
