Privacy

Authentik SSO Self-Hosted: Worth It for a Household?

Authentik self-hosted is three containers now, not four. The compose stack, forward auth in front of an app with no login, and when you do not need it.

Authentik SSO self-hosted — the three-container stack, forward auth, and the trusted proxy setting

⚡ The short version

Authentik is three containers now, not four: a server, a background worker and PostgreSQL. Redis was removed in version 2025.10 and most of the guides you will find still show it. What earns the stack its keep is forward auth — putting a real login in front of an application that has none — and not the single sign-on, which mostly buys convenience you could get from a password manager.

The Cloudflare Tunnel guide on this site ends with a working public URL and says nothing about who may open it. That is the gap authentik self-hosted fills, and the honest reason to run it: not so one password opens six services, but so the service with no password at all stops being reachable by anyone who guesses the hostname.

It is also heavier than the “just add a container” tone of most write-ups suggests.

What Does Authentik Actually Buy You?

Two different things, and only one of them is worth the containers.

The advertised feature is single sign-on: one identity, one login screen, every application handing off to it. That works, and for a household it is convenience rather than a security gain. If everyone already uses a self-hosted password manager, a unique password per service is not the problem authentik solves.

What changes the possibilities is the proxy provider. Its documentation is blunt about the purpose: it “protects applications that do not support native authentication protocols such as OIDC, SAML, or LDAP” (checked 10 September 2026). Plenty of self-hosted software has no login at all — a dashboard, an admin panel, a metrics page, a half-finished tool somebody published on GitHub. Publishing one of those publishes it to everyone.

Authentik puts a login in front of that application without the application knowing, and passes the identity through as headers, so an app that can read X-authentik-username, X-authentik-email or X-authentik-groups can treat the request as already authenticated instead of asking again.

Every service behind authentik becomes unreachable when its database is down, which is an argument for keeping the doors to your own infrastructure — SSH, the router, the proxy admin — outside it.

Three Containers or Four?

Three, and this is the detail that dates almost every guide currently on page one for this topic.

Older releases ran a fourth. Authentik’s 2025.10 release notes carry “Removed Redis dependency: authentik no longer uses Redis at all” as a headline change, and say what moved: earlier versions used Redis for caching, background tasks, the embedded outpost’s session store and WebSocket connections. Tasks had already gone to PostgreSQL in 2025.8, and 2025.10 moved the rest (checked 10 September 2026).

That leaves three components:

Container What it does What it persists
Server API, flows, SSO requests, and the embedded outpost that serves proxy providers /data, for uploaded icons and backgrounds
Worker Background tasks — email, notifications, scheduled jobs /certs and /templates, both optional
PostgreSQL All configuration and state, now including sessions and cache The database directory, and this is the one that matters

The removal is not free: authentik’s own note says to expect “roughly 50% more database connections to Postgres”, because everything Redis used to hold now lives there. On a small box that is a connection-limit question rather than a memory one.

If you are upgrading rather than installing fresh, the Redis container does not remove itself. The project's upgrade instructions pass --remove-orphans for exactly that reason. Leave it out and you keep paying for a container nothing talks to any more.

What Does It Take to Run?

A host with at least 2 CPU cores and 2 GB of RAM, which is the requirement on authentik’s Docker Compose installation page (checked 10 September 2026). That floor is a real constraint on the class of machine this site usually writes about: a five-dollar VPS with 1 GB does not clear it. The server image publishes only linux/amd64 and linux/arm64, checked against the container registry on 10 September 2026, so a Raspberry Pi works while a 32-bit Raspberry Pi OS has no image to pull.

Installation is a download rather than a compose file you write. Fetch the project’s compose.yml, then generate two secrets into a .env file beside it:

echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env

Use the project’s file rather than one from a tutorial, because it pins the version: the documentation notes that compose.yml “statically references the latest version available at the time of downloading”, which is why upgrading means downloading it again. What it amounts to, with the current stable tag:

services:
  server:
    image: ghcr.io/goauthentik/server:2026.8.2
    command: server
    environment:
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
    ports:
      - "9000:9000"

  worker:
    image: ghcr.io/goauthentik/server:2026.8.2
    command: worker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  postgresql:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: ${PG_PASS}
    volumes:
      - database:/var/lib/postgresql/data

volumes:
  database:

2026.8.2 is the current stable release, read from the project’s git tags and confirmed present in the registry on 10 September 2026. PostgreSQL 14 through 18 are supported, so 16-alpine sits comfortably inside the window. The Docker for self-hosting guide covers the compose vocabulary this leans on.

Three details catch people out. The server listens on 9000 for HTTP and 9443 for HTTPS internally, and the published ports change through COMPOSE_PORT_HTTP and COMPOSE_PORT_HTTPS in .env rather than by editing the YAML. The PostgreSQL password cannot exceed 99 characters, which an over-enthusiastic generator will trip. And the worker mounts the Docker socket by default.

That Docker socket mount is real root access. Authentik's documentation says so directly: a container with the socket has "unfettered access to the full Docker API" and it "can also result in possible root escalation on the host system". It is there so authentik can deploy outposts for you. If you do not need that, remove the mount and deploy outposts by hand, or put a socket proxy in front of it — but do not leave it mounted just because the default did.

One more from the same file: do not mount /etc/timezone or /etc/localtime into these containers. Everything internal runs in UTC, and overriding it breaks OAuth and SAML authentication.

Proxy Mode or Forward Auth?

Forward auth, if you already run a reverse proxy — and you almost certainly do.

The proxy provider offers three modes, and the difference is which piece of software carries the application’s traffic:

Mode Who proxies the traffic Use when
Proxy The authentik outpost You have no reverse proxy and want authentik to be it
Forward auth, single application Your existing reverse proxy Each app needs its own policies and bindings
Forward auth, domain level Your existing reverse proxy Many apps share a parent domain and the same access rules

Domain-level mode is the seductive one: configure it once, and everything under *.example.com is protected without a provider per application. The cost is stated plainly in the documentation — it “cannot enforce different application-level authorization rules for each protected application”. One rule for everyone.

That works for a household where all three of you get the same access to everything, and stops working the moment one service should be yours alone. Retrofitting single-application mode later means creating a provider per app anyway.

How Do You Put a Login in Front of an App That Has None?

By pointing your proxy at authentik’s auth endpoint before it forwards the request. In Nginx terms that is auth_request, and the Nginx Proxy Manager setup takes it in the Advanced tab of the proxy host:

location / {
    proxy_pass          $forward_scheme://$server:$port;
    auth_request        /outpost.goauthentik.io/auth/nginx;
    error_page          401 = @goauthentik_proxy_signin;
    auth_request_set    $auth_cookie $upstream_http_set_cookie;
    add_header          Set-Cookie $auth_cookie;

    auth_request_set    $authentik_username $upstream_http_x_authentik_username;
    proxy_set_header    X-authentik-username $authentik_username;
}

# every request here must work without authentication
location /outpost.goauthentik.io {
    proxy_pass          http://authentik:9000/outpost.goauthentik.io;
    proxy_set_header    Host $http_host;
    proxy_set_header    X-Original-URL $scheme://$http_host$request_uri;
    proxy_pass_request_body off;
    proxy_set_header    Content-Length "";
}

Read the comment on that second block rather than skimming it. The /outpost.goauthentik.io path is how the browser reaches the login flow, so protecting it with the thing it is trying to authenticate against gives a redirect loop and no useful error.

Two more lines from the same template look like unrelated bugs when they bite: proxy_buffers 8 16k with proxy_buffer_size 32k heads off the “upstream sent too big header” failure, because the identity headers push responses past the default buffer, and port_in_redirect off stops Nginx rewriting redirects to an internal port.

A typo in Unauthenticated Paths fails open, quietly. Each line is a regular expression, and authentik's documentation says a pattern that fails to compile is skipped with a warning in the outpost log while the remaining patterns still apply. You do not get an error — you get a path you meant to expose staying protected, or worse, a rule you meant to scope narrowly never applying. Check the outpost log after editing that field.

Why Does It Load Forever Behind a Reverse Proxy?

Because authentik thinks your HTTPS request was HTTP, and version 2026.8 made that much easier to trigger. From that release the server “only uses forwarded request headers such as X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-For when the connection comes from a trusted proxy network”; earlier versions were inconsistent about it. The change is a genuine security fix — it stops a client forging its own proxy headers — and it breaks working setups on upgrade.

Symptoms, from the documentation’s troubleshooting list: an endless loading spinner, a generic authentication error, or a browser complaining about blocked mixed content. All three are one fault — authentik generating http:// URLs for a page loaded over https://.

The trusted list defaults to the private ranges and loopback: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fe80::/10 and ::1/128. A reverse proxy sharing a Docker network on the same host is already inside it, which is why most people never meet this. Set AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS if yours is not, and note that it replaces the default list rather than extending it.

Your proxy also has to speak HTTP/1.1 or newer and pass WebSocket upgrade headers through, since outposts reach the server over WebSockets. HTTP/1.0 proxies are not supported.

Is a Password on the App Enough?

Often, yes — and this is the section the enthusiastic guides do not write.

✅ Worth the three containers

  • You run something with no authentication of its own and want it reachable from outside
  • More than a couple of people use the services, and you want to remove one person's access in one place
  • You want group-based rules — family sees these apps, you see all of them
  • You are already running PostgreSQL for something else and know how to back it up

❌ Skip it

  • Every app you run already has a login and there are two of you
  • The services are only ever reached over Tailscale or another mesh VPN, where the network is the access control
  • Your host has 1 GB of RAM, which is below the documented minimum
  • You would not notice for a week if the database were corrupt

That last bullet deserves more room. Once authentik is in the path, its PostgreSQL volume stands between you and every service you own. Losing it does not lose your data; it locks you out until you rebuild the identity provider from nothing. The database goes into your Docker volume backup routine the day you install it, not the week after you need it.

For two or three people whose services all have their own logins, authentik is a convenience bought with a database — a fair trade if you enjoy running it, but not a security upgrade. The security upgrade is forward auth in front of the app that had nothing, and you can run that for one application without moving anything else behind it.

Frequently Asked Questions About Authentik

Does authentik still need Redis?

No. authentik removed the Redis dependency in version 2025.10, having already moved background tasks to PostgreSQL in 2025.8. Caching, the embedded outpost’s session store and WebSocket connections moved across at the same time. Any guide showing a four-service compose file with a Redis container predates that release. The project notes the change costs roughly 50% more database connections.

How much memory does authentik need?

The project’s Docker Compose installation page asks for a host with at least 2 CPU cores and 2 GB of RAM, checked 10 September 2026. That is the documented minimum for the whole stack rather than a measured idle figure, and it is the number to plan against instead of a RAM reading from a blog post, which was taken on somebody else’s hardware.

Can I run authentik on a Raspberry Pi?

Only on a 64-bit operating system. The server image publishes linux/amd64 and linux/arm64 and nothing else, checked against the registry on 10 September 2026, so a 32-bit Raspberry Pi OS has no image to pull. A Pi 4 or 5 running 64-bit Raspberry Pi OS clears the 2 GB requirement, though PostgreSQL on an SD card is the part that will hurt.

Why does authentik load forever behind my reverse proxy?

Usually because it is reading an HTTPS request as HTTP. From version 2026.8 authentik only trusts forwarded headers such as X-Forwarded-Proto when the connection arrives from a trusted proxy network, and the default list covers the private ranges plus loopback. If your reverse proxy connects from an address outside those ranges, set the trusted proxy CIDR option to include it — that setting replaces the default list rather than adding to it.

What is the difference between forward auth single application and domain level?

Single-application mode gives each protected application its own provider, policies and bindings in authentik. Domain-level mode uses one provider for every application under a shared parent domain, so you configure it once and users authorize once, but you cannot restrict individual applications to different users. Choose single-application mode whenever two apps need different access rules.

Do I need authentik if only two people use my server?

Probably not. If every service you run has its own login and both of you are willing to use a password manager, authentik adds a database and two containers to back up and gains you convenience rather than security. The case that justifies it is an application with no authentication of its own, where the alternative is leaving it open.

Product links on this site are plain links. We earn nothing from them — see our disclosure policy.