# Docker Compose for deployment behind an existing Traefik reverse proxy # All domains and the proxy web name are configurable via environment variables services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: hq-postgres environment: POSTGRES_USER: ${POSTGRES_USER:-headquarter} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-headquarter} POSTGRES_DB: ${POSTGRES_DB:-headquarter} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-headquarter} -d ${POSTGRES_DB:-headquarter}", ] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: - backend restart: unless-stopped # Redis Cache redis: image: redis:7-alpine container_name: hq-redis command: redis-server --appendonly yes volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 5s networks: - backend restart: unless-stopped # Web Frontend headquarter-frontend: build: context: ./apps/web dockerfile: Dockerfile args: VITE_API_BASE_URL: ${API_PUBLIC_URL:-https://${API_DOMAIN}} VITE_APP_URL: ${WEB_PUBLIC_URL:-https://${WEB_DOMAIN}} container_name: hq-web environment: VITE_API_BASE_URL: ${API_PUBLIC_URL:-https://${API_DOMAIN}} VITE_APP_URL: ${WEB_PUBLIC_URL:-https://${WEB_DOMAIN}} depends_on: - headquarter-api networks: - backend - traefik restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.headquarter-frontend.rule=Host(`${WEB_DOMAIN}`)" - "traefik.http.routers.headquarter-frontend.entrypoints=websecure" - "traefik.http.routers.headquarter-frontend.tls=true" - "traefik.http.routers.headquarter-frontend.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}" - "traefik.http.services.headquarter-frontend.loadbalancer.server.port=80" # API Service headquarter-api: build: context: ./apps/api dockerfile: Dockerfile container_name: hq-api environment: APP_ENV: production DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-headquarter}:${POSTGRES_PASSWORD:-headquarter}@postgres:5432/${POSTGRES_DB:-headquarter} POSTGRES_HOST: postgres POSTGRES_PORT: 5432 REDIS_URL: redis://redis:6379/0 SESSION_SECRET: ${SESSION_SECRET:-change-me-in-production} SESSION_TTL_HOURS: ${SESSION_TTL_HOURS:-24} REPO_BASE_PATH: /data/repos INSTANCE_BASE_PATH: /data/instances API_DOMAIN: ${API_DOMAIN} WEB_DOMAIN: ${WEB_DOMAIN} AUTHENTIK_DOMAIN: ${AUTHENTIK_DOMAIN} API_PUBLIC_URL: ${API_PUBLIC_URL:-} WEB_PUBLIC_URL: ${WEB_PUBLIC_URL:-} AUTHENTIK_CLIENT_ID: ${AUTHENTIK_CLIENT_ID:-headquarter-web} AUTHENTIK_CLIENT_SECRET: ${AUTHENTIK_CLIENT_SECRET} AUTHENTIK_APPLICATION_SLUG: ${AUTHENTIK_APPLICATION_SLUG:-headquarter-web} AUTHENTIK_AUTHORIZE_URL: ${AUTHENTIK_AUTHORIZE_URL:-} AUTHENTIK_TOKEN_URL: ${AUTHENTIK_TOKEN_URL:-} volumes: - /data/repos:/data/repos - /data/working-copies:/data/working-copies - /data/instances:/data/instances - avatar_uploads:/app/uploads - /var/run/docker.sock:/var/run/docker.sock depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - backend - traefik restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.headquarter-api.rule=Host(`${API_DOMAIN}`)" - "traefik.http.routers.headquarter-api.entrypoints=websecure" - "traefik.http.routers.headquarter-api.tls=true" - "traefik.http.routers.headquarter-api.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}" - "traefik.http.services.headquarter-api.loadbalancer.server.port=8000" volumes: postgres_data: redis_data: avatar_uploads: networks: backend: driver: bridge traefik: external: true name: ${TRAEFIK_NETWORK:-traefik}