Resolve OQ-4: scoped Cloudflare API token for DNS-01 + ExternalDNS
Operator chose Option A. cert-manager solves ACME DNS-01 and ExternalDNS manages *.home.keithjackson.dev records via a scoped Cloudflare token (Zone.DNS.Edit, keithjackson.dev), stored SOPS-encrypted. Operator provides the token once (new prereq T-2.4p); T-2.4/T-2.5 unblocked. Only OQ-BKP (off-cluster DR backup target, Phase 4) remains open. Updated: docs 00,08,09; task board. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
192ce31bef
commit
cde2f2330c
4 files changed
+37
-38
No files matched your search
@@ -195,10 +195,13 @@ implementation.
|
||||
tunnel**, **non-TCP** (OpenVPN UDP / Lightway-UDP), rules enforced outside the service
|
||||
(ADR-0012). See [`03`](03-networking-isolation-and-egress.md).
|
||||
|
||||
- **OQ-4 (TLS/DNS challenge access)** — **RESOLVED**: a **scoped Cloudflare API token**
|
||||
(`Zone·DNS·Edit`, `keithjackson.dev`), SOPS-encrypted, drives cert-manager DNS-01 and ExternalDNS.
|
||||
The static `*.keithjackson.dev` wildcard covers reachability but not TXT-challenge writes; the token
|
||||
handles issuance + record automation. Operator provides the token once. See
|
||||
[`08`](08-tls-and-certificates.md).
|
||||
|
||||
### Still open
|
||||
- **OQ-4 (TLS/DNS challenge access)**: Cloudflare already has a wildcard `*.keithjackson.dev` → public
|
||||
IP (covers reachability), but **ACME DNS-01 needs write access** to create `_acme-challenge` TXT
|
||||
records, and `*.keithjackson.dev` does **not** match the two-label-deep `*.home.keithjackson.dev`.
|
||||
Decide the challenge mechanism: **(a)** a scoped Cloudflare **API token** (Zone·DNS·Edit) → fully
|
||||
automated DNS-01 + ExternalDNS, or **(b)** **acme-dns delegation** (one-time `_acme-challenge`
|
||||
CNAME edit, then no standing Cloudflare credential). See [`08`](08-tls-and-certificates.md).
|
||||
- **OQ-BKP (off-cluster DR backup target)**: which S3-compatible endpoint or NFS host stores
|
||||
Velero/Longhorn backups of the irreplaceable tier. Needed by **Phase 4**, not blocking Phase 2.
|
||||
See [`04`](04-storage-and-state.md).
|
||||
@@ -28,24 +28,23 @@ services (R-TLS-01/02/03).
|
||||
needs no new cert), with per-service certs available where isolation warrants.
|
||||
- The DNS provider API token is a SOPS-encrypted secret ([07](07-security-and-secrets.md)).
|
||||
|
||||
## DNS-01 challenge access (OQ-4 — the one open item)
|
||||
## DNS-01 challenge access (OQ-4 — RESOLVED: scoped Cloudflare API token)
|
||||
|
||||
Cloudflare already has a wildcard `*.keithjackson.dev` → public-IP record. **That covers
|
||||
reachability but not certificate issuance**: ACME DNS-01 requires cert-manager to **write
|
||||
`_acme-challenge` TXT records**, and the existing wildcard does not match two-label-deep names like
|
||||
`plex.home.keithjackson.dev`. So a **challenge-access decision is still required**:
|
||||
Cloudflare already has a wildcard `*.keithjackson.dev` → public-IP record, which covers
|
||||
*reachability* but not certificate issuance (ACME DNS-01 must **write `_acme-challenge` TXT records**,
|
||||
and that wildcard does not match two-label-deep names like `plex.home.keithjackson.dev`).
|
||||
|
||||
- **Option A — scoped Cloudflare API token** (Zone·DNS·Edit for `keithjackson.dev`), stored
|
||||
SOPS-encrypted ([07](07-security-and-secrets.md)). cert-manager writes TXT challenges and
|
||||
ExternalDNS manages the `*.home.keithjackson.dev` records — **fully automated**. *Recommended
|
||||
(simplest).*
|
||||
- **Option B — acme-dns delegation**: a one-time `_acme-challenge` **CNAME** in Cloudflare points to
|
||||
an in-cluster acme-dns server; cert-manager writes only to acme-dns, so **no standing Cloudflare
|
||||
credential** lives in the cluster. More moving parts; public `*.home` records then need the
|
||||
one-time wildcard record instead of ExternalDNS.
|
||||
**Decision (OQ-4):** use a **scoped Cloudflare API token** — `Zone·DNS·Edit` limited to the
|
||||
`keithjackson.dev` zone — stored **SOPS-encrypted** ([07](07-security-and-secrets.md)). With it:
|
||||
- **cert-manager** solves DNS-01 by writing/removing TXT challenge records automatically (issue,
|
||||
renew, revoke — R-TLS-02), including the wildcard `*.home.keithjackson.dev` cert and internal-only
|
||||
services (R-TLS-03).
|
||||
- **ExternalDNS** manages the `*.home.keithjackson.dev` records automatically ([09](09-dns-and-ingress.md),
|
||||
R-DNS-02) — no manual record editing for public services.
|
||||
|
||||
Either option supports the wildcard `*.home.keithjackson.dev` cert and internal-only issuance
|
||||
(R-TLS-03). This is the remaining blocker for the TLS/DNS workstream (Phase 2).
|
||||
**Operator prerequisite:** create the scoped token in Cloudflare and hand it over once; it is then
|
||||
committed SOPS-encrypted and never touched manually again. The token is least-privilege (single zone,
|
||||
DNS edit only) so its blast radius is bounded (R-SEC-02). Rotation = re-encrypt + commit.
|
||||
|
||||
## Renewal & revocation (R-TLS-02)
|
||||
|
||||
@@ -75,8 +74,8 @@ CA distribution. Split-horizon DNS ([09](09-dns-and-ingress.md)) resolves
|
||||
- Certificate expiry and issuance failures raise alerts.
|
||||
- Onboarding a new service requires no manual certificate step.
|
||||
|
||||
## Open questions
|
||||
- **OQ-4** — DNS-01 challenge access: **Option A (scoped Cloudflare API token, recommended)** vs
|
||||
**Option B (acme-dns delegation)**. Provider is Cloudflare (confirmed). This is the only item still
|
||||
blocking Phase 2 TLS.
|
||||
- Wildcard vs. per-service certs default — **resolved: wildcard** `*.home.keithjackson.dev` (ADR-0006).
|
||||
## Resolved
|
||||
- **OQ-4** — DNS-01 via a **scoped Cloudflare API token** (`Zone·DNS·Edit`, `keithjackson.dev`),
|
||||
SOPS-encrypted; drives both cert-manager DNS-01 and ExternalDNS. Phase 2 TLS/DNS is unblocked once
|
||||
the operator provides the token.
|
||||
- Wildcard vs. per-service certs default — **wildcard** `*.home.keithjackson.dev` (ADR-0006).
|
||||
@@ -62,9 +62,9 @@ A wildcard `*.keithjackson.dev` matches only **one** label deep — it covers `h
|
||||
but **not** `plex.home.keithjackson.dev`. Consequences:
|
||||
- **`internal` services need no public record** — PiHole resolves `<svc>.home.keithjackson.dev` to
|
||||
the internal Gateway VIP (split-horizon). This is the majority of services.
|
||||
- **`public` services** need a public record for `<svc>.home.keithjackson.dev`. That is provided by
|
||||
either a one-time `*.home.keithjackson.dev` → public-IP record, or by **ExternalDNS via the DNS
|
||||
API** — both hinge on OQ-4 (see [08](08-tls-and-certificates.md)).
|
||||
- **`public` services** need a public record for `<svc>.home.keithjackson.dev`. Per OQ-4 (resolved),
|
||||
**ExternalDNS manages these automatically** via the scoped Cloudflare API token — no manual record
|
||||
editing (see [08](08-tls-and-certificates.md)).
|
||||
|
||||
## Interaction with default-deny
|
||||
|
||||
@@ -81,9 +81,5 @@ not let other in-cluster services reach it unless an explicit allow rule exists.
|
||||
|
||||
## Resolved
|
||||
- **OQ-1** — single SOHO edge (manual port-forward only); ingress VIP via **Cilium L2 announcement**.
|
||||
|
||||
## Open questions
|
||||
- **OQ-4** — DNS challenge/record access: Cloudflare **API token** (automated ExternalDNS + DNS-01)
|
||||
vs **acme-dns delegation** (one-time CNAME, no standing credential). Determines whether public
|
||||
`*.home.keithjackson.dev` records and ACME challenges are automated or partly manual. See
|
||||
[08](08-tls-and-certificates.md).
|
||||
- **OQ-4** — scoped **Cloudflare API token** drives ExternalDNS (records) and cert-manager DNS-01
|
||||
(certs) automatically; see [08](08-tls-and-certificates.md).
|
||||
Reference in new issue
Block a user