# Cloud / Central layer composition. # Pulls in every stack that runs on the central hub and adds cross-stack # dependencies (the per-stack composes stay standalone-runnable). # # Fresh-deploy procedure (see ../docs/architecture.md for the long version): # 1. cp .env.example .env && fill secrets # 2. Set DNS A records for the 10 short subdomains + vpn.wbd-rd.nl # 3. docker compose up -d # - nginx-init creates a self-signed bootstrap cert # - sql comes up, init.d/01-databases.sh provisions per-app DBs # - keycloak / gitea / mlflow wait on sql healthcheck before starting # 4. ./deploy.sh — single command. Brings everything up, runs first-time cert # issuance via certbot HTTP-01 (SAN over all *.wbd-rd.nl), reloads nginx, # smoke-tests every vhost. Idempotent; safe to rerun. # 5. Flip ACME_CA_URI from staging → prod in .env, ./deploy.sh again. name: cloud include: # Foundation — ingress, DB, ops console - ../stacks/nginx-proxy/compose.yml - ../stacks/sql/compose.yml - ../stacks/portainer/compose.yml # Identity + VPN - ../stacks/keycloak/compose.yml - ../stacks/oauth2-proxy/compose.yml - ../stacks/wireguard-server/compose.yml # Data - ../stacks/influxdb/compose.yml # Apps - ../stacks/node-red/compose.yml - ../stacks/grafana/compose.yml - ../stacks/gitea/compose.yml - ../stacks/jenkins/compose.yml # Messaging + mail - ../stacks/rabbitmq/compose.yml - ../stacks/postfix/compose.yml # ML / notebooks - ../stacks/mlflow/compose.yml - ../stacks/jupyterhub/compose.yml # SensorThings - ../stacks/frost/compose.yml # Cross-stack dependencies. Declared at the cloud level so each stack's # own compose.yml stays standalone-runnable (no required peers). services: keycloak: depends_on: sql: condition: service_healthy gitea: depends_on: sql: condition: service_healthy mlflow: depends_on: sql: condition: service_healthy networks: edge: name: cloud-edge driver: bridge app: name: cloud-app driver: bridge data: name: cloud-data driver: bridge internal: true # databases — no internet egress mgmt: name: cloud-mgmt driver: bridge