Extend LE *.unkin.net wildcard to arrstack + authentik (reflect into gitea) #418

Merged
benvin merged 4 commits from benvin/wildcard-consumers into main 2026-08-25 21:48:54 +10:00
Member

Why

#417 stood up the central Let's Encrypt *.unkin.net wildcard (Certificate wildcard-unkin-net in cert-manager, secret wildcard-unkin-net-tls, emberstack-reflected). This wires the remaining single-label public hosts onto that publicly-trusted leaf instead of the internal Vault-PKI CA.

A *.unkin.net wildcard matches single-label subdomains only, so cluster hostnames under *.k8s.syd1.au.unkin.net are deliberately left on vault-issuer.

Note: PR #417 already merged to main, so this is no longer stacked — it targets main directly.

How

  • cert-manager: reflect wildcard-unkin-net-tls into arrstack, authentik, gitea (appended to both reflector namespace lists → cheeztv,arrstack,authentik,gitea).
  • arrstack: repoint the public arrproxy gateway listener (arrstack.unkin.net) certificateRefswildcard-unkin-net-tls; drop its cert-manager.io/* vault-issuer annotations.
  • authentik: repoint the identity.unkin.net https listener → wildcard-unkin-net-tls. The identity.k8s.syd1.au.unkin.net listeners keep authentik-tls (vault-issuer), so the gateway common-name is retargeted to that cluster host. authentik-ldap gateway untouched.
  • gitea: secret reflected only; git.unkin.net cutover deferred (no manifest change), same deferred pattern as fafflix.

Validation

  • kustomize build OK for cert-manager / arrstack / authentik / gitea overlays.
  • kubeconform all valid (0 invalid, 0 errors) across the four overlays.
  • Verified no *.k8s.syd1.au.unkin.net listener lost its vault-issuer wiring.
## Why #417 stood up the central Let's Encrypt `*.unkin.net` wildcard (Certificate `wildcard-unkin-net` in `cert-manager`, secret `wildcard-unkin-net-tls`, emberstack-reflected). This wires the remaining single-label public hosts onto that publicly-trusted leaf instead of the internal Vault-PKI CA. A `*.unkin.net` wildcard matches **single-label** subdomains only, so cluster hostnames under `*.k8s.syd1.au.unkin.net` are deliberately left on `vault-issuer`. > Note: PR #417 already merged to `main`, so this is no longer stacked — it targets `main` directly. ## How - **cert-manager**: reflect `wildcard-unkin-net-tls` into `arrstack`, `authentik`, `gitea` (appended to both reflector namespace lists → `cheeztv,arrstack,authentik,gitea`). - **arrstack**: repoint the public `arrproxy` gateway listener (`arrstack.unkin.net`) `certificateRefs` → `wildcard-unkin-net-tls`; drop its `cert-manager.io/*` vault-issuer annotations. - **authentik**: repoint the `identity.unkin.net` https listener → `wildcard-unkin-net-tls`. The `identity.k8s.syd1.au.unkin.net` listeners keep `authentik-tls` (vault-issuer), so the gateway `common-name` is retargeted to that cluster host. `authentik-ldap` gateway untouched. - **gitea**: secret **reflected only**; `git.unkin.net` cutover deferred (no manifest change), same deferred pattern as fafflix. ## Validation - `kustomize build` OK for cert-manager / arrstack / authentik / gitea overlays. - `kubeconform` all valid (0 invalid, 0 errors) across the four overlays. - Verified no `*.k8s.syd1.au.unkin.net` listener lost its vault-issuer wiring.
unkin-agent added 1 commit 2026-08-25 21:06:14 +10:00
Extend the LE *.unkin.net wildcard to arrstack + authentik (reflect into gitea)
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
fffc14f880
why: after #417 stood up the central Let's Encrypt *.unkin.net wildcard
(Certificate wildcard-unkin-net, secret wildcard-unkin-net-tls, emberstack-
reflected), the remaining single-label public hosts should terminate on the
real publicly-trusted leaf instead of the internal Vault-PKI CA. A *.unkin.net
wildcard only matches single-label subdomains, so cluster hostnames under
*.k8s.syd1.au.unkin.net stay on vault-issuer.

- certificate_wildcard-unkin-net: reflect the secret into arrstack, authentik
  and gitea (append to both reflector namespace lists)
- arrstack: point the public arrproxy gateway (arrstack.unkin.net) at
  wildcard-unkin-net-tls and drop its vault-issuer annotations
- authentik: point the identity.unkin.net listener at wildcard-unkin-net-tls;
  the identity.k8s.syd1.au.unkin.net listeners keep authentik-tls, so the
  gateway common-name is retargeted to the cluster host
- gitea: secret reflected only; git.unkin.net cutover deferred (no manifest
  change), same deferred pattern as fafflix
Author
Member

Review finding (critical): apps/base/authentik/gateway.yaml

The authentik Gateway still carries the Gateway-level annotations

cert-manager.io/cluster-issuer: vault-issuer
cert-manager.io/common-name: identity.k8s.syd1.au.unkin.net

while now also having a listener (https, hostname identity.unkin.net) whose certificateRefs points at wildcard-unkin-net-tls — the secret that's supposed to be populated only by the emberstack reflector from the centrally-managed LE Certificate in cert-manager ns.

cert-manager's gateway-shim creates one Certificate object per distinct secretName referenced by any listener in the Gateway, and Gateway-level issuer/common-name annotations apply to all of them — there's no per-listener opt-out (confirmed against the gateway-shim docs: it explicitly creates a separate Certificate "since two Secret names are used", and shared annotations apply across all generated Certificates). So this Gateway will also cause cert-manager to mint and own a second, competing Certificate for wildcard-unkin-net-tls in the authentik namespace, issued off vault-issuer (internal Vault PKI) instead of the real LE wildcard.

That fights the emberstack reflector for ownership of the same secret name/namespace: whichever controller reconciles last wins, so identity.unkin.net's public TLS can flip between the real LE wildcard cert and an untrusted internal Vault-PKI leaf — defeating the point of this PR and potentially breaking public HTTPS on identity.unkin.net intermittently.

The arrstack gateway in this same PR avoided exactly this by removing the cert-manager.io/* annotations entirely (its Gateway no longer needs any vault-issued cert). authentik's Gateway still needs a vault-issued cert for the internal listener (identity.k8s.syd1.au.unkin.netauthentik-tls), so the annotations can't just be dropped wholesale — but leaving them at the shared Gateway level while also referencing the wildcard secret from another listener in the same object re-introduces the hazard.

Suggested fix: split into two Gateway objects — one with no cert-manager.io/* annotations serving identity.unkin.net on wildcard-unkin-net-tls (mirroring the arrstack pattern), and a second retaining cluster-issuer: vault-issuer / common-name: identity.k8s.syd1.au.unkin.net, serving only the internal hostname on authentik-tls.

(Side note, resolved fine: the authentik-tls cert's own CN/SAN transition — dropping identity.unkin.net from its SAN list and retargeting CN to identity.k8s.syd1.au.unkin.net — is not itself a problem; no remaining listener needs the old SAN from that secret, and gateway-shim will reconcile/re-issue it automatically.)

Everything else in the PR looks correct: wildcard Certificate's reflector namespace lists are exactly cheeztv,arrstack,authentik,gitea on both reflection-allowed-namespaces and reflection-auto-namespaces with nothing else changed in that file; arrstack gateway cleanly repointed with no dead references to arrproxy-gateway-tls left anywhere in the repo; authentik-ldap gateway untouched (and uses TLS Passthrough only, so it's unaffected by gateway-shim regardless); gitea has zero manifest changes (reflect-only, as intended); no *.k8s.syd1.au.unkin.net listener lost its vault-issuer wiring. CI is green on fffc14f.

**Review finding (critical): `apps/base/authentik/gateway.yaml`** The `authentik` Gateway still carries the Gateway-level annotations ``` cert-manager.io/cluster-issuer: vault-issuer cert-manager.io/common-name: identity.k8s.syd1.au.unkin.net ``` while now *also* having a listener (`https`, hostname `identity.unkin.net`) whose `certificateRefs` points at `wildcard-unkin-net-tls` — the secret that's supposed to be populated **only** by the emberstack reflector from the centrally-managed LE `Certificate` in `cert-manager` ns. cert-manager's gateway-shim creates one `Certificate` object **per distinct secretName referenced by any listener in the Gateway**, and Gateway-level issuer/common-name annotations apply to *all* of them — there's no per-listener opt-out (confirmed against the gateway-shim docs: it explicitly creates a separate `Certificate` "since two Secret names are used", and shared annotations apply across all generated Certificates). So this Gateway will also cause cert-manager to mint and own a **second, competing `Certificate` for `wildcard-unkin-net-tls` in the `authentik` namespace**, issued off `vault-issuer` (internal Vault PKI) instead of the real LE wildcard. That fights the emberstack reflector for ownership of the same secret name/namespace: whichever controller reconciles last wins, so `identity.unkin.net`'s public TLS can flip between the real LE wildcard cert and an untrusted internal Vault-PKI leaf — defeating the point of this PR and potentially breaking public HTTPS on `identity.unkin.net` intermittently. The `arrstack` gateway in this same PR avoided exactly this by **removing** the `cert-manager.io/*` annotations entirely (its Gateway no longer needs any vault-issued cert). `authentik`'s Gateway still needs a vault-issued cert for the internal listener (`identity.k8s.syd1.au.unkin.net` → `authentik-tls`), so the annotations can't just be dropped wholesale — but leaving them at the shared Gateway level while also referencing the wildcard secret from another listener in the *same* object re-introduces the hazard. Suggested fix: split into two `Gateway` objects — one with no `cert-manager.io/*` annotations serving `identity.unkin.net` on `wildcard-unkin-net-tls` (mirroring the arrstack pattern), and a second retaining `cluster-issuer: vault-issuer` / `common-name: identity.k8s.syd1.au.unkin.net`, serving only the internal hostname on `authentik-tls`. (Side note, resolved fine: the `authentik-tls` cert's own CN/SAN transition — dropping `identity.unkin.net` from its SAN list and retargeting CN to `identity.k8s.syd1.au.unkin.net` — is not itself a problem; no remaining listener needs the old SAN from that secret, and gateway-shim will reconcile/re-issue it automatically.) Everything else in the PR looks correct: wildcard `Certificate`'s reflector namespace lists are exactly `cheeztv,arrstack,authentik,gitea` on both `reflection-allowed-namespaces` and `reflection-auto-namespaces` with nothing else changed in that file; `arrstack` gateway cleanly repointed with no dead references to `arrproxy-gateway-tls` left anywhere in the repo; `authentik-ldap` gateway untouched (and uses TLS `Passthrough` only, so it's unaffected by gateway-shim regardless); gitea has zero manifest changes (reflect-only, as intended); no `*.k8s.syd1.au.unkin.net` listener lost its vault-issuer wiring. CI is green on fffc14f.
unkin-agent added 1 commit 2026-08-25 21:15:05 +10:00
Split authentik gateway into public wildcard + internal vault-issuer gateways
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
b0dce55cd4
The single authentik Gateway kept cert-manager.io annotations (vault-issuer,
common-name identity.k8s.syd1.au.unkin.net) while its public identity.unkin.net
https listener referenced the reflector-managed wildcard-unkin-net-tls. The
cert-manager gateway-shim mints a Certificate per distinct listener secretName
from Gateway-level annotations, so it would create a competing vault-issuer
Certificate for wildcard-unkin-net-tls and fight the emberstack reflector over
that secret.

Split into two Gateways mirroring the cheeztv/fafflix convention:
- authentik (public): identity.unkin.net listeners on wildcard-unkin-net-tls,
  no cert-manager annotations, external-dns publishes identity.unkin.net.
- authentik-internal: identity.k8s.syd1.au.unkin.net listeners on authentik-tls
  with the vault-issuer cert-manager annotations, external-dns publishes the
  cluster host. Both target 198.18.200.4.

Update HTTPRoutes to attach each hostname's redirect + app route to the
matching gateway's http/https sections.
Author
Member

Split authentik into a public wildcard gateway (identity.unkin.net -> wildcard-unkin-net-tls, no cert-manager annotations) plus an internal vault-issuer gateway (identity.k8s.syd1.au.unkin.net -> authentik-tls, common-name on the cluster host) per review, mirroring the cheeztv two-gateway pattern. HTTPRoutes re-parented per hostname; external-dns preserved per host (both target 198.18.200.4). kustomize build + kubeconform pass (35 valid, 0 errors).

Split authentik into a public wildcard gateway (identity.unkin.net -> wildcard-unkin-net-tls, no cert-manager annotations) plus an internal vault-issuer gateway (identity.k8s.syd1.au.unkin.net -> authentik-tls, common-name on the cluster host) per review, mirroring the cheeztv two-gateway pattern. HTTPRoutes re-parented per hostname; external-dns preserved per host (both target 198.18.200.4). kustomize build + kubeconform pass (35 valid, 0 errors).
unkin-agent added 1 commit 2026-08-25 21:39:57 +10:00
Move public identity gateway to external traefik proxy
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
68c8ec79e1
The public authentik gateway (identity.unkin.net) now uses traefik-external
and removes external-dns management, matching the arrproxy external gateway
convention. DNS remains managed out-of-band via bind-operator. The internal
authentik-internal gateway stays on traefik-internal.
Author
Member

public identity gateway moved to traefik-external (no external-dns annotations), matching the arrproxy external gateway convention

public identity gateway moved to traefik-external (no external-dns annotations), matching the arrproxy external gateway convention
unkin-agent added 1 commit 2026-08-25 21:43:26 +10:00
Identity gateway migrated to traefik-external (198.18.199.0); watchstate added to wildcard cert reflector lists
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
7d7b5fb6f2
Author
Member

identity-dns-internal repointed to the external traefik VIP 198.18.199.0 (gateway moved to traefik-external); watchstate added to wildcard reflector lists for its upcoming external gateway

identity-dns-internal repointed to the external traefik VIP 198.18.199.0 (gateway moved to traefik-external); watchstate added to wildcard reflector lists for its upcoming external gateway
benvin merged commit 5da12e398d into main 2026-08-25 21:48:54 +10:00
benvin deleted branch benvin/wildcard-consumers 2026-08-25 21:48:55 +10:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/argocd-apps#418