What the stack runs
authentik is an open-source identity provider. Applications sign users in against it over OAuth2/OpenID Connect, SAML, LDAP, RADIUS or a proxy provider, and every login is a flow: a sequence of stages (identification, password, login) you can rearrange in the admin interface. The official Compose file starts three services:
| Container | Job | Persistent path |
|---|---|---|
| server | Core API, flow execution, SSO endpoints, and the embedded outpost for proxy providers | ./data (uploaded icons, flow backgrounds, CSV reports), ./custom-templates |
| worker | Background tasks: email, event notifications, outpost deployment through the Docker socket | ./data, ./certs, ./custom-templates |
| postgresql | All configuration and user data, except uploaded files | named volume database |
LDAP, RADIUS, proxy and RAC providers run in an outpost, a separate service that talks to the core over the API and websockets. On Docker Compose the worker creates outposts itself through /var/run/docker.sock, which is why the Compose file mounts the socket into the worker (the file also runs the worker as root).
Requirements and sizing
The installation guide asks for a host with at least 2 CPU cores and 2 GB of RAM, plus Docker Compose v2 or Podman. That page covers the Compose method, which the docs describe as suited to test setups and small-scale production; they also cover a Kubernetes install and a high-availability guide. The docs give no per-user or per-login figure, so anything above the minimum is your own estimate.
Our reading: memory goes first, because PostgreSQL caches its working set in RAM and the Compose file sets shm_size: 512mb on both the server and the worker, a ceiling on their shared memory rather than a fixed reservation. Cores matter when many logins land at once. Disk needs room for the images, the database, and the dumps you retain, one of them taken before every upgrade.
On the dedicated server range, a Moonshot cartridge with 8 cores and 8 to 32 GB clears the minimum several times over for a team-sized directory and keeps the identity service off the machines it protects. A racked single-socket server suits an instance that also hosts the database for other apps, and it adds a full out-of-band console. Racked machines are handed over in about 30 minutes once payment is approved.
Install with the ports on loopback
Docker's -p-style port publishing writes its own iptables rules, so ufw does not filter it, and an unqualified mapping listens on IPv4 and IPv6 alike. Set ufw to allow SSH only before the first start, then hold authentik's two listeners on 127.0.0.1. The COMPOSE_PORT_HTTP and COMPOSE_PORT_HTTPS variables are the docs' way to change the published ports; giving them an address prefix is our use of them, and it leaves nothing bound on [::].
sudo ufw allow OpenSSH && sudo ufw enable
sudo mkdir -p /opt/authentik && cd /opt/authentik
sudo wget https://docs.goauthentik.io/compose.yml
sudo touch .env && sudo chmod 600 .env
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" | sudo tee -a .env >/dev/null
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" | sudo tee -a .env >/dev/null
echo "COMPOSE_PORT_HTTP=127.0.0.1:9000" | sudo tee -a .env >/dev/null
echo "COMPOSE_PORT_HTTPS=127.0.0.1:9443" | sudo tee -a .env >/dev/null
sudo chmod 600 .env
sudo docker compose pull && sudo docker compose up -d
sudo ss -tlnp | grep -E ':(9000|9443) '
The two openssl rand lines are the documented way to generate the database password and the secret key; the docs note that PostgreSQL does not support passwords longer than 99 characters, and 36 random bytes come out as 48 in base64. Creating .env with mode 600 before writing to it, and setting it again after, keeps both secrets readable by root alone. The last command should list 127.0.0.1 only. Leave /etc/localtime unmounted: the docs warn that authentik runs on UTC internally and a mounted timezone breaks OAuth and SAML.
Claiming akadmin privately
A fresh instance has an akadmin account with no password. The initial-setup flow asks the first visitor to set one, and nothing checks who that visitor is. Open it over an SSH tunnel under your own login, before any DNS name or proxy points at the box.
- From your workstation:
ssh -L 9000:127.0.0.1:9000 you@your-server. - Open
http://localhost:9000/if/flow/initial-setup/and set the email and password for akadmin. - Sign in and add a named admin account for yourself before anyone else can reach the login page.
- If the flow will not load, the troubleshooting page says to restart the containers first; if that fails,
docker compose exec server ak changepassword akadminsets the password directly, as a last resort.
Reverse proxy and TLS
authentik needs a proxy that speaks HTTP/1.1 or newer, because outposts hold websocket connections, and it must forward Host, X-Forwarded-Proto, X-Forwarded-For and the upgrade headers. It honours forwarded headers only from trusted networks; the defaults include 127.0.0.0/8 and the private ranges Docker's bridges draw from, so nginx on the same host needs no change to AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS. Adapted from the docs' nginx example, pointed at the loopback HTTP listener:
map $http_upgrade $connection_upgrade_keepalive {
default upgrade;
'' '';
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sso.example.com;
ssl_certificate /etc/letsencrypt/live/sso.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sso.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade_keepalive;
}
}
Then sudo ufw allow 80,443/tcp. An endless spinner or mixed-content errors after this step usually mean X-Forwarded-Proto is not reaching authentik as https.
Backups and upgrades
The backup guide calls PostgreSQL the most important part: users, flows, policies and configuration all live there. Dump it with native tools and copy the result off the host; tuning the database itself is covered on our PostgreSQL dedicated server page. From a cron script, use exec -T so Compose does not ask for a terminal:
cd /opt/authentik
docker compose exec -T postgresql pg_dump -U authentik -d authentik -cC > /var/backups/authentik-$(date +%F).sql
tar czf /var/backups/authentik-files-$(date +%F).tgz data certs custom-templates .env
chmod 600 /var/backups/authentik-*
If you mount custom blueprints into /blueprints, add that folder to the archive; the backup guide recommends it. The stock compose.yml does not mount it. The archive holds .env, so it carries both secrets; keep it private. Changing AUTHENTIK_SECRET_KEY ends every active session. To upgrade, download the new compose.yml, which pins a fixed release, then docker compose pull and up -d. authentik cannot be downgraded, so dump the database first, never skip a major version (take each one to its newest .x release before moving on), and upgrade outposts at the same time: their version must match the server.
Where this setup stops
One Compose host is one point of failure for every application that signs in through it. If the identity service must survive a machine loss, follow the high-availability guide or Kubernetes instead. The docs flag the worker's Docker socket mount as a security risk: put a socket proxy in front of it, or remove the mount and deploy outposts by hand. If you are weighing Keycloak instead, our self-hosted Keycloak page covers its production mode on one machine.
Questions
What hardware does authentik need?
The Docker Compose guide sets the floor at 2 CPU cores and 2 GB of RAM, and positions that method for tests and small-scale production. It publishes no per-user sizing. Memory headroom for PostgreSQL is the first thing worth adding above the minimum.
Can I run authentik without Docker?
The documented paths are Docker Compose (or Podman), Kubernetes with the Helm chart, and AWS CloudFormation. Everything on this page follows the Compose route, which the docs describe as suited to test setups and small-scale production.
Is the initial setup page dangerous to leave open?
Yes, until it has been used. The first person to complete /if/flow/initial-setup/ sets the akadmin password. Keep ports 9000 and 9443 on loopback and finish the flow over an SSH tunnel before a proxy publishes the instance.
Does authentik still need Redis?
The current compose.yml defines only postgresql, server and worker, so there is no Redis container to run or back up. If you upgrade an older install, read the release notes for every version you pass through.
What do I lose if I lose the database?
Everything that matters: the backup guide says the PostgreSQL database holds users, policies, flows and configuration, and losing it means full application data loss. Uploaded files in ./data and custom templates are restorable separately.
Can the LDAP outpost run on the same machine?
Yes. On Docker Compose the worker can deploy outposts locally through the Docker socket integration, or you can run them yourself from their own Compose file. Each outpost has to match the server's release.