xpeditis2.0/docker/portainer-stack.yml
David 890bc189ee
Some checks failed
CI/CD Pipeline - Xpeditis PreProd / Frontend - Build & Test (push) Failing after 5m31s
CI/CD Pipeline - Xpeditis PreProd / Frontend - Docker Build & Push (push) Has been skipped
CI/CD Pipeline - Xpeditis PreProd / Backend - Build & Test (push) Failing after 5m42s
CI/CD Pipeline - Xpeditis PreProd / Backend - Docker Build & Push (push) Has been skipped
CI/CD Pipeline - Xpeditis PreProd / Deploy to PreProd Server (push) Has been skipped
CI/CD Pipeline - Xpeditis PreProd / Run Smoke Tests (push) Has been skipped
fix v0.2
2025-11-12 18:00:33 +01:00

308 lines
11 KiB
YAML

version: '3.8'
services:
# PostgreSQL Database
xpeditis-db:
image: postgres:15-alpine
restart: unless-stopped
volumes:
- xpeditis_db_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: xpeditis_prod
POSTGRES_USER: xpeditis
POSTGRES_PASSWORD: xpeditis_prod_password_CHANGE_ME
PGDATA: /var/lib/postgresql/data/pgdata
networks:
- xpeditis_internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U xpeditis"]
interval: 10s
timeout: 5s
retries: 5
deploy:
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# Redis Cache
xpeditis-redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --requirepass xpeditis_redis_password_CHANGE_ME --appendonly yes
volumes:
- xpeditis_redis_data:/data
networks:
- xpeditis_internal
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 3s
retries: 5
deploy:
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# MinIO S3 Storage
xpeditis-minio:
image: minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
volumes:
- xpeditis_minio_data:/data
environment:
MINIO_ROOT_USER: minioadmin_CHANGE_ME
MINIO_ROOT_PASSWORD: minioadmin_password_CHANGE_ME
networks:
- xpeditis_internal
- traefik_network
labels:
# MinIO API
- "traefik.enable=true"
- "traefik.http.routers.xpeditis-minio-api.rule=Host(`s3.xpeditis.com`)"
- "traefik.http.routers.xpeditis-minio-api.entrypoints=websecure"
- "traefik.http.routers.xpeditis-minio-api.tls=true"
- "traefik.http.routers.xpeditis-minio-api.tls.certresolver=letsencrypt"
- "traefik.http.routers.xpeditis-minio-api.service=xpeditis-minio-api"
- "traefik.http.services.xpeditis-minio-api.loadbalancer.server.port=9000"
# MinIO Console
- "traefik.http.routers.xpeditis-minio-console.rule=Host(`minio.xpeditis.com`)"
- "traefik.http.routers.xpeditis-minio-console.entrypoints=websecure"
- "traefik.http.routers.xpeditis-minio-console.tls=true"
- "traefik.http.routers.xpeditis-minio-console.tls.certresolver=letsencrypt"
- "traefik.http.routers.xpeditis-minio-console.service=xpeditis-minio-console"
- "traefik.http.services.xpeditis-minio-console.loadbalancer.server.port=9001"
- "traefik.docker.network=traefik_network"
# HTTP to HTTPS redirect
- "traefik.http.routers.xpeditis-minio-http.rule=Host(`s3.xpeditis.com`) || Host(`minio.xpeditis.com`)"
- "traefik.http.routers.xpeditis-minio-http.entrypoints=web"
- "traefik.http.routers.xpeditis-minio-http.middlewares=xpeditis-redirect"
- "traefik.http.middlewares.xpeditis-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.xpeditis-redirect.redirectscheme.permanent=true"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
deploy:
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
# Backend API (NestJS)
xpeditis-backend:
image: xpeditis/backend:latest
restart: unless-stopped
environment:
# Node Environment
NODE_ENV: production
PORT: 4000
# Database
DATABASE_HOST: xpeditis-db
DATABASE_PORT: 5432
DATABASE_USER: xpeditis
DATABASE_PASSWORD: xpeditis_prod_password_CHANGE_ME
DATABASE_NAME: xpeditis_prod
DATABASE_SSL: "false"
DATABASE_SYNC: "false"
DATABASE_LOGGING: "false"
# Redis
REDIS_HOST: xpeditis-redis
REDIS_PORT: 6379
REDIS_PASSWORD: xpeditis_redis_password_CHANGE_ME
REDIS_TTL: 900
# JWT
JWT_SECRET: your-super-secret-jwt-key-CHANGE_ME-min-32-characters
JWT_ACCESS_EXPIRATION: 15m
JWT_REFRESH_EXPIRATION: 7d
# S3/MinIO
AWS_S3_ENDPOINT: http://xpeditis-minio:9000
AWS_REGION: us-east-1
AWS_ACCESS_KEY_ID: minioadmin_CHANGE_ME
AWS_SECRET_ACCESS_KEY: minioadmin_password_CHANGE_ME
AWS_S3_BUCKET: xpeditis-documents
AWS_S3_FORCE_PATH_STYLE: "true"
# CORS
CORS_ORIGIN: https://app.xpeditis.com,https://www.xpeditis.com
# Rate Limiting
RATE_LIMIT_TTL: 60
RATE_LIMIT_MAX: 100
# Email (Placeholder - configure based on your email provider)
EMAIL_HOST: smtp.example.com
EMAIL_PORT: 587
EMAIL_USER: noreply@xpeditis.com
EMAIL_PASSWORD: email_password_CHANGE_ME
EMAIL_FROM: "Xpeditis <noreply@xpeditis.com>"
# Sentry (Optional - for error tracking)
SENTRY_DSN: ""
SENTRY_ENVIRONMENT: production
SENTRY_TRACES_SAMPLE_RATE: 0.1
# App URLs
FRONTEND_URL: https://app.xpeditis.com
API_URL: https://api.xpeditis.com
networks:
- xpeditis_internal
- traefik_network
labels:
- "traefik.enable=true"
# API Routes
- "traefik.http.routers.xpeditis-api.rule=Host(`api.xpeditis.com`)"
- "traefik.http.routers.xpeditis-api.entrypoints=websecure"
- "traefik.http.routers.xpeditis-api.tls=true"
- "traefik.http.routers.xpeditis-api.tls.certresolver=letsencrypt"
- "traefik.http.routers.xpeditis-api.priority=100"
- "traefik.http.services.xpeditis-api.loadbalancer.server.port=4000"
- "traefik.http.routers.xpeditis-api.middlewares=xpeditis-api-headers,xpeditis-api-ratelimit"
- "traefik.docker.network=traefik_network"
# Middleware Headers
- "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Forwarded-For="
- "traefik.http.middlewares.xpeditis-api-headers.headers.customRequestHeaders.X-Real-IP="
- "traefik.http.middlewares.xpeditis-api-headers.headers.accessControlAllowOriginList=https://app.xpeditis.com,https://www.xpeditis.com"
- "traefik.http.middlewares.xpeditis-api-headers.headers.accessControlAllowMethods=GET,POST,PUT,PATCH,DELETE,OPTIONS"
- "traefik.http.middlewares.xpeditis-api-headers.headers.accessControlAllowHeaders=*"
- "traefik.http.middlewares.xpeditis-api-headers.headers.accessControlMaxAge=3600"
# Rate Limiting
- "traefik.http.middlewares.xpeditis-api-ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.xpeditis-api-ratelimit.ratelimit.burst=200"
- "traefik.http.middlewares.xpeditis-api-ratelimit.ratelimit.period=1m"
# HTTP to HTTPS redirect
- "traefik.http.routers.xpeditis-api-http.rule=Host(`api.xpeditis.com`)"
- "traefik.http.routers.xpeditis-api-http.entrypoints=web"
- "traefik.http.routers.xpeditis-api-http.priority=100"
- "traefik.http.routers.xpeditis-api-http.middlewares=xpeditis-redirect"
- "traefik.http.routers.xpeditis-api-http.service=xpeditis-api"
depends_on:
- xpeditis-db
- xpeditis-redis
- xpeditis-minio
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:4000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
replicas: 2
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
# Frontend (Next.js)
xpeditis-frontend:
image: xpeditis/frontend:latest
restart: unless-stopped
environment:
NODE_ENV: production
NEXT_PUBLIC_API_URL: https://api.xpeditis.com
NEXT_PUBLIC_WS_URL: wss://api.xpeditis.com
networks:
- traefik_network
labels:
- "traefik.enable=true"
# Frontend Routes
- "traefik.http.routers.xpeditis-app.rule=Host(`app.xpeditis.com`) || Host(`www.xpeditis.com`)"
- "traefik.http.routers.xpeditis-app.entrypoints=websecure"
- "traefik.http.routers.xpeditis-app.tls=true"
- "traefik.http.routers.xpeditis-app.tls.certresolver=letsencrypt"
- "traefik.http.routers.xpeditis-app.priority=50"
- "traefik.http.services.xpeditis-app.loadbalancer.server.port=3000"
- "traefik.http.routers.xpeditis-app.middlewares=xpeditis-app-headers"
- "traefik.docker.network=traefik_network"
# Middleware Headers
- "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Forwarded-For="
- "traefik.http.middlewares.xpeditis-app-headers.headers.customRequestHeaders.X-Real-IP="
# Security Headers
- "traefik.http.middlewares.xpeditis-app-headers.headers.stsSeconds=31536000"
- "traefik.http.middlewares.xpeditis-app-headers.headers.stsIncludeSubdomains=true"
- "traefik.http.middlewares.xpeditis-app-headers.headers.stsPreload=true"
- "traefik.http.middlewares.xpeditis-app-headers.headers.forceSTSHeader=true"
- "traefik.http.middlewares.xpeditis-app-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.xpeditis-app-headers.headers.browserXssFilter=true"
# HTTP to HTTPS redirect
- "traefik.http.routers.xpeditis-app-http.rule=Host(`app.xpeditis.com`) || Host(`www.xpeditis.com`)"
- "traefik.http.routers.xpeditis-app-http.entrypoints=web"
- "traefik.http.routers.xpeditis-app-http.priority=50"
- "traefik.http.routers.xpeditis-app-http.middlewares=xpeditis-redirect"
- "traefik.http.routers.xpeditis-app-http.service=xpeditis-app"
depends_on:
- xpeditis-backend
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
deploy:
replicas: 2
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
volumes:
xpeditis_db_data:
driver: local
xpeditis_redis_data:
driver: local
xpeditis_minio_data:
driver: local
networks:
traefik_network:
external: true
xpeditis_internal:
driver: overlay
internal: true