Demo host runbook (demo.umbraculum.dev)
Tier: Public
Status: Operator runbook — LIVE on Contabo VPS 84.247.163.121 since 2026-06-03; HTTPS via Traefik v3.6 + Let's Encrypt
Audience: maintainers standing up or resetting the public demo stack (not production cloud)
Resume point: Native EAS demo work can resume — see
native-eas-demo-build-log.md§"Where we are".
[!IMPORTANT]
demo.umbraculum.devis a demonstration environment only.
Seed data (recipes, brew sessions, E2E fixtures) exists to build and show Umbraculum—not as a production brewery ledger inside this repository. The database may be wiped or re-seeded without notice. There is no SLA, no backup promise, and no multi-tenant production posture.Infrastructure custody (bootstrap). At Phase 0 the demo host may run on maintainer-operated provisional VPS infrastructure (personal billing account). When the community votes for entity-owned hosting (
CORE-DEVELOPMENT-AND-COMMUNITY.md§4.6.7;LICENSING.md§7.6), migration is redeploy + restore on a new VPS + DNS cutover — not transfer of the existing VPS subscription or provider account between legal entities.Future customer-facing hosted product is tracked separately at
cloud-hosted-product-track.md(cloud.umbraculum.dev) — not this host.
What runs on the demo host
Single HTTPS origin (Traefik → internal nginx) serving:
| Path | Backend |
|---|---|
/api/** | services/api |
/{locale}/** | apps/web |
/media/** | synced web static assets |
Required services (production-mode containers): traefik, nginx, api, web, postgres (pgvector), redis, gotenberg.
Clients:
- Browser — MRP/CRP walkthroughs, full web app (
mrp-crp-alpha-demo-walkthrough.md) - EAS
previewAPK — brewery native;EXPO_PUBLIC_API_BASE_URL=https://demo.umbraculum.dev(apps/native/eas.json) - Native Open on web — must use the same origin (
openWebFallback.ts) - Ubuntu Touch — Click webapp over the same web origin (cookie session, online-first); reference package
packaging/ubuntu-touch/umbraculum-reference/(ubuntu-touch-shell-strategy.md)
Demo accounts (credentials)
Demo logins use the E2E seed personas (defaults; ship-safe — same on every demo). Source of truth: apps/web/e2e/personas.json and services/api/src/cli/seedE2eFixture.ts.
| Role | Default password | |
|---|---|---|
| Brewery admin (primary demo) | e2e-admin@brewery.local | e2e-admin-pw! |
| Member | e2e-member@brewery.local | e2e-member-pw! |
| Viewer | e2e-viewer@brewery.local | e2e-viewer-pw! |
| Multi-workspace admin (SelectWorkspace flow) | e2e-multi-admin@brewery.local | e2e-multi-admin-pw! |
Active workspace (fixtures): e2e00000-0000-0000-0000-0000000000aa.
These credentials are public by design — they exist only on the demo host whose DB may be wiped at any time. They appear in the platform shared layout notice on demo (one-line summary always visible; Demo sign-in table and About this demo prose each behind a collapsed expander by default). Copy defaults live in @umbraculum/i18n (sharedLayoutNotice.demo.*); the banner is activated only when the demo VPS builds web with NEXT_PUBLIC_WEB_SHARED_LAYOUT_NOTICE_ID=demo (see umbraculum-hosting-demo docker-compose.demo.yml). Local docker compose does not set that flag.
To override passwords on demo, set E2E_ADMIN_PASSWORD etc. in /opt/umbraculum-hosting-demo/.env and re-run seed:e2e (upsert hashes the new value into the same user row, no data loss). Note: the shared layout notice still shows i18n default passwords until copy is updated or a future env override lands — operators should keep runbook and banner in sync when rotating demo passwords.
Native login: POST /api/auth/login/native with the same email/password as web.
Current status (last checked 2026-06-03)
Run from repo root:
./scripts/demo-host-verify.sh
BASE_URL=https://demo.umbraculum.dev ./scripts/demo-native-api-smoke.sh
| Check | Result |
|---|---|
DNS A | 84.247.163.121 (Contabo VPS 10, vmi3344577) |
https://demo.umbraculum.dev/api/health | {"ok":true} — Traefik v3.6 + Let's Encrypt |
Browser https://demo.umbraculum.dev/en | 307 → /en/login for anonymous; dashboard after login |
demo-native-api-smoke.sh (5/5) | health, native login, /auth/me, /recipes, /auth/webview-exchange all green |
Stack: umbraculum-hosting-demo main (compose + Traefik v3.6 + nginx) at /opt/umbraculum-hosting-demo; umbraculum-dev master at /opt/umbraculum-dev; volumes umbraculum_demo_* (data) + reused umbraculum_root_node_modules/umbraculum_npm_cache (build).
Local preflight (optional): BASE_URL=http://localhost:18080 ./scripts/demo-native-api-smoke.sh — proves API paths against your dev stack; does not close G1.
Open follow-ups (non-blocking for demo)
1. Phase 0 Step 2 — SSH key-only hardening
Status: keys installed and working; password SSH is still enabled as a fallback. Close this before treating the VPS as long-lived.
Procedure:
-
From your laptop, open a second terminal (keep your existing root SSH session open in the first):
ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no umbdemo 'echo OK && hostname'Must print
OKandvmi3344577with no password prompt. Do not proceed otherwise — you risk a permanent lockout. -
On the VPS:
cd /opt/umbraculum-hosting-demobin/harden --ssh-hardeningThis applies the
umbraculum-hosting-commonsecurity baseline plusPasswordAuthentication noin/etc/ssh/sshd_config.d/99-umbraculum-hosting.conf. The script's post-flight check fails the run if SSH did not reload cleanly. -
Verify from a third terminal that password login is now refused:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no umbdemo# expect: Permission denied (publickey).
Recovery if locked out: Contabo VNC console → log in as root → restore /etc/ssh/sshd_config.d/99-umbraculum-hosting.conf (or systemctl edit ssh to override PasswordAuthentication yes) → systemctl restart ssh.
2. Pin Traefik image to a digest
Status: DONE as of 2026-06-03 — docker-compose.demo.yml pins traefik:v3.6@sha256:802adc80a7bb20a6766c9385c2ad547f0de98564cd20d31d0b6d8f726f906f66. Bump procedure (when a v3.6.x release lands):
docker pull traefik:v3.6
docker inspect traefik:v3.6 --format '{{index .RepoDigests 0}}'
# update the image: line in docker-compose.demo.yml, commit, push, then on VPS:
cd /opt/umbraculum-hosting-demo && bin/pull
docker compose -f docker-compose.demo.yml --env-file .env up -d traefik
3. Revoke the temporary GitHub PAT (after umbraculum-dev flips public)
Status (2026-06-27): VPS verified — scripts/demo-vps-pat-revoke-verify.sh green on demo VPS. Confirm classic PAT revoked in GitHub UI.
-
GitHub → Profile → Settings → Developer settings → Personal access tokens (classic) → revoke
umbdemo-read(or whatever you named it). -
VPS — wipe stored credentials:
git config --global --unset credential.helper || truerm -f /root/.git-credentials -
Verify (on VPS):
/opt/umbraculum-dev/scripts/demo-vps-pat-revoke-verify.shOr manually:
cd /opt/umbraculum-dev && git fetch origin && git statusgit ls-remote https://github.com/umbraculum-dev/umbraculum-dev.git HEAD
Redeploy maintenance UX
During api / web restarts, nginx serves a branded maintenance page (HTTP 503) instead of raw 502 Bad Gateway. Native clients get JSON 503 on /api/*.
| Artifact | Repo |
|---|---|
nginx/demo.conf + nginx/maintenance/maintenance.html | umbraculum-hosting-demo |
| Mirror | infra/nginx/demo.conf |
| Operator runbook | hosting-demo docs/OPERATOR.md — bin/redeploy |
After bin/pull on the demo VPS: docker compose … up -d nginx then optional maintenance smoke (stop api/web briefly → curl expects 503 maintenance, not 502).
Infra bring-up checklist (maintainer)
- DNS —
demo.umbraculum.dev→ A/AAAA or CNAME to the host running Docker Compose (must reach your Umbraculum nginx, not a registrar parking page). - TLS — HTTPS at Traefik (Let's Encrypt HTTP-01). Android EAS builds require HTTPS.
- Deploy — Follow umbraculum-hosting-demo
docs/OPERATOR.mdC1–C7. - Env — Production env in
/opt/umbraculum-hosting-demo/.env:ACME_EMAIL,POSTGRES_PASSWORD,DATABASE_URL,APP_AI_KEY_SECRET,RENDERING_SIGNING_SECRET. - Migrate + seed —
prisma migrate deploythennpm run seed:e2e -w @umbraculum/api. - Verify
curl -fsS https://demo.umbraculum.dev/api/health # {"ok":true}./scripts/demo-host-verify.shBASE_URL=https://demo.umbraculum.dev ./scripts/demo-native-api-smoke.sh
- Smoke web — Log in at
https://demo.umbraculum.dev/enase2e-admin@brewery.localand runmrp-crp-alpha-demo-walkthrough.mdsteps 1–4. - Smoke native — Install EAS
previewAPK; followcanonical-native-platform-surface.md§5.1.
Reset policy
- Demo data may be deleted and re-seeded at any time for demos or CI parity.
- Do not store data on demo that you cannot afford to lose.
- Your real operational brewery (outside this repo) will use
cloud.umbraculum.devwhen that track ships—not demo.
Related docs
demo-host-ssl-strategy.md— Traefik v3.6 + ACME ADRnative-eas-demo-build-log.md— EAS build IDs and device smoke statuscanonical-native-platform-surface.md§5 — native demo scope and checklistubuntu-touch-shell-strategy.md— UT Morph webapp wrapper strategypackaging/ubuntu-touch/umbraculum-reference/README.md— reference Click package (demo origin default)NATIVE-STRATEGY-AND-CI.md§5 — EAS profiles and CI workflowcloud-hosted-product-track.md— future hosted product (not demo)