Files
stack/deploy/portainer/README.md
jason.woltje 4dbd429203
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
feat(deploy): portainer stack template for federation test instances [DEPLOY-02] (#485)
2026-04-22 01:34:44 +00:00

4.1 KiB

deploy/portainer/

Portainer stack templates for Mosaic Stack deployments.

Files

File Purpose
federated-test.stack.yml Docker Swarm stack for federation end-to-end test instances (mos-test-1.woltje.com, mos-test-2.woltje.com)

federated-test.stack.yml

A self-contained Swarm stack that boots a federated-tier Mosaic gateway with co-located Postgres 17 (pgvector) and Valkey 8. This is a test template — production deployments will use a separate template with stricter resource limits and Docker secrets.

Deploy via Portainer UI

  1. Log into Portainer.
  2. Navigate to Stacks → Add stack.
  3. Set a stack name matching STACK_NAME below (e.g. mos-test-1).
  4. Choose Web editor and paste the contents of federated-test.stack.yml.
  5. Scroll to Environment variables and add each variable listed below.
  6. Click Deploy the stack.

Required environment variables

Variable Example Notes
STACK_NAME mos-test-1 Unique per stack — used in Traefik router/service names.
HOST_FQDN mos-test-1.woltje.com Fully-qualified hostname served by this stack.
POSTGRES_PASSWORD (generate randomly) Database password. Do not reuse between stacks.
BETTER_AUTH_SECRET (generate: openssl rand -base64 32) BetterAuth session signing key.
BETTER_AUTH_URL https://mos-test-1.woltje.com Public base URL of the gateway.

Optional variables (uncomment in the YAML or set in Portainer):

Variable Notes
ANTHROPIC_API_KEY Enable Claude models.
OPENAI_API_KEY Enable OpenAI models.
OTEL_EXPORTER_OTLP_ENDPOINT Forward traces to a collector (e.g. http://jaeger:4318).

Required external resources

Before deploying, ensure the following exist on the Swarm:

  1. traefik-public overlay network — shared network Traefik uses to route traffic to stacks.
    docker network create --driver overlay --attachable traefik-public
    
  2. letsencrypt cert resolver — configured in the Traefik Swarm stack. The stack template references tls.certresolver=letsencrypt; the name must match your Traefik config.
  3. DNS A record${HOST_FQDN} must resolve to the Swarm ingress IP (or a Cloudflare-proxied address pointing there).

Deployed instances

Stack name HOST_FQDN Purpose
mos-test-1 mos-test-1.woltje.com DEPLOY-03 — first federation peer
mos-test-2 mos-test-2.woltje.com DEPLOY-04 — second federation peer

Image

The gateway image is pinned by digest to fed-v0.1.0-m1 (verified in DEPLOY-01). Update the digest in the YAML when promoting a new build — never use :latest or a mutable tag in Swarm.

Notes

  • This template boots a vanilla M1-baseline gateway in federated tier. Federation grants (Step-CA, mTLS) are M2+ scope and not included here.
  • Each stack gets its own Postgres volume (postgres-data) and Valkey volume (valkey-data) scoped to the stack name by Swarm.
  • depends_on is honoured by Compose but ignored by Swarm — healthchecks on Postgres and Valkey ensure the gateway retries until they are ready.