How to Install Authentik for Self-Hosted SSO
Table of contents
- Key takeaways
- Why Authentik and not something else
- The architecture since 2025.10
- The basic deployment
- First start and migrations
- Forward authentication with Traefik
- Typical friction points
- Conclusion
- Frequently asked questions
- What is the difference between Authentik and Keycloak?
- Does Authentik support SAML in addition to OAuth/OIDC?
- How much memory does Authentik need in production?
Actualizado: 2026-05-03
Authentik is the self-hosted identity provider that has received the most recommendations in the last two years from people I work with. It combines OAuth2, SAML, LDAP, and forward authentication in a single package, with a reasonable interface and a much gentler learning curve than Keycloak. This article covers the concrete install with Docker Compose, the current architecture decisions, and the points where most people stumble the first time.
Key takeaways
- Since version 2025.10, Authentik drops the mandatory Redis dependency: the minimum stack is PostgreSQL + server + worker (three containers instead of four).
- Forward authentication with Traefik is the most common use case: protecting internal web services without modifying each application.
- Three classic first-install problems: domain/URL configuration, cookie handling across subdomains, and persistent volumes for PostgreSQL.
- Fits small and medium organizations well; for thousands of users or complex policies, Keycloak remains more powerful.
- Never skip major.minor versions in upgrades: go one by one.
Why Authentik and not something else
The choice between Authentik, Keycloak, Zitadel, and commercial solutions like Auth0 depends on context, but for small-to-medium self-hosting the choice has clear nuances:
- Keycloak: very powerful but heavy. Admin interface has a learning curve that slows teams without dedicated time.
- Zitadel: elegant but younger and with a smaller ecosystem.
- Auth0: excellent but stopped being a realistic option for anyone wanting to self-host.
Authentik occupies the middle ground: complete enough for real cases, with good SAML and OAuth2 support, with useful forward authentication to protect services behind Traefik or Nginx, and with manageable resource consumption. A small instance runs comfortably with 2 GB of memory and a couple of cores.
The architecture since 2025.10
An important change to understand before installing: since version 2025.10, Authentik dropped the mandatory Redis dependency. For years the minimum architecture was PostgreSQL + Redis + server + worker. Now PostgreSQL + server + worker is enough, and Redis has become optional for high-concurrency cases.
This simplification has two practical effects:
- The stack drops from four containers to three, reducing configuration and failure surface.
- Anyone installing for the first time no longer has to explain why a Redis is hanging off the identity service.
The basic deployment
The docker-compose.yml starts from the official one published by Authentik but simplified. It defines:
- A
postgresqlservice with version 16. - A
serverservice with theghcr.io/goauthentik/serverimage andservercommand. - A
workerservice with the same image andworkercommand.
The server exposes ports 9000 and 9443, which Traefik or Nginx use for forward authentication.
Minimum environment variables:
AUTHENTIK_SECRET_KEY: a long random string used to sign tokens.AUTHENTIK_POSTGRESQL__HOST: pointing to the database service.AUTHENTIK_POSTGRESQL__USER,AUTHENTIK_POSTGRESQL__NAME,AUTHENTIK_POSTGRESQL__PASSWORD.
In serious deployments, move the password and the secret out of direct definition into a secrets manager or a git-ignored .env file.
A useful detail: set memory and CPU limits on the containers from the start. The server can spike during mass logins or LDAP syncs, and without a declared limit can affect other services on the same host.
First start and migrations
When the server boots for the first time, it automatically runs database migrations. This process can take several minutes. A typical friction point is booting server and worker at the same time. On first install and on major upgrades, the best approach is:
- Start only the server.
- Watch it finish migrations in the logs.
- Start the worker.
If both try to apply migrations simultaneously, PostgreSQL locks can appear that require killing sessions manually. This pattern also applies on sequential upgrades between major versions: you cannot skip major.minor, you must go one by one.
After migrations, the admin interface sits on port 9000 under /if/flow/initial-setup/ the first time. There, the initial admin user is created. Use a real email and save the password in a manager.
Forward authentication with Traefik
The most common use case when adopting Authentik is protecting internal web services behind a proxy. The pattern is called forward authentication: Traefik receives the request, forwards it to Authentik to verify a valid session, and if none exists sends the user to login.
The configuration on the Authentik side follows these steps:
- Create a proxy provider with forward auth single application or forward auth domain.
- Create an application linked to it.
- Create an outpost that exposes the forward auth endpoint.
On the Traefik side, a middleware of type forwardAuth points to the outpost, and that middleware applies to any router that should be protected.
A pattern I use is having two predefined middleware chains:
chain-base: for public services without authentication.chain-oauth: for protected services passing through Authentik.
This clean separation makes adding or removing protection from a service a matter of changing a label, not rebuilding configuration.
Typical friction points
Three problems almost everyone hits the first time:
- Domain and URL configuration. Authentik needs to know from which domain it is accessed to correctly generate redirects. The
AUTHENTIK_HOSTvariable and the brand configuration inside the interface must match the real domain. If you putauthentik.example.comin Traefik but Authentik thinks it is atlocalhost, redirects bring the user back tolocalhostand login does not work. - Cookie handling across subdomains. For an Authentik session to protect services on different subdomains, cookies need to be configured with the parent domain. The solution is configuring the proxy provider with cookie domain pointing to the root domain.
- Data storage. The PostgreSQL database is critical and must live on a persistent volume with backups configured. Several teams have lost entire Authentik configurations by having the volume on tmpfs or by deleting the volume when doing
compose downwith the wrong flag.
Conclusion
Authentik offers the best ratio of install effort to capabilities obtained in the self-hosted identity space. An afternoon is enough to have a working instance with web login and forward authentication on a couple of services. If you are evaluating self-hosted identity and do not have extreme scale or very specific compliance requirements, Authentik is the first candidate to try.
Where to pause and think: whether your organization has external users, partners, or customers who will also authenticate. Availability and federated identity requirements change a lot when SSO stops being internal. The good news is that this review can be done with Authentik already running on internal tasks, without needing to pick the final tool from day one.
Frequently asked questions
What is the difference between Authentik and Keycloak?
Authentik stands out for its modern UI and easy Docker Compose installation. Keycloak has greater enterprise maturity but requires more resources. For small teams or self-hosting, Authentik is usually more manageable.
Does Authentik support SAML in addition to OAuth/OIDC?
Yes. Authentik supports OAuth 2.0, OpenID Connect, SAML 2.0, LDAP, and forward auth proxy. You can use it as a SAML IdP for services that don’t support OIDC.
How much memory does Authentik need in production?
A basic installation with server and worker requires approximately 500 MB–1 GB of RAM. With multiple concurrent users, it’s recommended to allocate at least 2 GB for the full instance including the database.