Overview & Goals
By this point I had an ephemeral K3s cluster booting itself from scratch, Argo CD syncing apps from this repo, and Headlamp staring at me asking for a login. The obvious next move was a sane login story: one identity, end-to-end TLS, no plaintext anywhere, and no fragile copy-pasting of passwords from ~/.bashrc.
Explanation
Section titled “Explanation”I had three things I wanted to fix at once:
- One login for every UI. Headlamp, Argo CD, and (eventually) other things should all defer to the same identity store. I didn’t want a per-app password file.
- HTTPS everywhere, including internal hosts. Browser-trusted certs without paying for or proving out a public domain. The cluster is private, so a private Certificate Authority is fine.
- Stay GitOps-pure. No
kubectl create secret …at a terminal. Everything reconcilable from this repo, including the bits that bootstrap the rest.
The shape that fell out of this:
- Dex as the OIDC provider. Tiny, declarative, perfect for a lab.
- A self-signed Root CA that lives on the node and gets handed to cert-manager.
- cert-manager with a
ClusterIssuerbacked by that CA, issuing TLS for every internal hostname. - trust-manager to publish the CA into a
lab-caConfigMap that any app can mount to trust outbound TLS calls. - Traefik doing the Ingress part; cert-manager auto-issues the TLS secret it serves.
It’s surprising how few moving parts that ends up being once you let Argo CD do the wiring.
flowchart LR
A[gen-lab-certs.sh<br/>cloud-init] --> B[cluster-root-ca<br/>Secret]
B --> C[ClusterIssuer<br/>local-ca]
B --> D[Bundle: lab-ca]
D --> E[ConfigMap lab-ca<br/>in labelled namespaces]
C --> F[TLS Secrets<br/>per Ingress]
E --> G[Apps mount<br/>for outbound TLS]
F --> H[Traefik HTTPS<br/>dex.kidd.network<br/>headlamp.kidd.network<br/>argocd.kidd.network]
What You’ll End Up With
Section titled “What You’ll End Up With”https://dex.kidd.network— OIDC provider, trusted by your browser.https://headlamp.kidd.network— Kubernetes dashboard with “Login with Dex” working.https://argocd.kidd.network— Argo CD UI authed by the same Dex identity.https://cert.kidd.network— a tiny download page to trust the CA on any new machine.kubectlcan authenticate against the k3s API via the same OIDC issuer (optional but free once Dex is up).
Components
Section titled “Components”| Piece | Where it lives | What it does |
|---|---|---|
| Dex | src/manifests/ainur/dex.yml, dex/values.yaml | OIDC provider; static clients for Headlamp and Argo CD |
| cert-manager + trust-manager | Installed via user-data:589-627 HelmCharts | Issue TLS, distribute CA to namespaces |
| Root CA | Generated by gen-lab-certs.sh (user-data:232-302) | Lives at /etc/rancher/k3s/oidc/lab-ca.crt; imported as cluster-root-ca Secret |
lab-ca Bundle | user-data:642-663 | trust-manager Bundle that targets namespaces labelled ainur.kidd.network/ca: inject |
| Headlamp OIDC client | src/manifests/ainur/headlamp/values.yaml | Mounts lab-ca so it trusts Dex’s cert |
| Argo CD OIDC config | Embedded in user-data at the Argo CD HelmChart block | Wires Argo CD to Dex; lives in user-data because Argo bootstraps the rest of GitOps |
| CA download portal | src/manifests/ainur/cert/ | Friendly page at cert.kidd.network with install instructions per OS |
Flow at a Glance
Section titled “Flow at a Glance”- The node boots and
gen-lab-certs.shgenerates the Root CA (if it doesn’t already exist) and stores it on disk. - cert-manager and trust-manager are installed via k3s HelmChart manifests staged from cloud-init.
cluster-root-caSecret is created in thecert-managernamespace from the on-disk CA.ClusterIssuer local-caand thelab-caBundleare applied.- Argo CD syncs the
dex,headlamp, andcert-downloadapplications. - Each Argo CD
ApplicationusessyncPolicy.managedNamespaceMetadatato drop theainur.kidd.network/ca: injectlabel onto its destination namespace. - trust-manager sees the label and publishes the
lab-caConfigMap into the namespace. - cert-manager issues TLS for each Ingress; Traefik serves the apps over HTTPS.
- You trust the CA on your laptop once (via cert.kidd.network) and you’re done.
Next Steps
Section titled “Next Steps”Walk through the prerequisites to make sure the cluster you have lines up with the cluster I’m assuming, then start at Configuring cert-manager for a Self-Signed CA and work down.