Authentik vs Keycloak, in short: choose Keycloak when your apps already speak OpenID Connect or SAML and you want the lighter, faster server, and choose authentik when you also need an LDAP server for older devices or a login screen in front of apps that have none. In our lab test on 18 October 2026, on one server with 2 vCPUs and 3 GB of RAM, Keycloak 26.8.1 with PostgreSQL used about 0.6 GB of memory at idle and finished a full login in about 0.06 seconds, while authentik 2026.8.4 used about 1.1 GB and needed 2.1 seconds.
Both have a free, open-source edition, and both are fine for a small company's single sign-on. Keycloak fits our VPS hosting plans from VPS Micro upwards; authentik is more comfortable on VPS Mini. Below are the measurements, the Docker Compose setups we ran, and a table that matches each situation to a plan and a city.
Key facts, checked on 18 October 2026:
- authentik 2026.8.4 is the current release, published on 14 October 2026 (authentik releases). Security fixes go to the 2026.8.x and 2026.5.x lines only (authentik security policy).
- Keycloak 26.8.1 is the current release, published on 13 October 2026 (Keycloak downloads). Version 26.8.0 arrived on 1 October 2026 with SCIM provisioning and client secret rotation as supported features (Keycloak blog).
- authentik's core is MIT licensed, with a separate licence for its
authentik/enterprisefolder (LICENSE). Enterprise costs $5 per user per month, billed annually (authentik pricing). Keycloak is Apache 2.0 licensed and has been a CNCF incubating project since 10 April 2023 (CNCF). - authentik asks for "at least 2 CPU cores and 2 GB of RAM" (authentik Docker Compose docs). Keycloak's container guide recommends a 2 GB memory limit for smaller production deployments and caps the Java heap at 70% of the container's memory (Keycloak containers guide).
- Keycloak's sizing guide plans 1 vCPU for every 15 password logins per second (Keycloak CPU and memory sizing).
Authentik or Keycloak: which should a small company choose?
Five questions settle it for most offices.
- Does a NAS, printer, old wiki or VPN box need LDAP? authentik can act as an LDAP server through an outpost. Keycloak can only read users from an existing LDAP or Active Directory server.
- Do some web apps have no login integration at all? authentik's proxy provider puts its own login in front of them. With Keycloak you add a separate tool such as oauth2-proxy.
- Is the server small? Keycloak used about half of authentik's memory in our test: 0.6 GB against 1.1 GB at idle.
- Will many people log in at the same moment? On 2 vCPUs, Keycloak handled about 30 logins per second and authentik about 0.6.
- Do you want a project with no paid tier of its own and a foundation behind it? That is Keycloak.
A yes to question 1 or 2 usually points to authentik, even on a small server. If both answers are no, Keycloak is the leaner choice.
What is self-hosted SSO? The terms in plain words
Single sign-on (SSO) means each person logs in once, in one place, and every connected app trusts that login. Self-hosted SSO means the software that holds those logins runs on your own server instead of a cloud service such as Microsoft Entra ID or Okta. For a small company that means one password and one two-factor setup per employee, and one switch to turn off when someone leaves.
- An identity provider (IdP) keeps the users and their passwords, and every other app asks it who is logging in. authentik and Keycloak are both IdPs.
- OpenID Connect (OIDC) is the usual modern login protocol: the app sends you to the IdP, the IdP sends you back with a one-time code, and the app swaps the code for tokens. Grafana, Forgejo, Nextcloud, Headscale and NetBird support it.
- SAML 2.0 is an older XML-based login protocol that many business web apps still use.
- LDAP is a directory protocol from the 1990s that NAS boxes, printers and older software expect.
- SCIM is a standard for creating and removing user accounts in other apps automatically.
- Forward auth means the reverse proxy asks the IdP before it lets a request through, so an app gets a login without code changes.
The two products use different words for similar things. Keycloak keeps users in realms and calls apps clients. authentik gives each application a provider, builds logins from flows and stages, and runs LDAP and proxy logins in helper services called outposts.
They are also built differently. Keycloak is a Java application, built on Quarkus, that runs as one container next to a database such as PostgreSQL. authentik runs as two containers from the same image, a web server and a background worker, plus PostgreSQL; the official 2026.8 Compose file has no Redis. SSO is often what ties a self-hosted office together, and our guide to moving an office off Microsoft 365 or Google Workspace shows where it fits.
Authentik vs Keycloak feature comparison
| Question | authentik 2026.8 | Keycloak 26.8 |
|---|---|---|
| Best fit | A team of 5 to a few hundred with mixed apps, including old ones that need LDAP or header logins | Teams whose apps speak OIDC or SAML, developers building their own apps, a later path to clustering |
| What runs | Server and worker containers from one 1.95 GB image, plus PostgreSQL | One Java container (752 MB image), plus PostgreSQL 14 to 18 |
| OIDC and SAML | Both, plus SCIM, RADIUS and Kerberos | Both, plus OAuth 2.0 and SCIM (supported since 26.8) |
| LDAP | Serves LDAP through an outpost (tested below) | Reads users from LDAP and Active Directory; does not serve LDAP |
| Login for apps without SSO | Proxy provider with forward auth for Caddy, Nginx and Traefik | Needs a separate proxy such as oauth2-proxy |
| Two-factor login | TOTP, WebAuthn and passkeys, recovery codes, Duo, SMS, email | TOTP and HOTP apps, WebAuthn and passkeys, recovery codes |
| Admin work | One web interface; a "New Application" wizard creates the app and its provider together | More settings (realms, clients, scopes, mappers) and a CLI, kcadm.sh, that scripts everything |
| RAM in our lab | 1.1 GB idle, 1.4 GB whole server at peak | 0.6 GB idle, 0.85 GB whole server at peak (1 GB limit) |
| Logins on 2 vCPUs | About 0.6 per second | About 30 per second |
| Upgrades | A release about every 3 months; fixes for the last two; outposts must match the server version | A minor release about every 3 months; fixes in the current release; long-term support only from the Red Hat build |
| Licence and paid options | MIT core; Enterprise at $5 per user per month | Apache 2.0, CNCF incubating; paid support through the Red Hat build |
Sources for protocols and two-factor: authentik pricing, authentik authenticator docs, the Keycloak homepage and the Keycloak Server Administration Guide. We tested OIDC on both and LDAP on authentik. For SSO in a small business, either one runs on a single server from our VPS plans.
How we tested both on one small server
We tested on 18 October 2026 on our Amsterdam test server (AMD EPYC 7742), in a Debian 13 container limited to 2 vCPUs and 3 GB of RAM, with no swap, Docker 29.9.1 and Compose v5.6.0 from Docker's apt repository. One stack ran at a time, and we deleted it before starting the next.
- authentik 2026.8.4 ran from its official Compose file: server, worker and PostgreSQL 16.
- Keycloak 26.8.1 ran the official image in production mode (
start, notstart-dev) with PostgreSQL 17. - Grafana 13.2.4 was the test app, and a test user signed in to it through each IdP.
- A Python script ran the full OIDC login (authorization URL, username and password, code, token exchange) with 1, 5 and 10 logins in parallel for 60 seconds each, while
docker statssampled memory. Against authentik the script used almost no CPU. In the much faster Keycloak runs it shared the same 2 vCPUs, so Keycloak's figures are, if anything, on the low side.
A container on a shared host is not a full virtual machine, so read the numbers as a fair comparison, not a promise for your server.
How much RAM do authentik and Keycloak need?
In our test on 18 October 2026, authentik 2026.8.4 used 1,103 MiB at idle across its server, worker and PostgreSQL containers, and Keycloak 26.8.1 with PostgreSQL used 572 to 645 MiB, depending on the container memory limit. "Idle" means the stack was up and serving no logins; for authentik we took the reading about 10 minutes after the first start. "Whole server" is the used column of free -m for the 3 GB box, including Docker itself.
| Stack | Idle, per container | Peak during the login loop | Whole server, idle and peak |
|---|---|---|---|
| authentik 2026.8.4 | server 716 MiB, worker 311 MiB, PostgreSQL 76 MiB | server 775 MiB, worker 327 MiB, PostgreSQL 136 MiB | 1,255 MB and 1,405 MB |
| Keycloak 26.8.1, no memory limit | Keycloak 593 MiB, PostgreSQL 52 MiB | Keycloak 647 MiB, PostgreSQL 60 MiB | 825 MB and 907 MB |
Keycloak, mem_limit: 2g | Keycloak 518 MiB, PostgreSQL 53 MiB | Keycloak 566 MiB, PostgreSQL 64 MiB | 739 MB and 822 MB |
Keycloak, mem_limit: 1g | Keycloak 530 MiB, PostgreSQL 61 MiB | Keycloak 586 MiB, PostgreSQL 72 MiB | 760 MB and 849 MB |
authentik's server container holds the web interface, the API and an embedded outpost for proxy logins; the worker runs background jobs. The optional LDAP outpost added 40 MiB.
Set a memory limit for Keycloak
The heap is the block of memory Java reserves for a program's data. Keycloak's container sizes it from the memory it can see: 50% at start, up to 70%. Without a limit, our nested lab let Keycloak see the host's 16 GB, and it set a maximum heap of 11.7 GB. On a VPS it sees the VPS's own memory, so on a 4 GB server the 70% rule works out to a heap of about 2.8 GB. With mem_limit: 1g the maximum heap became 718 MiB, and Keycloak finished every login loop without an error. The Keycloak containers guide puts it plainly: "you should always set the memory limit for the container."
Is Keycloak faster than authentik? Login speed measured
Yes, by a wide margin. On 2 vCPUs, Keycloak 26.8.1 completed about 15 to 31 full logins per second in our test, and authentik 2026.8.4 about 0.5 to 0.6.
| Logins in parallel | authentik: logins per second | authentik: p95 | Keycloak (1 GB limit): logins per second | Keycloak: p95 |
|---|---|---|---|---|
| 1 | 0.47 | 2.30 s | 14.9 | 0.09 s |
| 5 | 0.59 | 9.43 s | 26.9 | 0.26 s |
| 10 | 0.64 | 16.70 s | 31.1 | 0.43 s |
p95 means 95 out of 100 logins finished within that time. Neither stack returned an error. Keycloak without a limit and with a 2 GB limit gave the same results within about 8%.
Why authentik is slower
Two things explain the gap. The first is password hashing, which turns a password into a stored fingerprint and is slow on purpose so that stolen hashes are hard to crack. authentik stored our test user's password as PBKDF2-SHA256 with 1,000,000 iterations, and the password step alone took 0.9 seconds. Keycloak has hashed with Argon2 by default since version 25 (Keycloak 25 release notes); our user's hash used 5 iterations and 7 MB of memory.
The second is the login flow. authentik's login took six requests from start to tokens: the password step, plus five others of 0.2 to 0.4 seconds each. Keycloak needed three. authentik's server peaked at 142% CPU and its PostgreSQL at 120%, where 100% means one full vCPU, so the 2 vCPUs were the limit. Keycloak peaked at 180% with PostgreSQL at 11% or less. Its single-stream result of about 15 logins per second is the same number Keycloak's sizing guide plans per vCPU.
In an office, a login happens once per session, not on every page. With authentik on 2 vCPUs, ten people pressing "log in" at the same moment waited up to about 17 seconds; spread over a few minutes, nobody would notice. If a whole team starts at 9:00 sharp, give authentik more vCPUs. It was CPU-bound, though we did not measure a 4 vCPU box.
How to install authentik with Docker Compose
Start from a secured Debian 13 VPS with Docker Engine and the Compose plugin installed from Docker's repository, as in our Docker setup guide. These are the official steps, plus two lines that keep authentik's ports on localhost behind your reverse proxy and a chmod so that only root can read the passwords in .env:
# as root
apt install -y wget openssl
mkdir -p /opt/authentik && cd /opt/authentik
wget https://docs.goauthentik.io/compose.yml
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env
echo "COMPOSE_PORT_HTTP=127.0.0.1:9000" >> .env
echo "COMPOSE_PORT_HTTPS=127.0.0.1:9443" >> .env
chmod 600 .env
docker compose pull
docker compose up -d
The images are 1.95 GB for authentik and 420 MB for PostgreSQL, so keep about 5 GB free for updates. The first start runs all database migrations; a fresh install in our lab (2026.5.7) answered about 100 seconds after the pull. Check it:
# as root, in /opt/authentik
docker compose ps
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9000/-/health/ready/
All three containers should show Up with (healthy), and curl should print 200. ss -ltn should list 9000 and 9443 on 127.0.0.1 only; in our lab, a request to the server's network address on port 9000 could not connect.
Next, point a name such as auth.example.com at the server and put a reverse proxy with HTTPS in front. In Caddy, the site block for that name needs one line, reverse_proxy 127.0.0.1:9000; our reverse proxy guide covers the full setup. Our lab had no real domain, so it used the private IP over plain HTTP instead.
Open https://auth.example.com/. It redirects to /if/flow/initial-setup/, where 2026.8 asks for an email, a password for the admin user akadmin, and the Base URL. Fill in the Base URL now, because it becomes required in 2026.11 (2026.8 release notes). 2026.8 also trusts proxy headers only from listed networks; the defaults include 127.0.0.0/8 and 172.16.0.0/12, which covers Caddy on the same host (configuration docs).
Note that the official worker container runs as root with the Docker socket mounted, so authentik can start outposts by itself. That is handy, but it gives authentik control of Docker on the server. The install docs say the mount "comes with some inherent security risks" and offer two ways out: a Docker socket proxy, or removing the mount and deploying outposts by hand.
How to run Keycloak on a VPS in production mode
Keycloak has no official Compose file, so this is the one we ran, with example names in place of the lab's IP address. We built it from the containers guide, the database guide (PostgreSQL 14 to 18 are supported) and the reverse proxy guide:
# as root: save as /opt/keycloak/compose.yml
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]
interval: 5s
retries: 10
keycloak:
image: quay.io/keycloak/keycloak:26.8.1
command: start
mem_limit: 1g
restart: unless-stopped
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: ${DB_PASSWORD}
KC_HOSTNAME: https://auth.example.com
KC_PROXY_HEADERS: xforwarded
KC_HTTP_ENABLED: "true"
KC_HEALTH_ENABLED: "true"
KC_BOOTSTRAP_ADMIN_USERNAME: tmpadmin
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
ports:
- "127.0.0.1:8080:8080"
depends_on:
postgres:
condition: service_healthy
volumes:
pg_data:
Use mem_limit: 2g instead if the server has 4 GB or more. KC_PROXY_HEADERS: xforwarded tells Keycloak to trust the X-Forwarded-* headers that your reverse proxy adds. Create the passwords and start:
# as root, in /opt/keycloak
apt install -y curl openssl python3
printf 'DB_PASSWORD=%s\nKC_ADMIN_PASSWORD=%s\n' "$(openssl rand -hex 16)" "$(openssl rand -hex 12)" > .env
chmod 600 .env
docker compose up -d
sleep 40
docker compose logs keycloak | grep "started in"
curl -s -H "X-Forwarded-Proto: https" -H "X-Forwarded-Host: auth.example.com" http://127.0.0.1:8080/realms/master/.well-known/openid-configuration | python3 -c 'import json,sys; print(json.load(sys.stdin)["issuer"])'
Expect a line like Keycloak 26.8.1 on JVM (powered by Quarkus 3.40.1) started in 6.784s. Keycloak first rebuilds its configuration, so start to ready took 24 to 34 seconds in our runs. The last command should print https://auth.example.com/realms/master, which shows the proxy settings work. Put Caddy in front with reverse_proxy 127.0.0.1:8080. Keycloak's reverse proxy guide says /admin/ and /realms/master/ should be reachable "only internally", so limit those paths to your office IP if you can.
Next, a realm for the company, a client for Grafana and a first user. These are the commands we ran, with the lab's realm name and IP address swapped for example names:
# as root, in /opt/keycloak
. ./.env
KC="docker compose exec -T keycloak /opt/keycloak/bin/kcadm.sh"
$KC config credentials --server http://localhost:8080 --realm master --user tmpadmin --password "$KC_ADMIN_PASSWORD"
$KC create realms -s realm=company -s enabled=true
GSEC=$(openssl rand -hex 24); echo "Grafana client secret: $GSEC"
$KC create clients -r company -s clientId=grafana -s enabled=true -s publicClient=false -s secret="$GSEC" -s 'redirectUris=["https://grafana.example.com/login/generic_oauth"]' -s standardFlowEnabled=true -s directAccessGrantsEnabled=false
$KC create users -r company -s username=alice -s enabled=true -s email=alice@example.com -s emailVerified=true -s firstName=Alice -s lastName=Test
$KC set-password -r company --username alice --new-password 'Use-A-Long-Passphrase'
You should see Logging into http://localhost:8080 as user tmpadmin of realm master, then Created new realm with id 'company', and a "Created new" line for the client and the user. The bootstrap account is temporary; Keycloak's docs say it "needs to be removed manually" (bootstrap admin docs). Create your own admin in the master realm, log in with it, then delete tmpadmin.
Connect your first app: Grafana over OpenID Connect
Grafana makes a good first app, because one block of settings covers both IdPs. In authentik, go to Applications, Applications, "New Application", pick OAuth2/OpenID Connect, add the strict redirect URI https://grafana.example.com/login/generic_oauth, select a signing key and note the client ID and secret (authentik Grafana guide).
We created the provider through authentik's API instead and hit one trap: with an empty list of grant types, authentik answered invalid_request and logged Invalid grant_type for provider. Adding authorization_code and refresh_token fixed it. According to authentik's OAuth2 provider docs, the web form selects all grant types by default, so the wizard avoids this trap.
# as root: /opt/grafana/compose.yml, with GF_CLIENT_ID and GF_CLIENT_SECRET in /opt/grafana/.env
services:
grafana:
image: grafana/grafana:13.2.4
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment:
GF_SERVER_ROOT_URL: "https://grafana.example.com"
GF_AUTH_GENERIC_OAUTH_ENABLED: "true"
GF_AUTH_GENERIC_OAUTH_NAME: "authentik"
GF_AUTH_GENERIC_OAUTH_CLIENT_ID: "${GF_CLIENT_ID}"
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: "${GF_CLIENT_SECRET}"
GF_AUTH_GENERIC_OAUTH_SCOPES: "openid profile email"
GF_AUTH_GENERIC_OAUTH_USE_PKCE: "true"
GF_AUTH_GENERIC_OAUTH_AUTH_URL: "https://auth.example.com/application/o/authorize/"
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: "https://auth.example.com/application/o/token/"
GF_AUTH_GENERIC_OAUTH_API_URL: "https://auth.example.com/application/o/userinfo/"
For Keycloak, change the name and the three URLs, and tell Grafana which claims hold the username and display name:
# as root: the lines that differ in /opt/grafana/compose.yml for Keycloak
GF_AUTH_GENERIC_OAUTH_NAME: "Keycloak"
GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH: "preferred_username"
GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH: "name"
GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH: "email"
GF_AUTH_GENERIC_OAUTH_AUTH_URL: "https://auth.example.com/realms/company/protocol/openid-connect/auth"
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: "https://auth.example.com/realms/company/protocol/openid-connect/token"
GF_AUTH_GENERIC_OAUTH_API_URL: "https://auth.example.com/realms/company/protocol/openid-connect/userinfo"
Start it with docker compose up -d in /opt/grafana. Our lab used the server's private IP and plain HTTP instead of these names. There, /login/generic_oauth sent the user to the IdP, and after the password Grafana's /api/user returned 'name': 'Alice Test' and her email, with both authentik and Keycloak. Other apps follow the same pattern; our Forgejo setup guide is a good second one, and Nextcloud, Headscale and NetBird log in over OIDC too.
LDAP, SAML and apps with no SSO support
This is where authentik pulls ahead. We gave it an LDAP provider with base DN dc=ldap,dc=goauthentik,dc=io and an LDAP outpost on its "Local Docker connection". The worker started the outpost container (ghcr.io/goauthentik/ldap:2026.8.4) by itself, and a normal LDAP query worked:
# as root on the authentik server, after apt install -y ldap-utils
ldapsearch -x -H ldap://127.0.0.1:389 -D "cn=akadmin,ou=users,dc=ldap,dc=goauthentik,dc=io" -W -b "dc=ldap,dc=goauthentik,dc=io" "(cn=alice)" cn mail
It returned dn: cn=alice,ou=users,dc=ldap,dc=goauthentik,dc=io, her mail attribute and result: 0 Success; a wrong password gave Invalid credentials (49).
Watch the ports. The outpost published 389 and 636 on all interfaces, and Docker's documentation says such packets are routed "before the firewall rules can be applied", so ufw alone will not close them (Docker and ufw). Run the LDAP outpost only where port 389 should be reachable. In production, bind with a service account that has search rights on the provider, not with akadmin (LDAP provider docs).
We did not test SAML or forward auth; both IdPs list SAML 2.0. For apps without any login support, authentik's proxy provider works with Caddy's forward_auth directive pointed at /outpost.goauthentik.io/auth/caddy, served by the outpost built into the server container. Keycloak has nothing built in for this, so you would add a separate tool such as oauth2-proxy. For apps on a home server, our Pangolin self-hosted tunnel guide puts a login in front of each one.
Upgrading authentik and Keycloak: what we ran
An identity server you never update puts every app behind it at risk, so we upgraded both.
- authentik 2026.5.7 to 2026.8.4: download the new
compose.yml(only the two image tags changed), thendocker compose pullanddocker compose up -d. The pull took 35 seconds, migrations ran, and authentik answered 57 seconds later with the admin login intact. A plain restart took 16 seconds. - Keycloak 26.7.5 to 26.8.1: change the image tag, pull,
up -d. Keycloak logged "Migrating older model to 26.8.0" for each realm, was ready after 34 seconds, and kept our test user.
authentik shipped 2026.2, 2026.5 and 2026.8 this year and patches only the last two; outposts must run the server's version, and 2026.8 blocks upgrades that skip versions it does not support. Keycloak shipped 26.6.0 in April, 26.7.0 in July and 26.8.0 in October 2026. Its security policy fixes issues in the current release or the next and points to the paid Red Hat build for long-term support. Either way, plan a short update window every three months.
Which VPS plan and city for self-hosted SSO
| Your situation | Plan | City | Why |
|---|---|---|---|
| Keycloak for a small team whose apps speak OIDC or SAML, staff across Western Europe | VPS Micro: 2 vCPU, 2 GB RAM, 40 GB NVMe, 1 Gb/s | Amsterdam | With a 1 GB limit, Keycloak and PostgreSQL peaked at 849 MB for the whole server |
| authentik with LDAP or a login for older tools, office in Kosovo or the region | VPS Mini: 4 vCPU, 4 GB RAM, 80 GB NVMe, 1 Gb/s | Prishtina | authentik peaked at 1.4 GB and is CPU-bound at login; Micro meets its 2 GB minimum but leaves little room for a reverse proxy and updates |
| The IdP plus Forgejo, Nextcloud, Grafana or Vaultwarden on one server, team in Ireland | VDS Small: 4 vCPU, 8 GB RAM, 240 GB NVMe, 10 Gb/s | Dublin | Room for several apps, and dedicated vCPUs keep logins quick when everyone starts at once |
VPS plans (Nano, Micro, Mini) have shared vCPUs; VDS plans have dedicated ones. We would not run either IdP on VPS Nano with 1 GB of RAM: our test box, running only Keycloak and PostgreSQL, peaked at 849 MB in use, which leaves almost nothing for a reverse proxy or updates. Our RAM guide for self-hosted apps helps you add up a whole stack, and you can upgrade later from the client area with a short reboot.
For the city, put the IdP near the apps that use it, because each app calls the IdP's token endpoint server to server at every login, and near the people who log in. RS Computers runs KVM servers in Amsterdam, Dublin and Prishtina. In our own ping.pe test of 6 October 2026, probes in Frankfurt and London reached our Amsterdam server in 6.6 and 6.7 ms, and our Prishtina server answered Vienna in 18.6 ms. Skopje is about 3 ms from Prishtina on our own network, which suits teams in Kosovo and North Macedonia. Dublin suits teams in Ireland. If your policy requires storage in the EU, Amsterdam and Dublin are inside it. Availability by city is on the plans page.
Frequently asked questions
Is authentik better than Keycloak?
They suit different offices. authentik is better when you need an LDAP server or a login in front of apps without SSO support. Keycloak is lighter and faster: in our test on 2 vCPUs on 18 October 2026, it used about 0.6 GB of RAM at idle against authentik's 1.1 GB, and handled about 30 logins per second against 0.6.
How much RAM do authentik and Keycloak need?
authentik officially needs at least 2 CPU cores and 2 GB of RAM; in our test, authentik 2026.8.4 used 1.1 GB across its three containers at idle, and the whole server peaked at 1.4 GB. Keycloak 26.8.1 with PostgreSQL used about 0.6 GB at idle and ran without errors under a 1 GB container limit. Always set that limit, because Keycloak's Java heap can grow to 70% of the memory it sees.
Which is easier to set up, authentik or Keycloak?
authentik is simpler to get running: it ships an official Docker Compose file, its first-run page asks only for an email, a password and the Base URL, and a wizard creates each app with its provider. Keycloak has no official Compose file and more settings to learn, such as realms, clients, scopes and mappers, but its kcadm.sh command line scripts the whole setup.
Is authentik free for commercial use?
Yes. authentik's core is MIT licensed, and its free version includes OIDC, SAML, LDAP, SCIM, RADIUS, Kerberos and proxy providers. Features such as the Microsoft Entra ID and Google Workspace integrations need the Enterprise plan, listed at $5 per user per month, billed annually, on 18 October 2026.
Can Keycloak act as an LDAP server?
No. Keycloak reads and syncs users from an existing LDAP or Active Directory server, but it does not answer LDAP queries itself. If a NAS, printer or older app logs users in over LDAP, authentik's LDAP outpost can serve it, as it did in our test.
Can I run the identity provider on the same VPS as my apps?
Yes, and for a small company it is the simplest setup. Put both behind one reverse proxy and keep the IdP's ports on 127.0.0.1. Plan on about 1.5 GB for authentik or 1 GB for Keycloak, plus the apps. With several apps, an 8 GB server such as VDS Small is comfortable.
One login, one server, then add the apps
Start with the IdP and one app, such as Grafana or Forgejo, and move the rest over one by one. If your apps all speak OpenID Connect, a Keycloak VPS on the Micro plan is the lean route. If you also need LDAP or a login in front of older tools, authentik on VPS Mini is the practical one. Compare sizes and cities on our VPS hosting plans page, or ask us on Telegram if you want the setup work quoted for your team.