CI / lint (push) Canceled after 0s
CI / typecheck (push) Canceled after 0s
CI / unit-tests (push) Canceled after 0s
CI / integration-tests (push) Canceled after 0s
CI / container-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s
Two real bugs hit during tonight's first production deploy (found and fixed live on the server, folded back into the tracked config so the next deploy doesn't hit either wall): 1. pgbouncer defaults to md5 auth; postgres:17-alpine defaults password_encryption to scram-sha-256. Every connection failed with "wrong password type" until AUTH_TYPE=scram-sha-256 was set explicitly on the pgbouncer service. 2. POSTGRES_USER/PASSWORD/DB were never documented anywhere (not in .env.example, despite docker-compose.prod.yml requiring them) -- added, with a note against `openssl rand -base64` for the password specifically: its output can contain /+=, which breaks pgbouncer's (and any DATABASE_URL parser's) naive URL parsing. Pointed at token_urlsafe instead, matching the other generated secrets. Co-Authored-By: Claude Sonnet 5 <[email protected]>
145 lines
4.4 KiB
YAML
145 lines
4.4 KiB
YAML
# Production-oriented topology (section 1/28): the host's own webserver
|
|
# (cPanel/Apache or LiteSpeed -- already holding ports 80/443 for other
|
|
# sites on the box) reverse-proxies to the API container on 127.0.0.1,
|
|
# terminating TLS itself; there's no Traefik here. PgBouncer sits in front
|
|
# of PostgreSQL, Redis and the worker are independently scaled. Requires a
|
|
# populated `.env` (never commit real secrets).
|
|
name: aurora-core
|
|
|
|
networks:
|
|
aurora-internal:
|
|
driver: bridge
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-aurora}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
POSTGRES_DB: ${POSTGRES_DB:-aurora_core}
|
|
volumes:
|
|
- aurora_postgres_data:/var/lib/postgresql/data
|
|
networks: [aurora-internal]
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-aurora}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
deploy:
|
|
resources:
|
|
limits: { cpus: "2", memory: 2G }
|
|
|
|
pgbouncer:
|
|
image: edoburu/pgbouncer:latest
|
|
restart: unless-stopped
|
|
environment:
|
|
DATABASE_URL: postgres://${POSTGRES_USER:-aurora}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-aurora_core}
|
|
POOL_MODE: transaction
|
|
MAX_CLIENT_CONN: "1000"
|
|
DEFAULT_POOL_SIZE: "25"
|
|
# postgres:17-alpine defaults password_encryption to scram-sha-256;
|
|
# pgbouncer defaults auth_type to md5, which then fails every
|
|
# connection with "wrong password type" against a scram-only server.
|
|
AUTH_TYPE: scram-sha-256
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks: [aurora-internal]
|
|
healthcheck:
|
|
test: ["CMD", "pg_isready", "-h", "localhost", "-p", "5432"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 10
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
restart: unless-stopped
|
|
command: ["redis-server", "--maxmemory", "512mb", "--maxmemory-policy", "allkeys-lru"]
|
|
volumes:
|
|
- aurora_redis_data:/data
|
|
networks: [aurora-internal]
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
|
|
migrate:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/api.Dockerfile
|
|
env_file: .env
|
|
environment:
|
|
DATABASE_URL_SYNC: postgresql+psycopg2://${POSTGRES_USER:-aurora}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-aurora_core}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks: [aurora-internal]
|
|
entrypoint: ["alembic"]
|
|
command: ["upgrade", "head"]
|
|
|
|
api:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/api.Dockerfile
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
environment:
|
|
AURORA_ENV: production
|
|
DATABASE_BEHIND_TRANSACTION_POOLER: "true"
|
|
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-aurora}:${POSTGRES_PASSWORD}@pgbouncer:5432/${POSTGRES_DB:-aurora_core}
|
|
REDIS_URL: redis://redis:6379/0
|
|
MEDIA_ROOT: /app/media
|
|
volumes:
|
|
- aurora_media_data:/app/media
|
|
depends_on:
|
|
pgbouncer:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
migrate:
|
|
condition: service_completed_successfully
|
|
networks: [aurora-internal]
|
|
# Bound to localhost only -- the host's own webserver (cPanel/Apache or
|
|
# LiteSpeed, already holding 80/443 for other sites on the box) terminates
|
|
# TLS for api.amdbs.net and reverse-proxies here. No Traefik on this box.
|
|
ports:
|
|
- "127.0.0.1:${AURORA_API_PORT:-8000}:8000"
|
|
deploy:
|
|
resources:
|
|
limits: { cpus: "1", memory: 1G }
|
|
|
|
worker:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/worker.Dockerfile
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
environment:
|
|
AURORA_ENV: production
|
|
DATABASE_BEHIND_TRANSACTION_POOLER: "true"
|
|
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-aurora}:${POSTGRES_PASSWORD}@pgbouncer:5432/${POSTGRES_DB:-aurora_core}
|
|
REDIS_URL: redis://redis:6379/0
|
|
MEDIA_ROOT: /app/media
|
|
volumes:
|
|
- aurora_media_data:/app/media
|
|
depends_on:
|
|
pgbouncer:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
migrate:
|
|
condition: service_completed_successfully
|
|
networks: [aurora-internal]
|
|
deploy:
|
|
replicas: 2
|
|
resources:
|
|
limits: { cpus: "1", memory: 1G }
|
|
|
|
volumes:
|
|
aurora_postgres_data:
|
|
aurora_redis_data:
|
|
aurora_media_data:
|