2025-07-23 23:06:15 -05:00
|
|
|
# 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
|
2026-02-19 16:52:55 -08:00
|
|
|
DOMAIN_CLIENT: https://hanzo.chat
|
|
|
|
|
DOMAIN_SERVER: https://hanzo.chat
|
2025-07-23 23:06:15 -05:00
|
|
|
ALLOW_REGISTRATION: ${ALLOW_REGISTRATION:-false}
|
2026-02-19 16:52:55 -08:00
|
|
|
|
|
|
|
|
# All AI requests go through Hanzo API gateway
|
2025-07-23 23:06:15 -05:00
|
|
|
OPENAI_BASE_URL: https://api.hanzo.ai/v1
|
2026-02-19 16:52:55 -08:00
|
|
|
|
2025-07-23 23:06:15 -05:00
|
|
|
# Production secrets (use real values)
|
|
|
|
|
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
|
2026-02-19 16:52:55 -08:00
|
|
|
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:?JWT_REFRESH_SECRET is required}
|
2025-07-23 23:06:15 -05:00
|
|
|
OPENAI_API_KEY: ${OPENAI_API_KEY:?OPENAI_API_KEY is required}
|
2026-02-19 16:52:55 -08:00
|
|
|
|
|
|
|
|
# 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
|
2026-06-23 13:11:39 -07:00
|
|
|
OPENID_IMAGE_URL: https://hanzo.chat/assets/logo.svg
|
2026-02-19 16:52:55 -08:00
|
|
|
OPENID_USERNAME_CLAIM: name
|
|
|
|
|
OPENID_NAME_CLAIM: name
|
|
|
|
|
OPENID_USE_PKCE: "true"
|
2025-07-23 23:06:15 -05:00
|
|
|
labels:
|
|
|
|
|
# Traefik routing
|
|
|
|
|
- "traefik.enable=true"
|
|
|
|
|
- "traefik.docker.network=traefik"
|
|
|
|
|
|
|
|
|
|
# HTTPS router
|
2026-03-10 16:14:27 -07:00
|
|
|
- "traefik.http.routers.hanzo-chat.rule=Host(`hanzo.chat`) || Host(`chat.hanzo.ai`)"
|
2025-07-23 23:06:15 -05:00
|
|
|
- "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
|