Files
stack/docker-compose.federated.yml
Jarvis d1925149c6
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
feat(federation): add Step-CA sidecar to federated compose stack [FED-M2-02]
Adds a profile-gated `step-ca` service to `docker-compose.federated.yml`
so the federated tier has its own internal CA. No gateway code consumes
the CA yet — that lands in M2-04 (ca.service.ts).

- docker-compose.federated.yml: new `step-ca` service using image
  `smallstep/step-ca:0.27.4` (pinned stable; `latest` forbidden by
  Mosaic image policy), named volume `step_ca_data`, port 9000,
  `[federated]` profile gate, healthcheck with 30s start_period
- infra/step-ca/init.sh: idempotent first-boot init; runs `step ca init`
  with JWK provisioner `mosaic-fed` if /home/step/config/ca.json absent;
  otherwise starts CA directly
- infra/step-ca/dev-password.example: sample dev password (real file
  is gitignored)
- infra/step-ca/templates/federation.tpl: X.509 template skeleton for
  custom OID SAN extensions (grantId 1.3.6.1.4.1.99999.1,
  subjectUserId 1.3.6.1.4.1.99999.2); TODO comment links M2-04 as the
  landing point
- .gitignore: ignores infra/step-ca/dev-password (real password)

Refs #461

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 21:00:05 -05:00

118 lines
4.1 KiB
YAML

# 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: