Refresh the self-hosting guide for the first public release (#320)
All checks were successful
CI / Lint, typecheck, test (pull_request) Successful in 6m43s
CI / Build container images (pull_request) Successful in 1m13s
CI / Auth e2e pack (pull_request) Successful in 8m52s
CI / Import/export fidelity gate (pull_request) Successful in 58s
CD / Build and push images (push) Successful in 16s
CD / Deploy to Test (push) Successful in 17s
CD / Smoke tests against Test (push) Successful in 1m25s
CD / Promote to Int (push) Successful in 13s
CI / Lint, typecheck, test (push) Successful in 6m54s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 8m42s
CI / Import/export fidelity gate (push) Successful in 58s

- TAG guidance points at pinned release tags (e.g. v0.14.0) instead of
  the pre-release `test` tag; concrete curl commands fetch the three
  reference files.
- Backup wording (guide + .env.example) names all four data volumes in
  the restore set (uploads, plugins, custom fonts, branding).
- Updating section states the back-up-first step and links the update
  runbook.
- Pass the external-authentication variables (OIDC_*, AUTH_LOCAL_ENABLED,
  AUTH_PROXY_*) through the reference compose and document them in
  .env.example: they were documented in security.md but unreachable from
  .env. Empty values count as unset (app-config.service.ts), so the block
  is inert until configured.
- New guide section "External authentication (optional)"; neutral
  APP_BASE_URL example.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017aviRTgWCcAHUh1SBoxf6P
This commit is contained in:
Claude Fable 5 2026-08-03 12:34:30 +02:00
parent 78258c4f9b
commit d2be1116bc
3 changed files with 79 additions and 14 deletions

View File

@ -52,7 +52,7 @@ COMPOSE_PROJECT_NAME=dorfteich
# --- public URL + mail -------------------------------------------------------- # --- public URL + mail --------------------------------------------------------
# Public base URL of the stage (scheme + host). E-mail links and the CSRF # Public base URL of the stage (scheme + host). E-mail links and the CSRF
# origin check are derived from it — it must match what browsers use. # origin check are derived from it — it must match what browsers use.
APP_BASE_URL=https://test.dorfteich.cloud APP_BASE_URL=https://wiki.example.com
# SMTP relay for outgoing mail (verification, password reset). Optional: # SMTP relay for outgoing mail (verification, password reset). Optional:
# leave everything unset and configure the relay in the browser during the # leave everything unset and configure the relay in the browser during the
@ -76,10 +76,36 @@ SMTP_FROM=Dorfteich <wiki@example.com>
#CADDY_HTTP_PORT=80 #CADDY_HTTP_PORT=80
#CADDY_HTTPS_PORT=443 #CADDY_HTTPS_PORT=443
# --- external authentication (issues #214#216, ADR 0021) ---------------------
# Deploy-level on purpose — a Site Admin cannot change these. All unset =
# local username/password login only. Full reference:
# docs/architecture/security.md §External authentication.
# OIDC (Authorization Code + PKCE) is enabled iff ISSUER + CLIENT_ID are set;
# CLIENT_SECRET stays empty for a public client. Redirect URI to register at
# the IdP: $APP_BASE_URL/api/v1/auth/oidc/callback
#OIDC_ISSUER=https://idp.example.com/realms/example
#OIDC_CLIENT_ID=dorfteich-web
#OIDC_CLIENT_SECRET=
#OIDC_SCOPES=openid profile email
#OIDC_PROVIDER_LABEL=Single Sign-On
# Hard switch (#216): false turns EVERY local credential flow off (404) —
# sign-in only via OIDC or the trusted proxy. Complete the first-run setup
# BEFORE flipping it.
#AUTH_LOCAL_ENABLED=false
# Perimeter authentication (#215): identity from a proxy header, honoured
# only when the TCP peer is on the allowlist; the proxy MUST strip the
# header from incoming traffic. Unset = feature off, the header is inert.
#AUTH_PROXY_HEADER=X-Auth-User
#AUTH_PROXY_TRUSTED_PEERS=10.0.0.5
#AUTH_PROXY_MAP=username
#AUTH_PROXY_MODE=plain
#AUTH_PROXY_DN_ATTRIBUTE=CN
# --- backups (ADR 0015, issue #83) -------------------------------------------- # --- backups (ADR 0015, issue #83) --------------------------------------------
# The backup sidecar dumps the database and archives the uploads/plugins # The backup sidecar dumps the database and archives the data volumes
# volumes nightly onto the `backups` volume; restore via # (uploads, plugins, custom fonts, branding) nightly onto the `backups`
# deploy/backup/restore.sh <backup-id>. All values optional. # volume; restore via deploy/backup/restore.sh <backup-id>. All values
# optional.
# Daily run time HH:MM in TZ (default 03:00; set TZ for stage-local time, # Daily run time HH:MM in TZ (default 03:00; set TZ for stage-local time,
# e.g. TZ=Europe/Berlin — unset means UTC). # e.g. TZ=Europe/Berlin — unset means UTC).
#TZ=Europe/Berlin #TZ=Europe/Berlin

View File

@ -61,6 +61,21 @@ services:
# VS-NfD hardening-profile mode (issue #243, ADR 0027): # VS-NfD hardening-profile mode (issue #243, ADR 0027):
# off | marked | hidden | enforced. Empty = off — no marking anywhere. # off | marked | hidden | enforced. Empty = off — no marking anywhere.
VS_NFD_MODE: ${VS_NFD_MODE:-} VS_NFD_MODE: ${VS_NFD_MODE:-}
# External authentication (issues #214#216, ADR 0021) — deploy-level
# on purpose, out of a Site Admin's reach. All empty = local
# username/password login only. Reference: security.md §External
# authentication.
OIDC_ISSUER: ${OIDC_ISSUER:-}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID:-}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:-}
OIDC_SCOPES: ${OIDC_SCOPES:-}
OIDC_PROVIDER_LABEL: ${OIDC_PROVIDER_LABEL:-}
AUTH_LOCAL_ENABLED: ${AUTH_LOCAL_ENABLED:-}
AUTH_PROXY_HEADER: ${AUTH_PROXY_HEADER:-}
AUTH_PROXY_TRUSTED_PEERS: ${AUTH_PROXY_TRUSTED_PEERS:-}
AUTH_PROXY_MAP: ${AUTH_PROXY_MAP:-}
AUTH_PROXY_MODE: ${AUTH_PROXY_MODE:-}
AUTH_PROXY_DN_ATTRIBUTE: ${AUTH_PROXY_DN_ATTRIBUTE:-}
# SMTP relay. Empty (= unset in .env) is fine: the setup wizard writes # SMTP relay. Empty (= unset in .env) is fine: the setup wizard writes
# the relay to the secret store on the `secrets` volume (issue #80); # the relay to the secret store on the `secrets` volume (issue #80);
# values set here in the stage .env always win over the store. # values set here in the stage .env always win over the store.

View File

@ -19,22 +19,27 @@ work, that is a bug (issue #88).
## Install ## Install
1. Create a directory and fetch the two reference files from the repository 1. Create a directory and fetch the reference files from the repository
(`deploy/compose/`): `docker-compose.yml`, `.env.example` — plus (`deploy/compose/`): `docker-compose.yml`, `.env.example` — plus
`Caddyfile` if you want the `caddy` profile. `Caddyfile` if you want the `caddy` profile.
```sh ```sh
mkdir dorfteich && cd dorfteich mkdir dorfteich && cd dorfteich
# copy docker-compose.yml, .env.example (and Caddyfile) here base=https://gitea.101010.cloud/stwaidele/dorfteich/raw/branch/main/deploy/compose
curl -fsSLO "$base/docker-compose.yml"
curl -fsSLO "$base/.env.example"
curl -fsSLO "$base/Caddyfile" # only for the caddy profile
cp .env.example .env && chmod 600 .env cp .env.example .env && chmod 600 .env
``` ```
2. Edit `.env` — the minimum: 2. Edit `.env` — the minimum:
- `POSTGRES_PASSWORD`, `COLLAB_TOKEN_SECRET`: long random strings - `POSTGRES_PASSWORD`, `COLLAB_TOKEN_SECRET`: long random strings
(`openssl rand -base64 32`). (`openssl rand -base64 32`).
- `IMAGE_PREFIX=gitea.101010.cloud/stwaidele/dorfteich` and `TAG`: - `IMAGE_PREFIX=gitea.101010.cloud/stwaidele/dorfteich` and `TAG`: pin
releases are semver tags (`v1.2.3`); until the first public release, the latest release tag (semver, e.g. `v0.14.0`) — the
`test` tracks the latest verified build. [release list](https://gitea.101010.cloud/stwaidele/dorfteich/releases)
is authoritative. Moving tags like `test`/`int` track our stages and
are not meant for third-party installs.
- `APP_BASE_URL=https://wiki.example.com` — must be exactly what - `APP_BASE_URL=https://wiki.example.com` — must be exactly what
browsers will use; e-mail links and the CSRF origin check derive browsers will use; e-mail links and the CSRF origin check derive
from it. from it.
@ -81,7 +86,10 @@ Unattended installs skip the wizard by pre-seeding: set the
## Updating ## Updating
```sh ```sh
# edit .env: TAG=v1.3.0 # 1. take a backup first — the pre-update set is the guaranteed way back:
# Admin → System → "Back up now", or:
docker compose run --rm -e BACKUP_RUN_ONCE=1 backup
# 2. edit .env: TAG=v1.3.0
docker compose pull && docker compose up -d docker compose pull && docker compose up -d
``` ```
@ -89,14 +97,17 @@ Database migrations run automatically at api start. Release notes flag
releases with a `migration` label and any manual steps. **Downgrade releases with a `migration` label and any manual steps. **Downgrade
window: one minor release** — `TAG` back + `pull` + `up -d` is supported window: one minor release** — `TAG` back + `pull` + `up -d` is supported
one step back; further back, restore the backup taken before the update one step back; further back, restore the backup taken before the update
instead (the nightly sidecar gives you one at most 24 h old). instead. Rollback paths — including what to do when a migration itself
fails — are in
[`docs/operations/update-runbook.md`](../operations/update-runbook.md).
## Backups & restore ## Backups & restore
Enabled by default (ADR 0015): the `backup` sidecar dumps the database and Enabled by default (ADR 0015): the `backup` sidecar dumps the database and
archives the uploads/plugins volumes nightly at `BACKUP_TIME` onto the archives the data volumes (uploads, plugins, custom fonts, branding)
`backups` volume, prunes by `BACKUP_RETENTION_DAYS`, writes `status.json`, nightly at `BACKUP_TIME` onto the `backups` volume, prunes by
and — with `BACKUP_MAIL_TO` set — mails you on failure. `BACKUP_RETENTION_DAYS`, writes `status.json`, and — with
`BACKUP_MAIL_TO` set — mails you on failure.
- On-demand backup: `docker compose run --rm -e BACKUP_RUN_ONCE=1 backup`, - On-demand backup: `docker compose run --rm -e BACKUP_RUN_ONCE=1 backup`,
or the **Back up now** button under _Admin → System_. or the **Back up now** button under _Admin → System_.
@ -138,6 +149,19 @@ If the app itself is gone, use the operator path in
`docs/operations/restore-runbook.md` instead — it documents fetching a `docs/operations/restore-runbook.md` instead — it documents fetching a
bundle from Nextcloud by hand. bundle from Nextcloud by hand.
## External authentication (optional)
Local username/password accounts work out of the box — nothing to
configure. Deployments with an existing identity provider can add OpenID
Connect login (`OIDC_ISSUER` + `OIDC_CLIENT_ID` in `.env` enable it), let
an authenticating reverse proxy assert identities (`AUTH_PROXY_*`), and —
after the first-run setup is complete — turn local credentials off
entirely with `AUTH_LOCAL_ENABLED=false`. All of this is deploy-level by
design: a Site Admin cannot change it from the UI. The variables are
documented in `.env.example`; semantics and the trust model are in
[`docs/architecture/security.md`](../architecture/security.md)
(§External authentication).
## Public REST API ## Public REST API
Scripts and integrations can talk to the instance through a Scripts and integrations can talk to the instance through a