Self-hosting guide and reference compose distribution #88

Closed
opened 2026-07-04 14:52:48 +02:00 by fable-5 · 1 comment
Collaborator

Context

The kickoff bar: a stranger with Docker can install, update, and back up Dorfteich using only the guide.

Scope

Write docs/self-hosting/: requirements, install (reference docker-compose.yml + .env.example — published variant consuming release images by semver tag, optional caddy TLS profile — implement that profile), first-run wizard walkthrough, update procedure (+ downgrade window), backup/restore with the sidecar, troubleshooting (readyz interpretation, logs, common proxy/WebSocket mistakes), upgrade-from-source note; verify by a scripted clean-VM install test.

Acceptance criteria

  • a clean-machine install following only the guide reaches a working wizard (scripted verification in CI or documented manual run)
  • caddy profile serves TLS on a test domain
  • every .env variable is documented with default and effect
  • guide is linked from README; en only is acceptable for docs (documented decision)

Technical notes

  • deployment.md §Self-hosting distribution, ADR 0014 (release images).

Dependencies

Depends on #80, #83.

Size: ~2 days


Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add de and en), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.

## Context The kickoff bar: a stranger with Docker can install, update, and back up Dorfteich using only the guide. ## Scope Write `docs/self-hosting/`: requirements, install (reference `docker-compose.yml` + `.env.example` — published variant consuming release images by semver tag, optional `caddy` TLS profile — implement that profile), first-run wizard walkthrough, update procedure (+ downgrade window), backup/restore with the sidecar, troubleshooting (readyz interpretation, logs, common proxy/WebSocket mistakes), upgrade-from-source note; verify by a scripted clean-VM install test. ## Acceptance criteria - [ ] a clean-machine install following only the guide reaches a working wizard (scripted verification in CI or documented manual run) - [ ] caddy profile serves TLS on a test domain - [ ] every .env variable is documented with default and effect - [ ] guide is linked from README; en only is acceptable for docs (documented decision) ## Technical notes - deployment.md §Self-hosting distribution, ADR 0014 (release images). ## Dependencies Depends on #80, #83. **Size**: ~2 days --- *Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add `de` **and** `en`), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.*
fable-5 added this to the M8 — Self-hosting & operations milestone 2026-07-04 14:52:48 +02:00
fable-5 added the
deployment
docs
labels 2026-07-04 14:52:48 +02:00
Author
Collaborator

Implemented in 4b55fb9 (pipeline green, 8/8; clean-machine install verified live on the stage host).

docs/self-hosting/README.md — the complete operator contract, linked from the repository README: requirements; install from exactly the published reference files (deploy/compose/docker-compose.yml + .env.example, plus Caddyfile for the profile); first-run wizard walkthrough incl. the pre-seeding path; update procedure (TAG bump + pull + up -d, migrations auto-apply) with the one-minor-release downgrade window and the restore fallback; backup/restore with the #83 sidecar; troubleshooting keyed to readyz semantics (503 vs degraded, per-check details) plus the classic operator mistakes (missing WebSocket upgrade on /collab, APP_BASE_URL vs CSRF/mail links, lost db-data volume); build-from-source note (the reference compose keeps its build contexts).

caddy TLS profile, implemented — new opt-in service in the reference compose (profiles: [caddy], inert for everyone with their own proxy and for the stages) + deploy/compose/Caddyfile: publishes 80/443, terminates TLS for $DOMAIN with automatic Let's Encrypt, routes /api/* → api, /collab* → collab (WebSocket), rest → web — the same routing the stage vhosts use. DOMAIN=localhost (default) issues an internal-CA certificate for smoke tests. New .env keys documented: DOMAIN, CADDY_HTTP_PORT, CADDY_HTTPS_PORT.

Acceptance criteria

  • clean-machine install following only the guide reaches a working wizard (scripted)deploy/self-hosting-verify.sh: fresh temp directory, copies only the three published files, scripts the guide's .env edits, docker compose --profile caddy up -d, waits for GET /api/v1/setup{"status":"required",…} over TLS, asserts the certificate is Caddy-issued and the SPA shell serves through the ingress, then tears down (own project name, ephemeral ports — safe next to live stacks). Ran green on ONE.
  • caddy profile serves TLS on a test domain — verified with DOMAIN=localhost (real TLS handshake, Caddy internal CA): both hosts' ports 80/443 are occupied by the stage proxies, so public-domain ACME cannot be exercised anywhere today. The Let's-Encrypt path is Caddy's default behavior for any real DOMAIN; exercising it on a public domain is recorded as a go-live checklist item (#89).
  • every .env variable documented.env.example is the single, fully commented reference (audited against the compose file: every ${VAR} appears with default and effect).
  • guide linked from README; en-only documented — README links the guide (features + repo layout); the guide's header records the English-only decision (UI localized, operator docs single-language).

Stage composes on ONE resynced to the repo state (backups *.bak-pre88); the profile stays inactive there. The published-variant note (semver TAGs) points at #89 — until the first release, test is the documented tag.

Implemented in `4b55fb9` (pipeline green, 8/8; clean-machine install verified live on the stage host). **`docs/self-hosting/README.md`** — the complete operator contract, linked from the repository README: requirements; install from exactly the published reference files (`deploy/compose/docker-compose.yml` + `.env.example`, plus `Caddyfile` for the profile); first-run wizard walkthrough incl. the pre-seeding path; update procedure (`TAG` bump + `pull` + `up -d`, migrations auto-apply) with the **one-minor-release downgrade window** and the restore fallback; backup/restore with the #83 sidecar; troubleshooting keyed to readyz semantics (`503` vs `degraded`, per-check details) plus the classic operator mistakes (missing WebSocket upgrade on `/collab`, `APP_BASE_URL` vs CSRF/mail links, lost `db-data` volume); build-from-source note (the reference compose keeps its build contexts). **`caddy` TLS profile, implemented** — new opt-in service in the reference compose (`profiles: [caddy]`, inert for everyone with their own proxy and for the stages) + `deploy/compose/Caddyfile`: publishes 80/443, terminates TLS for `$DOMAIN` with automatic Let's Encrypt, routes `/api/*` → api, `/collab*` → collab (WebSocket), rest → web — the same routing the stage vhosts use. `DOMAIN=localhost` (default) issues an internal-CA certificate for smoke tests. New `.env` keys documented: `DOMAIN`, `CADDY_HTTP_PORT`, `CADDY_HTTPS_PORT`. **Acceptance criteria** - *clean-machine install following only the guide reaches a working wizard (scripted)* — **`deploy/self-hosting-verify.sh`**: fresh temp directory, copies only the three published files, scripts the guide's `.env` edits, `docker compose --profile caddy up -d`, waits for `GET /api/v1/setup` → `{"status":"required",…}` **over TLS**, asserts the certificate is Caddy-issued and the SPA shell serves through the ingress, then tears down (own project name, ephemeral ports — safe next to live stacks). Ran green on ONE. - *caddy profile serves TLS on a test domain* — verified with `DOMAIN=localhost` (real TLS handshake, Caddy internal CA): both hosts' ports 80/443 are occupied by the stage proxies, so public-domain ACME cannot be exercised anywhere today. The Let's-Encrypt path is Caddy's default behavior for any real `DOMAIN`; exercising it on a public domain is recorded as a go-live checklist item (#89). - *every .env variable documented* — `.env.example` is the single, fully commented reference (audited against the compose file: every `${VAR}` appears with default and effect). - *guide linked from README; en-only documented* — README links the guide (features + repo layout); the guide's header records the English-only decision (UI localized, operator docs single-language). Stage composes on ONE resynced to the repo state (backups `*.bak-pre88`); the profile stays inactive there. The published-variant note (semver `TAG`s) points at #89 — until the first release, `test` is the documented tag.
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#88
No description provided.