Build Daily

Tinley Park · October 29, 2026
platformNeil Godfreyapplied

Security and identity layer of a Kubernetes homelab

The security and identity layer of a three-cluster K3s homelab managed by Rancher. Keycloak gives single sign-on over OIDC, OpenBao holds the secrets and External Secrets copies them into each cluster, Kyverno checks workloads at admission, Falco watches them at runtime, Trivy Operator scans the running images, and Cloudflare Tunnel and Access publish the sites with no inbound ports. Every piece is open source or on a free plan.

Updated October 17, 2026

The security and identity layer decides who can sign in, where secrets live and how they reach the pods, what a workload may do when it is created and while it runs, and how traffic from the internet gets in. In this homelab, three K3s clusters (management, beta and prod) run as Lima VMs on one Mac, and Rancher manages all three. The layer spreads across those clusters: the secret store sits on the management cluster, the checks sit where the product workloads run, and the public entry point sits on prod.

The services in this layer

Security and identity, by clusterHover, tap or tab to a service. The red lines show what it talks to.
One Mac, three Linux VMs
Security and identityWho can get in, where secrets live, and what is allowed to run.
Beta and Prod
Management
Beta
Prod

Keycloak is the single sign-on server. It runs on the prod cluster and signs users in to the products, and operators in to Rancher, Grafana, Argo CD and kubectl, all over OIDC. An Argo CronWorkflow rotates the OIDC client secrets every month.

OpenBao is the secret store and the source of truth for app secrets. It runs on the management cluster with integrated Raft storage and a KV v2 engine at kv/, with one subtree per cluster. A Raft snapshot goes to the backup store every night, and a secret-age exporter warns when a secret has not changed for too long.

External Secrets runs on beta and prod. Its ExternalSecret objects pull values from OpenBao into native Kubernetes Secrets, and Reloader rolls the workloads that use a Secret when its value changes.

Kyverno is the admission gate on beta and prod. Its policies cover pod security, required labels and image registry rules, and its background scan reports on objects that were already in the cluster. Rancher's own webhook guards the namespace pod-security labels.

Falco watches what containers do after they start, from kernel events through the modern eBPF driver, on beta and prod. Falcosidekick forwards its events to Alertmanager.

Trivy Operator runs on beta with a Trivy server. It scans the images and configuration of running workloads and writes VulnerabilityReport and ConfigAuditReport objects next to each one.

Cloudflare Tunnel publishes the product sites and APIs from prod over outbound-only connections, so the Mac opens no inbound ports. Cloudflare Access gates the admin hosts, the Rancher UI and the Keycloak master realm, to one identity.

How the pieces fit

Two flows cross this layer. A secret starts in OpenBao and ends as a value that a pod reads. A request starts at Cloudflare's edge and ends with a signed-in user. The figure follows both.

How secrets and requests cross the security layer

Step 1 of 3. External Secrets on prod logs in through the prod Kubernetes auth mount. The policy behind that mount allows reads of kv/prod/* only, so a beta login cannot read prod values.

The secret path runs from the management cluster to beta and prod. The request path enters through the tunnel on prod.

The two flows meet at the app pod. The OIDC client secret that the app uses at the end of the request path comes in through the secret path, and the monthly rotation of that secret uses both: the new value goes into OpenBao, External Secrets copies it, and Reloader rolls the pod. The checks sit around the pod too. Kyverno decides whether the pod may be created at all, Trivy Operator reports the known CVEs in its image on beta, and Falco reports what it does at runtime.

Choices and trade-offs

  • OpenBao for secrets. OpenBao is the community fork of HashiCorp Vault under the MPL 2.0 licence, the licence Vault had before it moved to the Business Source Licence. It unseals itself from a static unseal key, so a VM reboot does not wait for a person to enter key shares. The trade-off is that the unseal key sits beside the server. The nightly Raft snapshot and the single recovery share are the way back if the store is lost.
  • One store, one auth mount per cluster. One secret store on the management cluster keeps one place to rotate and audit. A separate Kubernetes auth mount for each of beta and prod limits a compromised token on one cluster to that cluster's own subtree.
  • Secrets stay out of Git. The manifests in Git hold ExternalSecret references only, and Argo CD applies them. A value changes in OpenBao, never with kubectl, because External Secrets overwrites the cluster copy on the next refresh.
  • Admission, scan and runtime as three tools. Kyverno, Trivy Operator and Falco each see a different moment: before a pod exists, what its image contains, and what it does when it runs. Rancher's webhook keeps the namespace pod-security labels, and Kyverno owns the workload-level rules.
  • Scans on beta only. Images are built once, tagged by git SHA, and run on beta before the same image reaches prod. A scan on beta therefore describes an image before it ships, and prod carries no scanner load.
  • Quiet runtime alerts. The Falco route in Alertmanager groups by cluster, rule and namespace and repeats at most every 4 hours. A noisy rule sends one email per window, not one per event.
  • No open ports. Cloudflare Tunnel and Access run on the free plans. An admin request passes Access and then the app's own login, so an app password alone does not open a console.
  • A known gap. Keycloak runs 26.0.6, a line that no longer gets security fixes. The upgrade steps through each minor release, as the Keycloak page explains.

Related