name: overcooked-s x-logging: &logging driver: json-file options: max-size: 10m max-file: "5" services: postgres: image: postgres:17-alpine restart: unless-stopped environment: POSTGRES_DB: product_s POSTGRES_USER: product_s POSTGRES_PASSWORD: ${S_POSTGRES_PASSWORD:?required} POSTGRES_INITDB_ARGS: --data-checksums volumes: - s-postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U product_s -d product_s"] interval: 5s timeout: 3s retries: 20 networks: [backend] security_opt: [no-new-privileges:true] logging: *logging mem_limit: 512m valkey: image: valkey/valkey:8-alpine restart: unless-stopped environment: S_VALKEY_PASSWORD: ${S_VALKEY_PASSWORD:?required} command: ["sh", "-ec", "exec valkey-server --appendonly yes --maxmemory-policy noeviction --requirepass \"$${S_VALKEY_PASSWORD}\""] volumes: - s-valkey:/data healthcheck: test: ["CMD-SHELL", "valkey-cli -a \"$${S_VALKEY_PASSWORD}\" --no-auth-warning ping | grep -q PONG"] interval: 5s timeout: 3s retries: 20 networks: [backend] security_opt: [no-new-privileges:true] logging: *logging mem_limit: 128m s-migrate: image: postgres:17-alpine depends_on: postgres: {condition: service_healthy} environment: PGHOST: postgres PGUSER: product_s PGDATABASE: product_s PGPASSWORD: ${S_POSTGRES_PASSWORD:?required} volumes: - ${OVERCOOKED_ROOT:-/opt/overcooked}/migrations:/migrations:ro - ${OVERCOOKED_ROOT:-/opt/overcooked}/s-migrate.sh:/migrate.sh:ro command: ["sh", "/migrate.sh"] networks: [backend] security_opt: [no-new-privileges:true] restart: "no" logging: *logging mem_limit: 128m s-control: image: ${S_CONTROL_IMAGE:?required} restart: unless-stopped init: true depends_on: s-migrate: {condition: service_completed_successfully} valkey: {condition: service_healthy} ports: - ${S_API_PORT_MAPPING:-0.0.0.0:18080:8080} read_only: true tmpfs: - /tmp:size=32m,mode=1777 environment: S_HTTP_ADDR: :8080 S_DATABASE_URL: postgres://product_s:${S_POSTGRES_PASSWORD}@postgres:5432/product_s?sslmode=disable S_VALKEY_URL: redis://:${S_VALKEY_PASSWORD}@valkey:6379/0 S_INTERNAL_KEY_ID: ${S_INTERNAL_KEY_ID:?required} S_INTERNAL_SHARED_SECRET: ${S_INTERNAL_SHARED_SECRET:?required} S_ACCESS_TOKEN_SECRET: ${S_ACCESS_TOKEN_SECRET:?required} S_SETUP_TOKEN: ${S_SETUP_TOKEN:?required} S_ACCESS_TOKEN_TTL: ${S_ACCESS_TOKEN_TTL:-15m} S_EMBY_ACCESS_TOKEN_TTL: ${S_EMBY_ACCESS_TOKEN_TTL:-720h} S_REFRESH_TOKEN_TTL: ${S_REFRESH_TOKEN_TTL:-720h} S_PLAYBACK_SESSION_TTL: ${S_PLAYBACK_SESSION_TTL:-90s} S_E_BASE_URL: ${S_E_BASE_URL:?required} S_E_PUBLIC_URL: ${S_E_PUBLIC_URL:-} S_E_KEY_ID: ${S_E_KEY_ID:?required} S_E_INTERNAL_SECRET: ${S_E_INTERNAL_SECRET:?required} S_E_ALLOW_INSECURE_HTTP: ${S_E_ALLOW_INSECURE_HTTP:-false} S_AUTH_BASE_URL: ${S_AUTH_BASE_URL:?required} S_AUTH_ALLOW_INSECURE_HTTP: ${S_AUTH_ALLOW_INSECURE_HTTP:-false} S_AUTH_PUBLIC_KEYS: ${S_AUTH_PUBLIC_KEYS:?required} S_AUTH_HEARTBEAT_INTERVAL: ${S_AUTH_HEARTBEAT_INTERVAL:-5m} S_INSTANCE_ID: ${S_INSTANCE_ID:-s-production-1} S_PLATFORM: ${S_PLATFORM:-linux-amd64} S_VERSION: ${S_VERSION:-customer} S_BACKUP_DIRECTORY: /var/lib/overcooked-s/backups S_UPDATE_DIRECTORY: /var/lib/overcooked-s/updates S_TURNSTILE_SITE_KEY: ${S_TURNSTILE_SITE_KEY:-} S_TURNSTILE_SECRET_KEY: ${S_TURNSTILE_SECRET_KEY:-} S_TURNSTILE_HOSTNAME: ${S_TURNSTILE_HOSTNAME:-} S_TELEGRAM_MTPROTO_URL: ${S_TELEGRAM_MTPROTO_URL:-http://telegram-disabled.invalid:8098} S_PORTAL_LOCATION: ${S_PORTAL_LOCATION:-Private Node} S_PORTAL_SERVER_URL: ${S_PORTAL_SERVER_URL:-} S_PORTAL_WEB_CLIENT_URL: ${S_PORTAL_WEB_CLIENT_URL:-} S_PORTAL_ANNOUNCEMENT: ${S_PORTAL_ANNOUNCEMENT:-} S_STORAGE_WEBHOOK_SECRET: ${S_STORAGE_WEBHOOK_SECRET:-} S_NODE_IMAGE_ARCHIVE: /var/lib/overcooked-s/node-images/media-node.tar.gz S_NODE_IMAGE_NAME: ${S_NODE_IMAGE_NAME:-git.leee.xin/overcooked/overcooked-media-node:latest} S_NODE_CONTROLLER_HOST: ${S_NODE_CONTROLLER_HOST:-} volumes: - s-backups:/var/lib/overcooked-s/backups - s-updates:/var/lib/overcooked-s/updates - ${OVERCOOKED_ROOT:-/opt/overcooked}/node-images:/var/lib/overcooked-s/node-images:ro healthcheck: test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8080/health/live || exit 1"] interval: 10s timeout: 3s start_period: 15s retries: 6 networks: backend: control-plane: aliases: [product-s] security_opt: [no-new-privileges:true] cap_drop: [ALL] logging: *logging mem_limit: 384m control-proxy: image: ${S_WEBUI_IMAGE:?required} restart: unless-stopped init: true depends_on: s-control: {condition: service_healthy} command: ["node", "/run/overcooked-control-plane/control-proxy.mjs"] volumes: - ${OVERCOOKED_ROOT:-/opt/overcooked}/control-plane:/run/overcooked-control-plane:ro healthcheck: test: - CMD - node - -e - | const fs = require("node:fs"); const https = require("node:https"); const request = https.get("https://control-proxy:8443/health/live", {ca: fs.readFileSync("/run/overcooked-control-plane/ca.crt"), cert: fs.readFileSync("/run/overcooked-control-plane/client.crt"), key: fs.readFileSync("/run/overcooked-control-plane/client.key"), servername: "control-proxy", rejectUnauthorized: true}, (response) => { response.resume(); process.exit(response.statusCode === 200 ? 0 : 1); }); request.setTimeout(2000, () => { request.destroy(); process.exit(1); }); request.on("error", () => process.exit(1)); interval: 10s timeout: 3s start_period: 10s retries: 6 networks: [control-plane] security_opt: [no-new-privileges:true] cap_drop: [ALL] logging: *logging mem_limit: 128m webui: image: ${S_WEBUI_IMAGE:?required} restart: unless-stopped init: true depends_on: s-control: {condition: service_healthy} ports: - ${S_WEB_PORT_MAPPING:-0.0.0.0:18083:3000} read_only: true tmpfs: - /tmp:size=64m,mode=1777 - /app/.next/cache:size=64m,mode=0755,uid=1000,gid=1000 networks: backend: frontend: control-plane: aliases: [product-s-web] healthcheck: test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:3000/ || exit 1"] interval: 10s timeout: 3s start_period: 20s retries: 6 security_opt: [no-new-privileges:true] cap_drop: [ALL] logging: *logging mem_limit: 384m networks: backend: internal: true frontend: control-plane: external: true name: overcooked-control volumes: s-postgres: s-valkey: s-backups: s-updates: