31 Aug 2026 · 9 min read
Every identity vendor sells the same story. Login is hard, MFA is hard, SSO is hard, so hand it all to us and pay per user per month. It's a good pitch, right up until you count the users and read the contract. The bill grows with your headcount and never stops.
At Obmondo we run identity for our own team, for every Kubernetes cluster we operate, and for a stack of internal apps, and the identity bill is zero. Not "cheap." Zero. It all runs on Keycloak, self-hosted, one central instance that everything else authenticates against. This post is about how that actually fits together, why the "someone else's tenant" part matters more in Europe than the price does, and where a paid vendor still earns its money.
The old way was a VPN and a flat network. Get onto the corporate network and you were trusted, and every internal dashboard and cluster API sat behind that one wall. Breach the wall once and you had the run of the place. Regulators have caught up with how badly that ages: NIS2 now expects essential and important entities to treat access control and strong authentication as baseline, not as a maturity milestone you'll get to next year.
So access at Obmondo is identity first. To reach a cluster's Kubernetes API, you come in over a NetBird mesh, a self-hosted WireGuard overlay, and NetBird authenticates you against our central Keycloak before you're a peer on the network at all. After a cluster is bootstrapped, the public kube-apiserver load balancer is switched off entirely. The API isn't sitting on the internet behind a password. It isn't reachable at all unless you've logged into Keycloak and joined the mesh. Your identity gates the network, and the network is the only path to the API.
That is the zero-trust model auditors keep asking for, except it isn't a slide. There is no flat network to be trusted on, and the single most valuable target in the cluster, the API server, has no public front door to attack.
Once you're on the mesh, kubectl gets its access from NetBird too. Nobody here carries a static admin kubeconfig with a token baked into it, and there's no separate credential plugin to install and wire up. NetBird recently grew a Kubernetes login of its own: its API Server Proxy exposes the cluster's API through the mesh and uses your NetBird identity to authorize every call. You ask NetBird what you can reach and let it write you a context:
netbird kubernetes list
netbird kubernetes write-kubeconfig cluster-name
kubectl --context cluster-name get pods -A
You are already logged into NetBird against Keycloak to be on the mesh, so there's no second login and no token sitting in a file to leak from a laptop.
Add someone to the SRE group in Keycloak and they have cluster-admin the next time their identity syncs through. Remove them and it's gone, everywhere, at once. There's no per-user binding to hunt down, no stale kubeconfig outliving an offboarding. This is exactly the property an ISO 27001 auditor wants to see: least privilege that's enforced centrally, and revocation that actually propagates instead of living on a checklist somebody forgot. "Who can reach production, and why" is one query against group membership, not an archaeology project.
The same Keycloak is the login for the apps too. Argo CD, Harbor, and the other tools in the cluster point their OIDC login straight at it. One account, one place to grant access, one place to revoke it, whether you're deploying with Argo CD or pushing an image to Harbor. Your engineers stop collecting a separate password per tool, and you stop wondering which of six admin panels still has an ex-contractor's account on it.
Not every internal tool speaks OIDC, of course. Plenty of dashboards and admin UIs have no real auth of their own. For those, a forward-auth service sits in front: Traefik hands each incoming request to it, it checks the user against Keycloak, and it returns allow or deny before the request ever reaches the app. You put a real login in front of something that was never built for one, with a single ingress annotation and no change to the app:
annotations:
traefik.ingress.kubernetes.io/router.middlewares: traefik-traefik-forward-auth@kubernetescrd
That closes the gap that usually stays open the longest, the long tail of small internal tools that "we'll put behind auth later" and never do.
A password on its own is not access control any regulator takes seriously in 2026, and it shouldn't be for you either. Keycloak lets us offer YubiKeys as a login option through WebAuthn, so an engineer taps a hardware key instead of, or on top of, a password. The authentication flow decides who gets prompted and how hard: you can duplicate the browser flow, put the WebAuthn step ahead of the one-time-password form, and make hardware keys the front-line second factor.
None of this is a premium tier. Phishing-resistant MFA is one of the concrete things NIS2 pushes for and one of the boxes a CIS benchmark makes you tick, and here it's a checkbox on a flow you already control rather than a line item on next year's contract.
Here's the part that matters more in Europe than anything above. Identity records are personal data of the touchiest kind: names, emails, group memberships, a log of who signed in from where and when. We've argued at length elsewhere on this blog that hosting in the EU doesn't make you GDPR compliant, because a US-owned provider stays reachable under the CLOUD Act no matter which datacenter its servers sit in. Self-hosting your identity plane is the clean side of that same coin.
There's no US-owned processor in the path to reason about. No cross-border transfer to paper over with Standard Contractual Clauses. No directory of your staff and your customers sitting in a tenant you don't control. The data is in your Postgres, in the region you chose, under your access rules. Data residency stops being a clause you negotiate and becomes a fact of where you deployed. That's the whole sovereignty argument in one line: your identity system runs on infrastructure you own, in a jurisdiction you picked, with no foreign SaaS anywhere in the login path.
The resilience angle is the same shape. DORA cares a great deal about third-party ICT concentration risk, about what happens when a critical outside service has a bad day. A hosted identity provider is precisely that kind of dependency: if it goes down or decides to drop you, every login you have goes with it. Self-hosting takes that single point of failure off the board. Recovery is yours to run, from realm export/import to the backing database, and it doesn't wait on a vendor's status page.
Line the alternatives up honestly. Okta, Auth0, and Microsoft Entra all price on monthly active users, and the features you need for the setup above (SAML and OIDC, group-based authorization, hardware-key MFA, external IdP brokering) are the ones that push you off the free tier into per-user pricing or an enterprise quote. Auth0's free tier stops being free the moment you want enterprise connections. Entra's conditional access sits behind the P1 and P2 licenses. For a company with real staff plus every operator on every cluster, that meter only ever spins one direction.
An alternative could be the open source solution with Keycloak on KubeAid that costs you no more than the compute it runs on. It's a StatefulSet backed by PostgreSQL, with metrics wired into Prometheus for monitoring and alerts, and the same hardened defaults built into KubeAid. You're already paying for the cluster so the marginal cost of identity is reduced to nothing; and it doesn't care whether you have ten users or ten thousand.
The tradeoffs? Yes, there will always be tradeoffs, and in this case it is the matter of responsibility for the operations. You'll be responsible for handling upgrades, the PostgreSQL database, backups, and disaster recovery, to name some. And when Keycloak has a bad night, it's your team that is paged, not a vendor with an SLA. There's no support line to call by default; you may have the docs and the source code; but you may not have the capability nor the wish to support it in your team and therefore have to buy it instead. On the other hand, what you gain is no per-user costs, no data leaving your control, no feature held hostage behind a plan upgrade, and no lock-in. The solution is standard OIDC and SAML on software you can pick up and run anywhere.
Strip away the acronyms and it comes down to one question. Do you own your identity system, or do you rent it? Renting is easier on day one and it's a fine choice for plenty of teams. But rented identity means your staff directory lives in someone else's jurisdiction, your compliance story depends on their paperwork, your logins depend on their uptime, and your bill depends on your own success.
Owning it means the answer to "where does the personal data live, who administers it, how is access granted and revoked, and what happens if the provider disappears" is the same short sentence every time: it's our Keycloak, in our cluster, in our region. None of this is a substitute for an actual audit, and nothing here is legal advice. But when the auditor asks those questions, and under NIS2, ISO 27001, GDPR, DORA, or CIS someone eventually will, a short honest answer beats a long one built on a vendor's promises. If you're running KubeAid, the pieces are already in the catalog. Point your clusters at your own Keycloak and keep the whole thing.
Want to set up your own or maybe let us do it?