# --------------------------------------------------------------------------- # A single env‑file (.env) contains ONLY non‑secret constants. # Every secret is exported from fetch‑secrets.sh and injected at deploy time. # --------------------------------------------------------------------------- x-env: &with-env restart: unless-stopped services: dek-init: image: busybox:1.36 user: "0:0" command: sh -lc 'mkdir -p /run/secrets/dev && chown -R 1000:1000 /run/secrets' volumes: - dek-vol:/run/secrets/dev restart: "no" # ───────────────────────────── server1 ───────────────────────────── server1: <<: *with-env depends_on: [dek-init] image: us-central1-docker.pkg.dev/aptivaai-dev/aptiva-repo/server1:${IMG_TAG} user: "1000:1000" read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL expose: ["${SERVER1_PORT}"] environment: ENV_NAME: ${ENV_NAME} APTIVA_API_BASE: ${APTIVA_API_BASE} PROJECT: ${PROJECT} KMS_KEY_NAME: ${KMS_KEY_NAME} DEK_PATH: ${DEK_PATH} JWT_SECRET: ${JWT_SECRET} DB_HOST: ${DB_HOST} DB_PORT: ${DB_PORT} DB_USER: ${DB_USER} DB_PASSWORD: ${DB_PASSWORD} DB_NAME: ${DB_NAME} DB_SSL_CERT: ${DB_SSL_CERT} DB_SSL_KEY: ${DB_SSL_KEY} DB_SSL_CA: ${DB_SSL_CA} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS} SUPPORT_SENDGRID_API_KEY: ${SUPPORT_SENDGRID_API_KEY} EMAIL_INDEX_SECRET: ${EMAIL_INDEX_SECRET} SALARY_DB_PATH: /app/salary_info.db FROM_SECRETS_MANAGER: ${FROM_SECRETS_MANAGER} volumes: - ./salary_info.db:/app/salary_info.db:ro - ./user_profile.db:/app/user_profile.db - dek-vol:/run/secrets/dev:rw healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:${SERVER1_PORT}/livez || exit 1"] interval: 15s timeout: 5s retries: 5 start_period: 25s # ───────────────────────────── server2 ───────────────────────────── server2: depends_on: [dek-init] <<: *with-env image: us-central1-docker.pkg.dev/aptivaai-dev/aptiva-repo/server2:${IMG_TAG} user: "1000:1000" read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL expose: ["${SERVER2_PORT}"] environment: ENV_NAME: ${ENV_NAME} PROJECT: ${PROJECT} KMS_KEY_NAME: ${KMS_KEY_NAME} DEK_PATH: ${DEK_PATH} GOOGLE_MAPS_API_KEY: ${GOOGLE_MAPS_API_KEY} ONET_USERNAME: ${ONET_USERNAME} ONET_PASSWORD: ${ONET_PASSWORD} JWT_SECRET: ${JWT_SECRET} OPENAI_API_KEY: ${OPENAI_API_KEY} DB_HOST: ${DB_HOST} DB_PORT: ${DB_PORT} DB_USER: ${DB_USER} DB_PASSWORD: ${DB_PASSWORD} DB_NAME: ${DB_NAME} DB_SSL_CERT: ${DB_SSL_CERT} DB_SSL_KEY: ${DB_SSL_KEY} DB_SSL_CA: ${DB_SSL_CA} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS} SUPPORT_SENDGRID_API_KEY: ${SUPPORT_SENDGRID_API_KEY} EMAIL_INDEX_SECRET: ${EMAIL_INDEX_SECRET} SALARY_DB_PATH: /app/salary_info.db FROM_SECRETS_MANAGER: ${FROM_SECRETS_MANAGER} volumes: - ./public:/app/public:ro - ./salary_info.db:/app/salary_info.db:ro - ./user_profile.db:/app/user_profile.db - dek-vol:/run/secrets/dev:ro healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:${SERVER2_PORT}/livez || exit 1"] interval: 15s timeout: 5s retries: 5 start_period: 25s # ───────────────────────────── server3 ───────────────────────────── server3: depends_on: [dek-init] <<: *with-env image: us-central1-docker.pkg.dev/aptivaai-dev/aptiva-repo/server3:${IMG_TAG} user: "1000:1000" read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL expose: ["${SERVER3_PORT}"] environment: ENV_NAME: ${ENV_NAME} PROJECT: ${PROJECT} KMS_KEY_NAME: ${KMS_KEY_NAME} DEK_PATH: ${DEK_PATH} JWT_SECRET: ${JWT_SECRET} OPENAI_API_KEY: ${OPENAI_API_KEY} STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY} STRIPE_PUBLISHABLE_KEY: ${STRIPE_PUBLISHABLE_KEY} STRIPE_WH_SECRET: ${STRIPE_WH_SECRET} STRIPE_PRICE_PREMIUM_MONTH: ${STRIPE_PRICE_PREMIUM_MONTH} STRIPE_PRICE_PREMIUM_YEAR: ${STRIPE_PRICE_PREMIUM_YEAR} STRIPE_PRICE_PRO_MONTH: ${STRIPE_PRICE_PRO_MONTH} STRIPE_PRICE_PRO_YEAR: ${STRIPE_PRICE_PRO_YEAR} TWILIO_ACCOUNT_SID: ${TWILIO_ACCOUNT_SID} TWILIO_AUTH_TOKEN: ${TWILIO_AUTH_TOKEN} TWILIO_MESSAGING_SERVICE_SID: ${TWILIO_MESSAGING_SERVICE_SID} DB_HOST: ${DB_HOST} DB_PORT: ${DB_PORT} DB_USER: ${DB_USER} DB_PASSWORD: ${DB_PASSWORD} DB_NAME: ${DB_NAME} DB_SSL_CERT: ${DB_SSL_CERT} DB_SSL_KEY: ${DB_SSL_KEY} DB_SSL_CA: ${DB_SSL_CA} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS} SUPPORT_SENDGRID_API_KEY: ${SUPPORT_SENDGRID_API_KEY} SALARY_DB_PATH: /app/salary_info.db FROM_SECRETS_MANAGER: ${FROM_SECRETS_MANAGER} volumes: - ./salary_info.db:/app/salary_info.db:ro - ./user_profile.db:/app/user_profile.db - dek-vol:/run/secrets/dev:ro - aptiva_uploads:/data/uploads healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:${SERVER3_PORT}/livez || exit 1"] interval: 15s timeout: 5s retries: 5 start_period: 25s # ───────────────────────────── nginx ─────────────────────────────── nginx: <<: *with-env image: us-central1-docker.pkg.dev/aptivaai-dev/aptiva-repo/nginx:${IMG_TAG} command: ["nginx", "-g", "daemon off;"] depends_on: [server1, server2, server3] networks: [default, aptiva-shared] environment: GOOGLE_MAPS_API_KEY: ${GOOGLE_MAPS_API_KEY} ports: ["80:80", "443:443"] volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - /etc/letsencrypt:/etc/letsencrypt:ro - ./empty:/etc/nginx/conf.d networks: default: name: aptiva_default aptiva-shared: external: true volumes: dek-vol: name: aptiva_dek_dev driver: local aptiva_uploads: