# Hanzo AI Chat - Production Override # Use with: docker compose -f compose.yml -f compose.prod.yml up -d # Requires Traefik reverse proxy running services: # Production chat configuration chat: image: hanzoai/chat:${VERSION:-latest} container_name: hanzo-chat-prod restart: unless-stopped ports: [] # No direct port exposure in production environment: # Production settings NODE_ENV: production DOMAIN_CLIENT: https://hanzo.chat DOMAIN_SERVER: https://hanzo.chat ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-false} # All AI requests go through Hanzo API gateway OPENAI_BASE_URL: https://api.hanzo.ai/v1 # Production secrets (use real values) JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required} JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:?JWT_REFRESH_SECRET is required} OPENAI_API_KEY: ${OPENAI_API_KEY:?OPENAI_API_KEY is required} # Hanzo IAM OpenID Connect OPENID_CLIENT_ID: ${OPENID_CLIENT_ID:?OPENID_CLIENT_ID is required} OPENID_CLIENT_SECRET: ${OPENID_CLIENT_SECRET:?OPENID_CLIENT_SECRET is required} OPENID_ISSUER: https://hanzo.id OPENID_SESSION_SECRET: ${OPENID_SESSION_SECRET:?OPENID_SESSION_SECRET is required} OPENID_SCOPE: openid profile email OPENID_CALLBACK_URL: /oauth/openid/callback OPENID_BUTTON_LABEL: Log in with Hanzo OPENID_IMAGE_URL: https://hanzo.chat/assets/logo.svg OPENID_USERNAME_CLAIM: name OPENID_NAME_CLAIM: name OPENID_USE_PKCE: "true" labels: # Traefik routing - "traefik.enable=true" - "traefik.docker.network=traefik" # HTTPS router - "traefik.http.routers.hanzo-chat.rule=Host(`hanzo.chat`) || Host(`chat.hanzo.ai`)" - "traefik.http.routers.hanzo-chat.entrypoints=websecure" - "traefik.http.routers.hanzo-chat.tls=true" - "traefik.http.routers.hanzo-chat.tls.certresolver=letsencrypt" # Service - "traefik.http.services.hanzo-chat.loadbalancer.server.port=3080" # Security headers - "traefik.http.middlewares.hanzo-chat-headers.headers.stsSeconds=31536000" - "traefik.http.middlewares.hanzo-chat-headers.headers.stsIncludeSubdomains=true" - "traefik.http.middlewares.hanzo-chat-headers.headers.stsPreload=true" - "traefik.http.middlewares.hanzo-chat-headers.headers.contentTypeNosniff=true" - "traefik.http.middlewares.hanzo-chat-headers.headers.browserXssFilter=true" - "traefik.http.middlewares.hanzo-chat-headers.headers.referrerPolicy=strict-origin-when-cross-origin" - "traefik.http.middlewares.hanzo-chat-headers.headers.customFrameOptionsValue=SAMEORIGIN" # Apply middlewares - "traefik.http.routers.hanzo-chat.middlewares=hanzo-chat-headers" networks: - hanzo-network - traefik deploy: resources: limits: cpus: '2' memory: 2G reservations: cpus: '0.5' memory: 512M # MongoDB production settings mongodb: restart: unless-stopped volumes: - mongodb_data:/data/db - mongodb_backup:/backup environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_USERNAME:?MONGO_USERNAME is required} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:?MONGO_PASSWORD is required} deploy: resources: limits: cpus: '1' memory: 1G # Meilisearch production settings meilisearch: restart: unless-stopped environment: MEILI_ENV: production MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:?MEILI_MASTER_KEY is required} deploy: resources: limits: cpus: '1' memory: 1G # Optional: MongoDB backup service mongodb-backup: image: hanzoai/mongodb-backup:latest container_name: hanzo-mongodb-backup restart: unless-stopped environment: MONGO_URI: mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@mongodb:27017/HanzoChat?authSource=admin BACKUP_SCHEDULE: "0 2 * * *" # Daily at 2 AM BACKUP_RETENTION_DAYS: 7 S3_BUCKET: ${BACKUP_S3_BUCKET:-} AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-} volumes: - mongodb_backup:/backup depends_on: - mongodb networks: - hanzo-network profiles: - with-backup volumes: mongodb_backup: networks: traefik: external: true