services:
  gateway:
    image: caddy:2.10-alpine
    restart: unless-stopped
    init: true
    read_only: true
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp
    environment:
      PUBLIC_DOMAIN: ${PUBLIC_DOMAIN:?set PUBLIC_DOMAIN}
      TLS_EMAIL: ${TLS_EMAIL:?set TLS_EMAIL}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    depends_on:
      frontend:
        condition: service_healthy
      auth:
        condition: service_healthy
      api:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O - --header=\"Host: $$PUBLIC_DOMAIN\" http://127.0.0.1/ >/dev/null"]
      interval: 15s
      timeout: 5s
      retries: 20
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  frontend:
    build:
      context: ..
      dockerfile: apps/frontend/Dockerfile
      args:
        VITE_FRONTEND_URL: ${PUBLIC_URL:?set PUBLIC_URL}
        VITE_AUTH_URL: ${PUBLIC_URL:?set PUBLIC_URL}
        VITE_API_URL: ${PUBLIC_URL:?set PUBLIC_URL}
        VITE_DEV_MAILBOX_ENABLED: "false"
    image: productier/frontend:latest
    restart: unless-stopped
    init: true
    read_only: true
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp
    environment:
      NODE_ENV: production
      PORT: 3000
    depends_on:
      auth:
        condition: service_healthy
      api:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:3000"]
      interval: 15s
      timeout: 5s
      retries: 20
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  auth:
    build:
      context: ../apps/backend/auth-service
      dockerfile: Dockerfile
    image: productier/auth-service:latest
    restart: unless-stopped
    init: true
    read_only: true
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp
    environment:
      APP_ENV: production
      NODE_ENV: production
      AUTH_PORT: 3001
      FRONTEND_URL: ${PUBLIC_URL:?set PUBLIC_URL}
      AUTH_URL: ${PUBLIC_URL:?set PUBLIC_URL}
      DATABASE_URL: postgres://productier:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/productier?sslmode=disable
      BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?set BETTER_AUTH_SECRET}
      CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:?set CORS_ALLOW_ORIGINS}
      AUTH_MAGIC_LINK_PROVIDER: ${AUTH_MAGIC_LINK_PROVIDER:-smtp}
      AUTH_MAIL_FROM: ${AUTH_MAIL_FROM:?set AUTH_MAIL_FROM}
      AUTH_SMTP_HOST: ${AUTH_SMTP_HOST:?set AUTH_SMTP_HOST}
      AUTH_SMTP_PORT: ${AUTH_SMTP_PORT:-587}
      AUTH_SMTP_SECURE: ${AUTH_SMTP_SECURE:-false}
      AUTH_SMTP_USER: ${AUTH_SMTP_USER:?set AUTH_SMTP_USER}
      AUTH_SMTP_PASSWORD: ${AUTH_SMTP_PASSWORD:?set AUTH_SMTP_PASSWORD}
      AUTH_DEV_MAILBOX_ENABLED: "false"
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:3001/health"]
      interval: 15s
      timeout: 5s
      retries: 20
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  api:
    build:
      context: ../apps/backend
      dockerfile: Dockerfile
    image: productier/api:latest
    restart: unless-stopped
    init: true
    read_only: true
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp
    environment:
      APP_ENV: production
      API_PORT: 8080
      API_SHUTDOWN_TIMEOUT: 15s
      DATABASE_URL: postgres://productier:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/productier?sslmode=disable
      AUTH_SERVICE_URL: http://auth:3001
      CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:?set CORS_ALLOW_ORIGINS}
      BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?set BETTER_AUTH_SECRET}
      MAIL_ENCRYPTION_KEY: ${MAIL_ENCRYPTION_KEY:?set MAIL_ENCRYPTION_KEY}
      FILE_STORAGE_PROVIDER: s3
      S3_ENDPOINT: http://rustfs:9000
      S3_REGION: ${S3_REGION:-us-east-1}
      S3_BUCKET: ${S3_BUCKET:-productier}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:?set S3_ACCESS_KEY}
      S3_SECRET_KEY: ${S3_SECRET_KEY:?set S3_SECRET_KEY}
      S3_USE_PATH_STYLE: "true"
      DB_MIGRATIONS_DIR: /app/migrations
    depends_on:
      postgres:
        condition: service_healthy
      auth:
        condition: service_healthy
      rustfs:
        condition: service_healthy
      rustfs-init:
        condition: service_completed_successfully
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://127.0.0.1:8080/v1/health"]
      interval: 15s
      timeout: 5s
      retries: 20
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    init: true
    security_opt:
      - no-new-privileges:true
    environment:
      POSTGRES_DB: productier
      POSTGRES_USER: productier
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U productier -d productier"]
      interval: 10s
      timeout: 5s
      retries: 20
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  rustfs:
    image: rustfs/rustfs@sha256:0725587f6fcca83c1898f321424327d6e6da5e01ea20382905dd258ed5af3be4
    restart: unless-stopped
    init: true
    security_opt:
      - no-new-privileges:true
    environment:
      RUSTFS_VOLUMES: /data/rustfs
      RUSTFS_ADDRESS: 0.0.0.0:9000
      RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001
      RUSTFS_CONSOLE_ENABLE: "true"
      RUSTFS_ACCESS_KEY: ${S3_ACCESS_KEY:?set S3_ACCESS_KEY}
      RUSTFS_SECRET_KEY: ${S3_SECRET_KEY:?set S3_SECRET_KEY}
    volumes:
      - rustfs-data:/data
    healthcheck:
      test: ["CMD", "sh", "-c", "wget -q -O - http://127.0.0.1:9000/health >/dev/null"]
      interval: 15s
      timeout: 5s
      retries: 20
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

  rustfs-init:
    image: amazon/aws-cli:2.27.42
    restart: "no"
    depends_on:
      rustfs:
        condition: service_healthy
    environment:
      AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY:?set S3_ACCESS_KEY}
      AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY:?set S3_SECRET_KEY}
      AWS_DEFAULT_REGION: ${S3_REGION:-us-east-1}
    entrypoint:
      - /bin/sh
      - -lc
      - |
        set -eu
        endpoint="http://rustfs:9000"
        until aws --endpoint-url "$${endpoint}" s3api list-buckets >/dev/null 2>&1; do
          sleep 1
        done
        aws --endpoint-url "$${endpoint}" s3api head-bucket --bucket ${S3_BUCKET:-productier} >/dev/null 2>&1 || \
          aws --endpoint-url "$${endpoint}" s3api create-bucket --bucket ${S3_BUCKET:-productier}

volumes:
  caddy-data:
  caddy-config:
  postgres-data:
  rustfs-data:
