Files
pad/docker-compose.prod.yml
T
xarmian 34ebf31fdf fix: resolve Codex review findings across SSE, audit, metrics, and deployment
- Make SSE limit checks atomic with subscription via SubscribeIfAllowed to
  prevent TOCTOU races where concurrent requests bypass connection caps
- Replace fmt.Sprintf JSON assembly with json.Marshal (auditMeta helper) in
  all audit log call sites to prevent silent JSONB insert failures on
  PostgreSQL when metadata contains special characters
- Pass database credentials via PGDATABASE env var instead of pg_dump/psql
  command-line args to avoid leaking passwords in ps/proc output
- Fix audit-log query builder to rebind placeholders once after all filters
  are appended, preventing duplicate $1 placeholders on PostgreSQL
- Replace per-workspace SSE GaugeVec with a single Gauge to avoid unbounded
  Prometheus label cardinality in multi-tenant deployments
- Fix prod Docker Compose: override PAD_REDIS_URL with password and add
  authenticated Redis healthcheck when REDIS_PASSWORD is set
2026-04-07 01:13:44 +00:00

79 lines
2.4 KiB
YAML

# Pad — production Docker Compose override
# Usage: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
#
# Extends the base docker-compose.yml with:
# - Resource limits
# - Secure cookie settings
# - CORS configuration
# - Email (Maileroo) support
# - Named network for reverse proxy integration
services:
pad:
environment:
PAD_SECURE_COOKIES: "true"
# Override Redis URL to include password when REDIS_PASSWORD is set.
# Without this, the pad container inherits the passwordless URL from
# docker-compose.yml and fails to connect when Redis AUTH is enabled.
PAD_REDIS_URL: "redis://:${REDIS_PASSWORD:-}@redis:6379"
# Set your public-facing URL for correct invitation links:
# PAD_URL: "https://pad.example.com"
# CORS origins (comma-separated):
# PAD_CORS_ORIGINS: "https://pad.example.com"
# Email (Maileroo):
# PAD_MAILEROO_API_KEY: "your-sending-key"
# PAD_EMAIL_FROM: "noreply@example.com"
# PAD_EMAIL_FROM_NAME: "Pad"
# SSE limits:
# PAD_SSE_MAX_CONNECTIONS: "1000"
# PAD_SSE_MAX_PER_WORKSPACE: "100"
deploy:
resources:
limits:
cpus: "2.0"
memory: 512M
reservations:
cpus: "0.5"
memory: 128M
networks:
- pad-net
- default
postgres:
environment:
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-change-me-in-production}"
deploy:
resources:
limits:
cpus: "2.0"
memory: 1G
reservations:
cpus: "0.25"
memory: 256M
# In production, consider using a managed PostgreSQL service instead.
redis:
command: redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru --requirepass "${REDIS_PASSWORD:-}"
healthcheck:
# Override the base healthcheck to authenticate when REDIS_PASSWORD is set.
# redis-cli reads REDISCLI_AUTH automatically for authentication.
test: ["CMD-SHELL", "REDISCLI_AUTH=$${REDIS_PASSWORD:-} redis-cli ping | grep -q PONG"]
interval: 5s
timeout: 3s
retries: 5
environment:
REDIS_PASSWORD: "${REDIS_PASSWORD:-}"
deploy:
resources:
limits:
cpus: "1.0"
memory: 256M
reservations:
cpus: "0.1"
memory: 64M
networks:
pad-net:
name: pad-net
# Attach your reverse proxy (Caddy, nginx) to this network.