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:
@@ -2,7 +2,7 @@
|
||||
title: "🚧 Deliberate limits"
|
||||
description: "What this Coder deployment does not enable and what each omission costs: no wildcard access URL, no Authelia gate, no open signup, no external provisioner, and a hard memory pressure gate."
|
||||
source: "verified deployment on the loca operator host, 2026-08-19"
|
||||
reviewed: 2026-08-19
|
||||
reviewed: 2026-08-20
|
||||
---
|
||||
|
||||
# 🚧 Deliberate limits
|
||||
@@ -28,19 +28,54 @@ Every entry here is a choice, not an oversight. Each one states the cost, the tr
|
||||
- `coder port-forward` from the CLI
|
||||
- SSH port forwarding, including `coder ssh -R` and anything set up by `coder config-ssh`
|
||||
- Coder Desktop and the IDE remotes (VS Code extension, JetBrains Gateway)
|
||||
- documented upgrade path, all of it requiring operator approval:
|
||||
- obtain a DNS-01 wildcard certificate for `*.code.loca.zone`, which means adding DNS-provider API credentials to this host
|
||||
- add an nginx server block for `server_name *.code.loca.zone` proxying to `127.0.0.1:52226`
|
||||
- set `CODER_WILDCARD_ACCESS_URL` on the `coder` service and restart it
|
||||
- once wildcards work, upstream advises disabling path-based apps (`CODER_DISABLE_PATH_APPS=true`), because path apps share the Coder API origin and a malicious workspace could reuse Coder cookies against the API
|
||||
- note the RFC 1035 label limit: app, agent, workspace and username together must stay under 63 characters in one hostname label
|
||||
|
||||
### Runbook: enabling `*.code.loca.zone` (blocked, do not start until both prerequisites exist)
|
||||
|
||||
Preflight re-confirmed 2026-08-20: `sudo -n certbot plugins` lists exactly `nginx`, `standalone`, `webroot`, no `dns-*` plugin is installed, and `/etc/letsencrypt/` holds no DNS credential file. So this runbook cannot be executed today, and nothing below should be attempted piecemeal — a half-applied wildcard leaves nginx serving a name its certificate does not cover.
|
||||
|
||||
Two named prerequisites, both operator decisions:
|
||||
|
||||
1. a DNS-provider API credential file for the `loca.zone` zone, mode 600 root-owned, e.g. `/etc/letsencrypt/dns-<provider>.ini`. The provider is genuinely unknown from this host: `loca.zone` nameservers point at `178.18.250.170`, self-hosted, so the credential shape cannot be guessed
|
||||
2. the matching plugin package `python3-certbot-dns-<provider>`, which is a package install and therefore ask-first
|
||||
|
||||
Then, in order:
|
||||
|
||||
```bash
|
||||
# 1. expand the existing lineage rather than creating a second one
|
||||
sudo certbot certonly \
|
||||
--dns-<provider> \
|
||||
--dns-<provider>-credentials /etc/letsencrypt/dns-<provider>.ini \
|
||||
--cert-name code.loca.zone --expand \
|
||||
-d code.loca.zone -d wiki.code.loca.zone -d '*.code.loca.zone'
|
||||
sudo certbot certificates # confirm all three SANs on one lineage
|
||||
|
||||
# 2. nginx: add the wildcard to both blocks that own the app name
|
||||
# /etc/nginx/sites-available/code.loca.zone
|
||||
# line 3 (listen 443 ssl) -> server_name code.loca.zone *.code.loca.zone;
|
||||
# line 56 (listen 80) -> server_name code.loca.zone *.code.loca.zone;
|
||||
# leave the two wiki.code.loca.zone blocks alone: a wildcard on the app
|
||||
# block would otherwise swallow the wiki host, and the wiki must stay static
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
|
||||
# 3. Coder: add to the coder service environment in docker-compose.yml
|
||||
# CODER_WILDCARD_ACCESS_URL: "*.code.loca.zone"
|
||||
cd /home/loca/dev/coder && sudo -n docker compose config >/dev/null \
|
||||
&& sudo -n docker compose up -d --force-recreate coder
|
||||
curl -sf http://127.0.0.1:52226/healthz
|
||||
```
|
||||
|
||||
Verified against the running v2.35.3 binary, not assumed: `coder server --help` documents `--wildcard-access-url, $CODER_WILDCARD_ACCESS_URL` taking the form `"*.example.com"`, and `--disable-path-apps, $CODER_DISABLE_PATH_APPS` whose own help text says it is "recommended for security purposes if a `--wildcard-access-url` is configured". So the follow-up hardening step is:
|
||||
|
||||
- set `CODER_DISABLE_PATH_APPS: "true"` only after subdomain apps are confirmed working, because it removes the path-based routes this deployment currently depends on, including the `code-server` app on `ws1`
|
||||
- note the RFC 1035 label limit: app, agent, workspace and username together must stay under 63 characters in one hostname label
|
||||
- renewal: the lineage keeps its `--dns-<provider>` authenticator in `/etc/letsencrypt/renewal/code.loca.zone.conf`, so unattended renewal needs the credential file to stay in place; the existing nginx reload hook still applies
|
||||
|
||||
## 🔓 No Authelia gate
|
||||
|
||||
- cost: the dashboard is publicly reachable and Coder's own login page is the only thing between the internet and the deployment; there is no second factor at the proxy
|
||||
- why the cost is accepted: an `auth_request` gate would 302 every cookie-less request, which is exactly what the `coder` CLI, the workspace agents and DERP relay traffic send. A browser-only gate is impossible because the SPA and the agents share `/api/v2`
|
||||
- compensating controls: Coder's own session handling, no open signup, a pinned server image, and a single admin account
|
||||
- full argument and the OIDC-via-Authelia upgrade path: [[operations/auth-model]]
|
||||
- since 2026-08-20 identity is nonetheless unified: Coder consumes Authelia over OIDC at the application layer, with password login kept as break-glass, while the proxy stays ungated — full argument in [[operations/auth-model]]
|
||||
|
||||
## 🚫 No open signup
|
||||
|
||||
|
||||
Reference in New Issue
Block a user