Match the short-functional naming convention used by the other vhosts (git, auth, dash, flow, ml, hub, ops, mq, ci, mqtt). FROST implements OGC SensorThings API, so `sta` is the natural fit. portainer.wbd-rd.nl is dropped from deploy.sh HOSTS — there is no nginx vhost for it; portainer is already served via ops.wbd-rd.nl. DNS prereq for first deploy is now: create one new A record for sta.wbd-rd.nl → cloud public IP. All other short subdomains already point correctly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cloud
The single central hub. One deployment, internet-facing.
What runs here
nginx-proxy, wireguard-server, keycloak, portainer, influxdb, grafana, node-red, mqtt, postfix, gitea, jenkins, sql.
See ../docs/architecture.md for the full network topology and ingress table.
Run
cp .env.example .env # fill in real secrets first
./deploy.sh # one-shot bring-up: containers + cert + smoke test
deploy.sh is idempotent — rerun any time. It will:
- Preflight — check
.envhas all required vars - Validate
docker compose config - Bring up containers, wait for
sqlhealthcheck, wait for nginx :80 - Inspect cert — figure out whether the current cert is self-signed, staging, or prod
- Issue / renew the SAN cert via certbot only when needed (initial issuance, or when
ACME_CA_URIno longer matches the current issuer); reload nginx - Status — show
docker compose ps - Smoke test every
*.wbd-rd.nlvhost over loopback
The script reissues the cert only when the CA in .env changes (e.g. staging → prod) or when only the bootstrap dummy is present — it does not waste Let's Encrypt rate limits on repeated runs.
Staging → prod flip
- Verify everything works with the staging cert (browser will warn — that's normal)
- Edit
.env: changeACME_CA_URItohttps://acme-v02.api.letsencrypt.org/directory ./deploy.sh— script detects the CA change and force-renews against prod
Ingress (host port bindings)
| Port | Container |
|---|---|
| tcp/80, 443 | nginx-proxy |
| tcp/8883 | nginx-proxy (MQTT-TLS via stream block) |
| udp/51820 | wireguard-server |
Everything else stays on the internal app / data / mgmt networks.
Adding a new stack
- Create
stacks/<name>/withcompose.yml,.env.example,README.md. - Uncomment (or add) the
include:entry incompose.yml. - Add the stack's env vars to
.env.example. docker compose pull && docker compose up -d.