Production overview

Production runs on Docker Compose, on one Linux server. Aspire is for development only: the services read ordinary configuration and do not need it. Everything lives in deploy/, and deploy/README.md is the complete guide; these pages are its map.

Server — docker compose

app.example.com

identity.example.com

api.example.com

before the hosts

Browser · MCP clients · Stripe

Caddy
TLS, Let's Encrypt

Sign-in

Scripts with a personal access token

Gateway

Identity host

API

SPA · nginx

PostgreSQL

RabbitMQ

Redis

Migration runner

Server — docker compose

app.example.com

identity.example.com

api.example.com

before the hosts

Browser · MCP clients · Stripe

Caddy
TLS, Let's Encrypt

Sign-in

Scripts with a personal access token

Gateway

Identity host

API

SPA · nginx

PostgreSQL

RabbitMQ

Redis

Migration runner

  • Caddy is the only container with published ports. It terminates TLS for three host names, gets and renews their certificates from Let's Encrypt and forwards the client's address.
  • The gateway, the identity host and the API listen on plain HTTP inside the network, and call each other at their public https:// names.
  • The migration runner applies every migration on each docker compose up, and the hosts start only once it has exited successfully.
  • PostgreSQL, RabbitMQ and Redis are not published.
Host nameServes
app.example.comThe gateway: the application and its API calls, /mcp, /scim/v2, Stripe's webhook
identity.example.comThe identity host: sign-in and the account pages
api.example.comThe API, for scripts and agents with a personal access token

The landing page and the documentation site are static: deploy them to any static host, or add them to the compose file (see Operate).

Try it on your machine first

The same images, in the same Production environment, on *.localhost — certificates from a local authority, e-mail caught by MailPit, the sample users seeded:

cd deploy
cp local/local.env.example .env
./local/make-ca.sh
docker compose -f docker-compose.yml -f docker-compose.local.yml up -d --build

Import local/ca/root.crt into your browser's trusted authorities, open https://app.localhost and sign in as J0hnd0e / Password123!.

The server

  • A Linux VPS with 2 vCPU and 4 GB of RAM at least (8 GB is comfortable), amd64 or arm64, and 20 GB of disk plus your data.
  • Docker Engine with the Compose plugin.
  • Ports 80 and 443 open (and 443/udp for HTTP/3) — nothing else.
  • Three DNS records pointing at the server, created before the first start: Caddy asks for the certificates straight away.

Next: configure it.