From d2be1116bc43c61f904895c89cd31eca49eb08c4 Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Mon, 3 Aug 2026 12:34:30 +0200 Subject: [PATCH] Refresh the self-hosting guide for the first public release (#320) - 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 Claude-Session: https://claude.ai/code/session_017aviRTgWCcAHUh1SBoxf6P --- deploy/compose/.env.example | 34 +++++++++++++++++++++--- deploy/compose/docker-compose.yml | 15 +++++++++++ docs/self-hosting/README.md | 44 ++++++++++++++++++++++++------- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/deploy/compose/.env.example b/deploy/compose/.env.example index 9e0d836..2ecf7fe 100644 --- a/deploy/compose/.env.example +++ b/deploy/compose/.env.example @@ -52,7 +52,7 @@ COMPOSE_PROJECT_NAME=dorfteich # --- public URL + mail -------------------------------------------------------- # 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. -APP_BASE_URL=https://test.dorfteich.cloud +APP_BASE_URL=https://wiki.example.com # SMTP relay for outgoing mail (verification, password reset). Optional: # leave everything unset and configure the relay in the browser during the @@ -76,10 +76,36 @@ SMTP_FROM=Dorfteich #CADDY_HTTP_PORT=80 #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) -------------------------------------------- -# The backup sidecar dumps the database and archives the uploads/plugins -# volumes nightly onto the `backups` volume; restore via -# deploy/backup/restore.sh . All values optional. +# The backup sidecar dumps the database and archives the data volumes +# (uploads, plugins, custom fonts, branding) nightly onto the `backups` +# volume; restore via deploy/backup/restore.sh . All values +# optional. # Daily run time HH:MM in TZ (default 03:00; set TZ for stage-local time, # e.g. TZ=Europe/Berlin — unset means UTC). #TZ=Europe/Berlin diff --git a/deploy/compose/docker-compose.yml b/deploy/compose/docker-compose.yml index 76fb44a..610cd6b 100644 --- a/deploy/compose/docker-compose.yml +++ b/deploy/compose/docker-compose.yml @@ -61,6 +61,21 @@ services: # VS-NfD hardening-profile mode (issue #243, ADR 0027): # off | marked | hidden | enforced. Empty = off — no marking anywhere. 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 # the relay to the secret store on the `secrets` volume (issue #80); # values set here in the stage .env always win over the store. diff --git a/docs/self-hosting/README.md b/docs/self-hosting/README.md index 48a353f..8395205 100644 --- a/docs/self-hosting/README.md +++ b/docs/self-hosting/README.md @@ -19,22 +19,27 @@ work, that is a bug (issue #88). ## 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 `Caddyfile` if you want the `caddy` profile. ```sh 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 ``` 2. Edit `.env` — the minimum: - `POSTGRES_PASSWORD`, `COLLAB_TOKEN_SECRET`: long random strings (`openssl rand -base64 32`). - - `IMAGE_PREFIX=gitea.101010.cloud/stwaidele/dorfteich` and `TAG`: - releases are semver tags (`v1.2.3`); until the first public release, - `test` tracks the latest verified build. + - `IMAGE_PREFIX=gitea.101010.cloud/stwaidele/dorfteich` and `TAG`: pin + the latest release tag (semver, e.g. `v0.14.0`) — the + [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 browsers will use; e-mail links and the CSRF origin check derive from it. @@ -81,7 +86,10 @@ Unattended installs skip the wizard by pre-seeding: set the ## Updating ```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 ``` @@ -89,14 +97,17 @@ Database migrations run automatically at api start. Release notes flag releases with a `migration` label and any manual steps. **Downgrade window: one minor release** — `TAG` back + `pull` + `up -d` is supported 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 Enabled by default (ADR 0015): the `backup` sidecar dumps the database and -archives the uploads/plugins volumes nightly at `BACKUP_TIME` onto the -`backups` volume, prunes by `BACKUP_RETENTION_DAYS`, writes `status.json`, -and — with `BACKUP_MAIL_TO` set — mails you on failure. +archives the data volumes (uploads, plugins, custom fonts, branding) +nightly at `BACKUP_TIME` onto the `backups` volume, prunes by +`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`, 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 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 Scripts and integrations can talk to the instance through a