coder: autostop TTL, nightly backups, Authelia OIDC, wildcard runbook
- docker-compose: CODER_OIDC_* wired to Authelia (password login kept as break-glass) - scripts/backup-stacks.sh + stacks-backup.timer: nightly pg_dump, Continue state, stack configs - vault: verification items 13/14, auth-model OIDC section, limits DNS-01 runbook
This commit is contained in:
@@ -60,19 +60,43 @@ reviewed: 2026-08-20
|
||||
- there is no self-service registration in Coder OSS with password auth; a user appears only because an admin made it
|
||||
- password reset for the initial Owner is a host-side operation: `coder reset-password <username>` only works when run on the machine running the control plane, which here means inside the `coder` container
|
||||
|
||||
## 🔭 Future upgrade path: Authelia as an OIDC provider
|
||||
## 🔗 Authelia as OIDC provider — configured
|
||||
|
||||
Not implemented, and it requires operator approval because it means editing the shared Authelia deployment.
|
||||
Implemented 2026-08-20. Identity is unified at the application layer: Coder consumes Authelia over OIDC. The proxy is still ungated — everything in the sections above still holds, and adding an `auth_request` gate would still break agents.
|
||||
|
||||
- shape of the change:
|
||||
- register a new OIDC client in Authelia for Coder, with redirect URI `https://code.loca.zone/api/v2/users/oidc/callback`
|
||||
- set `CODER_OIDC_ISSUER_URL`, `CODER_OIDC_CLIENT_ID`, `CODER_OIDC_CLIENT_SECRET` and, if wanted, `CODER_OIDC_EMAIL_DOMAIN` on the `coder` service
|
||||
- optionally add `offline_access` to `CODER_OIDC_SCOPES` so sessions survive access-token expiry
|
||||
- optionally set `CODER_DISABLE_PASSWORD_AUTH=true` once OIDC login is proven
|
||||
- what it does and does not change:
|
||||
- it unifies identity inside Coder, at the application layer, where the CLI and agents keep using their bearer tokens
|
||||
- it does not, and must not, add an nginx `auth_request` gate; the failure modes above still apply
|
||||
- prerequisites the operator must approve: a new Authelia client definition, a client secret placed in `.env`, and a restart of both stacks
|
||||
Authelia side, `/home/loca/dev/services/authelia/config/configuration.yml`, second entry under `identity_providers.oidc.clients`:
|
||||
|
||||
- `client_id: 'coder'`, `client_name: 'Coder'`, `public: false`
|
||||
- `client_secret` is a `pbkdf2-sha512` digest read via `{{ secret "/config/secrets/oidc/coder-client-secret.digest" }}`; that file is `600 root:root`, and the container runs as root so the strict mode is safe
|
||||
- `authorization_policy: 'one_factor'`, `consent_mode: 'implicit'`, `token_endpoint_auth_method: 'client_secret_basic'`
|
||||
- single redirect URI `https://code.loca.zone/api/v2/users/oidc/callback`
|
||||
- scopes `openid`, `profile`, `email`, `groups`; grant `authorization_code`; response type `code`
|
||||
|
||||
Coder side, `environment:` on the `coder` service in `docker-compose.yml`:
|
||||
|
||||
| variable | value |
|
||||
|---|---|
|
||||
| `CODER_OIDC_ISSUER_URL` | `https://auth.loca.zone` |
|
||||
| `CODER_OIDC_CLIENT_ID` | `coder` |
|
||||
| `CODER_OIDC_CLIENT_SECRET` | `${CODER_OIDC_CLIENT_SECRET}`, interpolated from `.env` (mode 600, gitignored) |
|
||||
| `CODER_OIDC_SCOPES` | `openid,profile,email` |
|
||||
| `CODER_OIDC_SIGN_IN_TEXT` | `Sign in with loca.zone SSO` |
|
||||
|
||||
Deliberately unset:
|
||||
|
||||
- `CODER_DISABLE_PASSWORD_AUTH` — password login stays as break-glass. If Authelia or the OIDC client breaks, the Owner can still log in with the credential in `.admin-credentials`
|
||||
- `CODER_OIDC_EMAIL_DOMAIN` — no domain restriction; the Authelia user database is the gate
|
||||
|
||||
Agent and CLI traffic is unaffected: both authenticate with `Coder-Session-Token` bearer tokens against `/api/v2/...`, a path OIDC never touches. Verified after the change — `ws1` agent `main` still `connected`, token `GET /api/v2/users/me` still `200`.
|
||||
|
||||
Verification actually performed:
|
||||
|
||||
- `GET /api/v2/users/authmethods` returns `password.enabled: true` and `oidc.enabled: true` with `signInText: "Sign in with loca.zone SSO"`
|
||||
- `https://code.loca.zone/login` renders the SSO button next to the password form
|
||||
- clicking it produces the chain `/api/v2/users/oidc/callback?redirect=%2F` → `https://auth.loca.zone/api/oidc/authorization?...client_id=coder...redirect_uri=https%3A%2F%2Fcode.loca.zone%2Fapi%2Fv2%2Fusers%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email` with PKCE `S256` → the Authelia login form at `?flow=openid_connect`. Authelia raising the form rather than `invalid_client` is the proof that the client id and secret digest are accepted
|
||||
- the final credential entry at the Authelia form is the operator's own SSO login and was not performed here: `users_database.yml` stores only a password hash, so no automated agent can complete it. First interactive SSO login remains an operator action, and it will create a second Coder account unless the OIDC email matches `admin@loca.zone`
|
||||
|
||||
Rotation: regenerate with `authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 64 --random.charset alphanumeric`, install the `Digest` to the digest file, put the `Random Password` in `.env`, then `docker compose restart` Authelia and `docker compose up -d --force-recreate coder`.
|
||||
|
||||
## 📚 Sources
|
||||
|
||||
|
||||
Reference in New Issue
Block a user