One login for every internal tool: Authentik as the front door to a Kubernetes platform
Twenty-seven platform tools across two clusters, from Grafana to per-pull-request environments and AI sandboxes, behind one identity broker fed by Google Workspace and AWS Identity Center, configured entirely from Git.
Industry: Media and events
Company size: 200-500 employees
Services: Platform engineering, identity and access, Kubernetes, GitOps
The Challenge
The client's Kubernetes platform had grown a second layer: the tools that run the platform. Grafana, the database operator's console, Vitess admin, OpenSearch dashboards, the registry, the error tracker, the cost dashboards, a mail catcher for QA, the pull request environment dashboard, and later the AI sandboxes and an AI data analyst. Every one of them needed a login, and every one of them had a different idea of what a login was: a local admin password in a sealed secret, an IP allow-list, a basic-auth header somebody had pasted into a wiki, or nothing at all behind an internal load balancer.
Two things made that untenable. Per-pull-request environments meant dozens of short-lived hostnames a week that product managers and QA needed to open from anywhere, so "internal only" stopped meaning anything. And the company runs on two identity systems already, Google Workspace for everyone and AWS Identity Center for engineers, so any new login was a third password to forget and a third place to forget to remove someone.
Our Approach
We put one identity broker in front of the whole platform and refused to let any tool keep its own door. Authentik was the choice: self-hosted, runs on the platform it protects, speaks SAML and OIDC on both sides, and can be configured entirely from a file.
- One broker, every clusterAuthentik runs once and manages an outpost in each cluster over a Kubernetes service connection, six outposts today. A cluster holds no identity server of its own, only a small proxy that asks the broker whether a request is allowed.
- Identity from where people already areGoogle Workspace is a SAML source, twice, because the company has two tenants. AWS Identity Center is a third. Enrollment flows create the Authentik account on first login and drop it into a default group, so nobody is issued a password and offboarding happens where it already happens.
- Everything declared in GitProviders, applications, outposts, groups, policies, and flows live in one blueprint file that Flux delivers as a ConfigMap and Authentik applies on change. It is on its 111th version after 190 commits, and nothing has been configured in the admin UI. Adding an application is one Ingress and three blueprint entries, written up as a guide the team follows without us.
- Three ways in, chosen per appTools that speak OIDC natively (Grafana, Sentry, Harbor, the database operator, the monitoring console) get an OAuth2 provider and real user identities with groups. Tools that do not get a proxy provider: the public hostname points at the outpost, which authenticates and forwards to the in-cluster service. Wildcard hosts such as per-pull-request environments and AI sandboxes use Traefik forward-auth against the outpost, one middleware for every stack, with the user's name, email, groups, and a signed JWT handed to the application in headers.
- Authorization as policy, not as passwordsExpression policies and groups decide who gets past the login. Operator tools are restricted to infrastructure-managed accounts. Tools employees use, like the pre-release site and the intent dashboard, accept any Google Workspace login. Cost dashboards, VPA recommendations, and the AI agent console are admin-only. QA has a group for the mail catcher. Each rule is a few lines in the same file as the app it protects.
- API clients without a back doorWhen developers asked for a header to bypass auth on pull request stacks for Postman and curl, the answer was no. The outpost already accepts HTTP Basic auth with a per-user Authentik app password, revocable per person, with an identity in the logs. The bypass list is reserved for webhooks, health checks, and static assets, and every pattern in it is reviewed as what it is: an authentication bypass.
- Sized from measurementTwo server replicas and one worker. The server handles about 3,500 requests an hour, 2,900 of them health probes, around 120 of them actual login flows.
The Results
Counted from the running system in September 2026.
- 43 active accounts, none with a password we manageEvery one is linked to a Google or Identity Center login and disappears when that does.
- New tools cost minutesThe AI sandbox environments, the AI data analyst, and the agent console each went behind SSO the day they were deployed, by the engineer deploying them, using the guide.
- The pull request dashboard is the busiest door1,083 of last month's authorizations were engineers opening their own pull request environments and stacks, which is the self-service the platform was built for.
- Audit for freeEvery login, authorization, and failed attempt is an event with a user, a source, and an application, and every access rule change is a reviewed commit.
What did not go to plan
- A leak that was not the broker's faultThe auth server started running out of memory once or twice a day per replica. Each authorization for one application retained about 350 MiB in the serving worker. The real driver was the pull request dashboard: an idle browser tab kept reconnecting its log stream after its session lapsed, straight into a full login flow, about fifty times an hour per tab, forever. We recycled workers as a stopgap, fixed the dashboard, then measured the leak was gone and removed the stopgap.
- The stopgap had its own costRecycling a worker every fifty requests re-ran Authentik's startup reconcile in every new worker process: 68 worker boots an hour, 1,530 configuration pushes to the outposts in three hours, and each outpost reloading all of its applications every few seconds. Nothing broke, but the logs were unreadable and the outposts were doing more work than the users. Removed the day the real fix shipped.
- A 64 MiB filesystemThe container image sets its temp directory to /dev/shm, and Kubernetes gives /dev/shm 64 MiB by default. After about three days the oldest replica wedged with no space left and bus errors on every restart. A memory-backed 512 MiB mount fixed it; the memory counts against the pod's limit, so the limit was adjusted with it.
- Two proxy modes, two regex dialectsBypass patterns match the path in proxy mode and the full URL in forward-domain mode. We unified them twice, breaking one side each time, before writing down that they must differ.
- Drift is silent until it is notThe blueprint re-applies only when its content changes. A change made in the admin UI that disabled authentication on every pull request stack lived for two weeks before the next blueprint edit reverted it, and nobody had been told. The guide now starts with a drift check, and the admin UI is treated as read-only.
- A registry that logged everyone out dailyThe registry's CLI tokens expired after a day because the OIDC scope did not request a refresh token. One scope, one line, and a note in the runbook about where that configuration actually lives, since it was not where the UI implied.
Key Takeaway
Single sign-on for internal tooling is not a product you buy; it is the decision that no tool on the platform gets to own its own login, enforced in the same Git repository as the tools themselves. The broker took a day to deploy. The value came from the guide, the policies, and the refusal to add a bypass header.
Related case studies: the GitOps EKS platform and pull request environments engineers run themselves
Too many logins behind your platform?
We'll inventory every internal tool and its current door, and show you what putting them behind one identity broker looks like on your cluster.