# docker-compose.federated.yml — Federated tier overlay # # USAGE: # docker compose -f docker-compose.federated.yml --profile federated up -d # # This file is a standalone overlay for the Mosaic federated tier. # It is NOT an extension of docker-compose.yml — it defines its own services # and named volumes so it can run independently of the base dev stack. # # IMPORTANT — HOST PORT CONFLICTS: # The federated services bind the same host ports as the base dev stack # (5433 for Postgres, 6380 for Valkey). You must stop the base dev stack # before starting the federated stack on the same machine: # docker compose down # docker compose -f docker-compose.federated.yml --profile federated up -d # # pgvector extension: # The vector extension is created automatically at first boot via # ./infra/pg-init/01-extensions.sql (CREATE EXTENSION IF NOT EXISTS vector). # # Tier configuration: # Used by `mosaic` instances configured with `tier: federated`. # DEFAULT_FEDERATED_CONFIG points at: # postgresql://mosaic:mosaic@localhost:5433/mosaic services: postgres-federated: image: pgvector/pgvector:pg17 profiles: [federated] ports: - '${PG_FEDERATED_HOST_PORT:-5433}:5432' environment: POSTGRES_USER: mosaic POSTGRES_PASSWORD: mosaic POSTGRES_DB: mosaic volumes: - pg_federated_data:/var/lib/postgresql/data - ./infra/pg-init:/docker-entrypoint-initdb.d:ro healthcheck: test: ['CMD-SHELL', 'pg_isready -U mosaic'] interval: 5s timeout: 3s retries: 5 valkey-federated: image: valkey/valkey:8-alpine profiles: [federated] ports: - '${VALKEY_FEDERATED_HOST_PORT:-6380}:6379' volumes: - valkey_federated_data:/data healthcheck: test: ['CMD', 'valkey-cli', 'ping'] interval: 5s timeout: 3s retries: 5 # --------------------------------------------------------------------------- # Step-CA — Mosaic Federation internal certificate authority # # Image: pinned to 0.27.4 (latest stable as of late 2025). # `latest` is forbidden per Mosaic image policy (immutable tag required for # reproducible deployments and digest-first promotion in CI). # # Profile: `federated` — this service must not start in non-federated dev. # # Password: # Dev: bind-mount ./infra/step-ca/dev-password (gitignored; copy from # ./infra/step-ca/dev-password.example and customise locally). # Prod: replace the bind-mount with a Docker secret: # secrets: # ca_password: # external: true # and reference it as `/run/secrets/ca_password` (same path the # init script already uses). # # Provisioner: "mosaic-fed" (consumed by apps/gateway/src/federation/ca.service.ts) # --------------------------------------------------------------------------- step-ca: image: smallstep/step-ca:0.27.4 profiles: [federated] ports: - '${STEP_CA_HOST_PORT:-9000}:9000' volumes: - step_ca_data:/home/step # init script — executed as the container entrypoint - ./infra/step-ca/init.sh:/usr/local/bin/mosaic-step-ca-init.sh:ro # X.509 template skeleton (wired in M2-04) - ./infra/step-ca/templates:/etc/step-ca-templates:ro # Dev password file — GITIGNORED; copy from dev-password.example # In production, replace this with a Docker secret (see comment above). - ./infra/step-ca/dev-password:/run/secrets/ca_password:ro entrypoint: ['/bin/sh', '/usr/local/bin/mosaic-step-ca-init.sh'] healthcheck: # The healthcheck requires the root cert to exist, which is only true # after init.sh has completed on first boot. start_period gives init # time to finish before Docker starts counting retries. test: [ 'CMD', 'step', 'ca', 'health', '--ca-url', 'https://localhost:9000', '--root', '/home/step/certs/root_ca.crt', ] interval: 10s timeout: 5s retries: 5 start_period: 30s volumes: pg_federated_data: valkey_federated_data: step_ca_data: