How to Set Up Authentik with Docker Compose

Install Authentik with Docker Compose, set your first admin, and put a login in front of an app that never had one — a step-by-step homelab walkthrough.

On this page
  1. Task 1: Install Authentik with Docker Compose
  2. Task 2: Set your first admin and look around
  3. Task 3: Create your first application and provider
  4. Task 4: Put a login in front of an app that has none
  5. Where to go next

In the overview post I made the case for running a single front door for your homelab. This is the part where we actually build it. By the end you’ll have Authentik running, a real admin account, and — the fun part — a login screen sitting in front of an app that shipped without one.

I’ll keep this grounded: every command here is the one from Authentik’s own installation docs, and every screenshot comes from a fresh Authentik 2026.8.5 install I walked through on 21 October 2026. I’ve flagged the two places it tripped me up.

First: make these values your own

This guide uses placeholder values so it stays safe to publish. Swap them for yours before you paste:

  • 10.0.0.20 — the IP (or hostname) of your Docker host running Authentik.
  • auth.homelab.lan — the internal DNS name you’ll reach Authentik at.
  • app.homelab.lan — the internal DNS name of the test app you’ll protect.
  • The akadmin password — you’ll set this yourself on first launch; keep it in your password manager, never in a note.

Rule of thumb: if a value looks specific to one machine, it’s a placeholder to change — not a literal to copy.


Task 1: Install Authentik with Docker Compose

1Check the prerequisites2 min

You need a host with Docker and the Compose v2 plugin, 2 CPU cores and 2 GB of RAM minimum. If you’re on Proxmox, an LXC container or a small VM both work — Authentik doesn’t care which.

Confirm Compose v2 is present (note the space — docker compose, not the old docker-compose):

Verify Docker Compose v2

docker compose version
2Download the compose file1 min

Authentik publishes a maintained compose.yml. Make a folder for the stack and pull it in:

Fetch the official compose file

mkdir -p ~/authentik && cd ~/authentik
wget https://docs.goauthentik.io/compose.yml

That file defines three services: the server, a worker, and a PostgreSQL database. (Recent Authentik releases dropped the separate Redis container from the official Compose file.) You don’t need to edit it.

3Generate the secrets2 min

Authentik needs two secrets: a database password and an application secret key. Never invent these by hand — generate real random values and append them to a .env file that Compose reads automatically:

Create the .env with strong random secrets

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

That file now contains your database password and the key that signs every session token. Keep it out of Git, off shared notes, and back it up somewhere private — if you lose AUTHENTIK_SECRET_KEY, existing sessions and tokens break.

Optionally, if you want Authentik to reach it on the standard web ports instead of 9000/9443, add these two lines to the same .env before starting — though if a reverse proxy will front it, leave the defaults:

Optional: use ports 80 and 443

echo "COMPOSE_PORT_HTTP=80" >> .env
echo "COMPOSE_PORT_HTTPS=443" >> .env
4Pull and start the stack5 min
Bring Authentik up

docker compose pull
docker compose up -d

The first pull downloads a few hundred megabytes and the database initializes on first boot, so give it a few minutes. Watch docker compose ps until the worker shows healthy: the worker creates the initial-setup flow on first boot, and until it has, the setup page in the next task won’t load. On a 2-vCPU VM that took about two and a half minutes in my re-test. If the page still won’t load once everything is healthy, Authentik’s docs suggest restarting the containers.


Task 2: Set your first admin and look around

1Run the initial-setup flow3 min

Open the root of the server in a browser. Authentik notices it hasn’t been set up yet and starts the first-run flow for you:

Initial setup — start from the root

http://10.0.0.20:9000/
Don't jump straight to the setup flow

Older guides (this one included, before this update) send you to /if/flow/initial-setup/ directly. On Authentik 2026.8.5 that’s refused with Request has been denied, and the message tells you to open the root URL instead. The setup flow only runs when you enter it from /.

The form asks for four things:

  • Email — the address for the built-in akadmin account, the default superuser.
  • Password and Password (repeat) — there is no pre-set password to look up; whatever you type here becomes it. Put it straight into your password manager.
  • Base URL — the address Authentik should use when it builds links for itself. Use the URL you’ll actually reach it at, with no path on the end. If you’ll put it behind a reverse proxy later, that’s your HTTPS name, such as https://auth.homelab.lan.
http://10.0.0.20:9000/
The first-run form on Authentik 2026.8.5. Base URL is new: it's the address Authentik uses when it builds its own links.
2Find the two interfaces2 min

Authentik has two faces, and knowing which is which saves confusion:

  • User interface (/) — the tile dashboard your family or teammates see: just the apps they’re allowed to open.
  • Admin interface (/if/admin/) — where you, as akadmin, configure everything: applications, providers, flows, and users.

Everything below happens in the admin interface. Sign in as akadmin and head there.

Do the boring hardening now

Before you wire up apps, give akadmin a second factor. In the user interface, click the gear icon at the top right, open Credentials, and under MFA Devices click Enroll to add a TOTP app or a passkey. MFA on the account that controls every other login is the whole point of running an identity provider.

Gear icon → Credentials → MFA Devices. Enroll opens the TOTP and passkey options.

Task 3: Create your first application and provider

In Authentik, a provider is how it integrates with a service, and an application is the tile that points at that provider and decides who may use it. The admin interface builds both at once.

1Open the application wizard1 min

In the admin interface, go to Applications → Applications and click New Application. That opens a short wizard that creates the application and a new provider together. (The dropdown beside the button also offers with Existing Provider… if you ever build a provider separately first.)

2Walk the four stages4 min

The wizard walks four short steps:

  1. Application — a name (say, “Grafana”) and an optional group.
  2. Choose a Provider — pick the protocol the app speaks. Modern apps use OAuth2/OpenID Connect; an app with no login of its own uses Proxy.
  3. Configure Provider — accept the auto-filled name and choose the authorization flow (the default default-provider-authorization-explicit-consent is fine to start).
  4. Configure Bindings — leave empty for now to allow everyone, or bind a group later to restrict access.

On the Review and Submit Application panel, check the summary and click Create Application. You’ve now got a working application and its provider in one pass.

Step 2 of the wizard. Scroll the grid for Proxy, LDAP, RADIUS and SCIM.
Note

For an OAuth2/OIDC app, this is where Authentik hands you the Client ID, Client Secret, and the OpenID configuration URL. You paste those into the app’s own “single sign-on” settings — each app words it slightly differently, but it always wants those three things. Treat the Client Secret like a password: it goes into the app’s config and your password manager, never into a screenshot or a chat message.


Task 4: Put a login in front of an app that has none

This is the trick that makes Authentik feel like magic: taking a bare dashboard with no auth and giving it a real login — no code changes to the app. It works through a Proxy provider and forward authentication, where your reverse proxy asks Authentik to vet each request first.

Here’s the shape of a single request once it’s wired up:

One request through forward authenticationBrowserapp.homelab.lanReverse proxyforwardAuthAuthentikoutpost checkThe appsigned in → allowLogin pageno session → redirectThe proxy never trusts the request itself — it asks Authentik, every time.
1Create a Proxy provider3 min

Run the same Applications → Applications → New Application wizard, but at the Choose a Provider step pick Proxy. Set it to Forward auth (single application) and set External host to the URL you’ll use, e.g. https://app.homelab.lan. Authentik’s built-in embedded outpost answers the forward-auth checks, so there’s nothing extra to deploy for a first app.

2Add the app to the embedded outpost2 min

This is the step I missed on my first pass. The embedded outpost only answers for applications assigned to it, and in my 2026.8.5 walk-through the wizard didn’t add the new proxy app for me. Until you do, the Providers column for the outpost shows a dash and forward auth has nothing to check against.

Go to Applications → Outposts, click the edit icon on authentik Embedded Outpost, move your app from Available Applications to Selected Applications, and click Save Changes.

Applications → Outposts → edit the embedded outpost. Move the app across, then Save Changes.

Back on the list, the outpost’s Providers column now names your proxy provider:

Before this step the Providers column showed a dash. Now the embedded outpost serves the test app.
3Point your reverse proxy at the outpost5 min

Now tell your proxy to check with Authentik before serving the app. With Traefik, that’s a forwardAuth middleware pointed at the embedded outpost’s auth endpoint:

Traefik forwardAuth middleware (dynamic config)

http:
  middlewares:
    authentik:
      forwardAuth:
        address: http://10.0.0.20:9000/outpost.goauthentik.io/auth/traefik
        trustForwardHeader: true
        authResponseHeaders:
          - X-authentik-username
          - X-authentik-groups
          - X-authentik-entitlements
          - X-authentik-email
          - X-authentik-name
          - X-authentik-uid
          - X-authentik-jwt
          - X-authentik-meta-jwks
          - X-authentik-meta-outpost
          - X-authentik-meta-provider
          - X-authentik-meta-app
          - X-authentik-meta-version

Attach that authentik middleware to the router for app.homelab.lan. The address is the embedded outpost’s Traefik endpoint; trustForwardHeader lets Authentik see the original host, and the response headers pass the signed-in user’s identity (username, groups, email and more) down to the app. That header list matches Authentik’s own Traefik example, and this exact middleware is the one I tested end to end on Traefik v3.

4Test it end to end2 min

Open https://app.homelab.lan in a private browser window. Instead of the app, you should land on Authentik’s login page. Sign in, and because the wizard’s default authorization flow is the explicit consent one, Authentik asks once whether to let the app see your details:

The explicit-consent flow, the wizard's default, asks once per app. Pick the implicit-consent flow if you'd rather skip it.

Click Continue and you’re bounced straight through to the app, now wearing a login it never had. That round trip is the win.

For my test I put traefik/whoami, which simply echoes the request it receives, behind the middleware. Trimmed and with the values replaced, this is what arrived after sign-in:

What the app receives after sign-in (trimmed, values replaced)

X-Authentik-Username: akadmin
X-Authentik-Groups: authentik Admins
X-Authentik-Email: admin@homelab.lan
X-Authentik-Name: authentik Default Admin
X-Authentik-Jwt: eyJhbGciOi...  (a signed token, trimmed)
X-Authentik-Meta-Outpost: authentik Embedded Outpost
X-Authentik-Meta-Provider: Provider for Test Proxy App
X-Authentik-Meta-Version: goauthentik.io/outpost/2026.8.5

The app never handled a password. It got a set of headers saying who you are and which groups you’re in, and apps that support header auth can log you in from those alone.

Those headers are credentials

A real dump of these headers holds your email address, a signed JWT and the session cookie. Don’t paste one into a forum post or an issue tracker. And only trust the X-Authentik-* headers on an app that can’t be reached except through the proxy: if the app’s own port is open on the network, anyone can send it headers that claim to be you.

Keep a way back in

Forward auth means Authentik now gates that app. Before you protect anything critical, make sure you have a break-glass path — a local admin account on the app itself, or proxy access that bypasses auth — so a misconfigured flow can’t lock you out of your own service.


Where to go next

You’ve got Authentik running, a hardened admin, and one app protected. The natural next moves are to bind a group to that application so only certain users see it, and to convert your OAuth2-capable apps (Grafana, Immich, and friends) from their own logins over to single sign-on one at a time. Do them one per evening — it’s oddly satisfying watching the separate passwords disappear.


Related posts:

Sources: Authentik installation docs, Authentik Traefik proxy docs.

Comments

Comments are powered by GitHub Discussions — sign in with a GitHub account to join the conversation.