Pocket ID vs Authentik vs Zitadel: Self-Hosted SSO on a VPS in 2026

Pocket ID vs Authentik vs Zitadel: Self-Hosted SSO on a VPS in 2026

By Fanny Engriana · · 10 min read · 11 views

If you run more than three internal tools, you eventually hit the same wall I did: every dashboard wants its own login, your password manager turns into a junk drawer, and rotating credentials across a team becomes a Friday afternoon ritual nobody wants. Self-hosted single sign-on (SSO) fixes this — but the three top options going into mid-2026 (Pocket ID, Authentik, and Zitadel) take wildly different approaches, and the wrong pick will either cost you a $20/month VPS upgrade or six weekends of YAML tuning.

I run authentication across a portfolio of 7 aggregator sites at Warung Digital Teknologi (wardigi.com) plus a dozen internal admin panels — everything from Grafana dashboards to file browsers to private deploy hooks. I've put all three identity providers on bare Hetzner CX22 boxes (€4.50/month) and Hostinger KVM 2 VPS instances over the past year. This is the comparison I wish I'd had before I started.

Server racks managing centralized identity infrastructure in a modern data center
Self-hosted IdP infrastructure on a VPS — Photo: Brett Sayles / Pexels

TL;DR — Which One Should You Pick

  • Pocket ID — pick this if you're a solo developer or small team (under 10 users), you're comfortable with passkeys, and you want auth set up in one evening on a 1GB VPS. It's the only one of the three I'd run on a €3.50/month VPS and trust to stay alive.
  • Authentik — pick this if you have legacy apps that don't speak OIDC natively, you need LDAP, or your auth flows are complicated (conditional MFA, geofencing, custom captcha). Budget at least 2GB RAM and expect a real learning curve.
  • Zitadel — pick this if you're building a B2B SaaS, you need true multi-tenancy with per-tenant branding, or you're already on Kubernetes and want gRPC APIs. Overkill for personal infrastructure.

The rest of this guide explains why, with real numbers from VPS deployments I've actually run.

What Changed in Self-Hosted SSO Between 2025 and 2026

Three shifts matter for your VPS picking:

  1. Authentik dropped Redis. As of release 2025.10, Authentik migrated its cache, embedded outpost, and WebSocket layer to PostgreSQL. That cut my container count from 4 to 3 and freed roughly 80–120 MB of RAM on my staging VPS — but it also bumped Postgres connection counts ~50% per the upgrade notes, so if you're on a 2GB box you may need to tune max_connections.
  2. Pocket ID hit ~5.7k stars and stabilized its API. It went from "fun weekend project" in late 2024 to genuinely production-viable in early 2026. The maintainer added Postgres support alongside the default SQLite, and the schema migrations have been clean across the last six minor releases on the boxes I've tracked.
  3. Zitadel v3 is fully event-sourced and cloud-billed by active user. Self-hosting is still free, but the Cloud SKU now charges per monthly-active user, which changes the calculus if you were halfway between hosted and self-hosted.

Passkeys also went mainstream during 2025 — Apple, Google, and Microsoft all ship passkey UX defaults now, which is the entire premise Pocket ID is built on.

The Three Architectures, Side by Side

Before comparing features, you need to understand what you're running. The three IdPs are not the same shape.

Pocket ID

A single Go binary plus an embedded SQLite database (optionally Postgres). Default port 1411. The Docker image is around 60 MB. Authentication is passkey-only — no username/password fallback by design. The maintainer's philosophy is "if you want password fallback, run something else."

services:
  pocket-id:
    image: ghcr.io/pocket-id/pocket-id:v1
    ports: ["1411:1411"]
    volumes: ["./data:/app/data"]
    environment:
      APP_URL: https://id.example.com

That's the full compose file. No queue worker, no Redis, no separate database container.

Authentik

Three services minimum: server (Python/Django ASGI), worker (background tasks — flow processing, email, expiring tokens), and postgres. As of 2025.10 Redis is gone, but Postgres carries more load. The image is around 1.1 GB and the runtime memory footprint of server+worker together hovers between 700 MB and 1.1 GB on my idle test box.

Authentik's killer feature is the Flow Engine — every auth interaction (login, password reset, enrollment, recovery) is modeled as a flow of stages with conditional policies. You can build "require WebAuthn if user is admin AND not on corporate IP" without writing code.

Zitadel

A single Go binary plus PostgreSQL (or CockroachDB for HA). Event-sourced — every state change is appended to an event log, and read models are projected from it. This is fundamentally different from Authentik's row-update model and means Zitadel scales horizontally without much drama. It ships with gRPC APIs, a Terraform provider, and a Kubernetes operator.

Per the Zitadel self-hosting docs, the binary itself runs in ~512 MB RAM with less than 1 CPU core, but the recommended minimum is 1 GB RAM, and the database needs ~4 GB per CPU core under load.

Real Resource Usage on a Hetzner CX22 (2 vCPU, 4GB RAM, €4.50/mo)

I ran each one in isolation on the same box for a week with synthetic traffic (~50 logins/day, mimicking a small team) plus a single test client app behind oauth2-proxy. Here's what I measured with docker stats averaged over the week:

IdPIdle RAMPeak RAM (login burst)Cold startDB on disk after 7 days
Pocket ID38 MB92 MB1.4 s18 MB (SQLite)
Zitadel210 MB480 MB4.2 s240 MB (Postgres)
Authentik780 MB1.15 GB22 s320 MB (Postgres)

A few notes on these numbers, because aggregate stats are misleading:

  • Authentik's 22-second cold start is the killer for me on cheap VPS. If your provider's reboot SLA matters, factor that in. Pocket ID is back online before the SSH banner finishes rendering.
  • Zitadel's idle 210 MB is mostly Postgres connection pool overhead and projection materialization. Under no traffic the binary alone sits closer to 90 MB.
  • Pocket ID's 38 MB idle is genuinely shocking when you've been running Keycloak. It's the only one that comfortably co-exists with other services on a €3.50/month VPS.

The honest takeaway: on a single-purpose 2GB VPS, all three are fine. On a shared 4GB box where you also run Caddy, a database, and three other apps, Authentik starts to crowd everything else.

Biometric and passkey authentication is the modern replacement for password-based SSO
Passkey/biometric authentication — the foundation Pocket ID is built on. Photo: Pexels

Feature-by-Feature: What You Actually Get

Protocol Support

ProtocolPocket IDAuthentikZitadel
OIDC / OAuth 2.0YesYesYes
SAML 2.0NoYesYes
LDAP (as server)NoYesNo
SCIM provisioningNoYesYes
Proxy auth modeNoYesNo
Passkey/WebAuthnYes (only)YesYes
TOTP MFANoYesYes
Magic-linkNoYesYes

Authentik wins on protocol breadth — it can act as the IdP, the LDAP server for legacy apps that only speak LDAP, AND a forward-auth proxy in front of apps with no SSO at all. That last one is huge: I've used Authentik's proxy outpost to slap auth in front of Uptime Kuma and an internal Adminer instance that have no native OIDC support.

Pocket ID's "passkey only" stance is a feature, not a limitation — until it isn't. If a single one of your users is on an old Android device without passkey support, or your auditor wants TOTP for break-glass accounts, Pocket ID won't work for you.

Multi-Tenancy

Zitadel is built around multi-tenancy from day one — organizations, projects, instances, all first-class. If you're building a SaaS where Acme Corp and Globex are separate customers with their own users and branding, Zitadel is the obvious choice.

Authentik can fake multi-tenancy via "tenants" (branding + policies per domain) but it's not isolation, it's segmentation. I wouldn't trust it for true B2B isolation.

Pocket ID is single-tenant. If you need multi-tenancy, stop reading and pick Zitadel.

Admin UX

This is subjective, but after running all three for client demos:

  • Pocket ID's admin UI is the cleanest of the three. Add user → user gets a passkey enrollment link → done. Add OIDC client → copy redirect URIs → done. There are maybe 12 buttons total in the entire admin panel.
  • Zitadel's console is dense and professional. You'll need to read docs to understand "organizations vs. projects vs. instances" but once it clicks, it's coherent.
  • Authentik's admin UI is the most powerful and the most overwhelming. Flows, stages, providers, outposts, policies, property mappings — there's a real learning curve. I've onboarded interns onto Pocket ID in an hour and onto Authentik over a week.

Information Gain: Three Things You Won't Read Elsewhere

I'll spend a moment on details that don't show up in most comparison posts.

1. The Hostinger VPS quirk with WebSockets

On Hostinger's KVM 2 and KVM 4 VPS plans, the default LiteSpeed-based reverse proxy in front of cPanel can choke WebSocket connections under sustained load. This breaks Authentik's admin UI (live log streaming) but not its auth flows. If you're on Hostinger and want Authentik, bypass cPanel entirely — install Caddy directly on the VPS and point your domain there. I learned this the hard way trying to host Authentik for one of our client projects in November 2025.

2. Pocket ID's database choice has a hidden cost

Pocket ID defaults to SQLite, which is fine. But SQLite means you can't run two replicas behind a load balancer for HA. If you ever need to add a second container instance, you must first migrate to Postgres — and the migration tooling is not as polished as the rest of the project. Decide upfront. For a single VPS deployment, SQLite is genuinely the right call.

3. Authentik's Postgres connection bump is real

After the 2025.10 → 2026.x upgrade, my Authentik instance on a 2GB VPS started hitting the default max_connections = 100 limit during password reset bursts. The release notes warn about a ~50% bump in connection usage and they're not exaggerating. If you're on a tight box, bump Postgres to max_connections = 150 and shared_buffers = 256MB before the upgrade, not after.

Pricing Reality Check (May 2026)

All three projects are open source and free to self-host. The cost is your VPS bill and your time.

VPS option for IdPMonthlyWorks for
Hetzner CX22 (2vCPU/4GB)€4.50All three
Hetzner CX11 (1vCPU/2GB)€3.79Pocket ID, Zitadel (tight)
Hostinger KVM 2 (2vCPU/8GB)$7.99All three
Contabo VPS 1 (4vCPU/8GB)€5.50All three

If you're going managed-cloud-IdP-as-a-service instead, Zitadel Cloud charges per monthly active user, Authentik has a paid Enterprise tier, and Pocket ID doesn't have a cloud offering — it's self-host or nothing.

The break-even math I do for clients: if you have fewer than 50 active users, self-hosting on a €4.50 Hetzner box is always cheaper than any managed SSO. Past 200 users, the operational toil starts to matter and you should consider managed.

My Decision Matrix

After deploying these for various wardigi.com client projects and internal infra, here's the cheat sheet I actually use:

  • Family + personal services? → Pocket ID. Done. Stop reading.
  • Small startup, under 15 employees, modern OIDC-only stack? → Pocket ID, with a written plan to migrate later if you outgrow it.
  • Anything with LDAP or legacy in-house apps? → Authentik.
  • More than one tenant who can't see each other's data? → Zitadel.
  • You're on Kubernetes and want Terraform-managed IdP? → Zitadel.
  • You want "set up MFA only for admins coming from outside the office IP" without scripting? → Authentik.
  • You already run Keycloak and you're considering switching? → Honestly, stay on Keycloak for now. None of these will save you enough operational headache to justify the migration unless Keycloak is actively painful.

How I Would Set It Up Today (For Most Readers)

For 90% of readers on a single VPS, this is what I'd actually do:

  1. Buy a Hetzner CX22 in the region nearest your users (€4.50/month).
  2. Install Caddy 2 as the reverse proxy — it does automatic HTTPS via Let's Encrypt with one line of config.
  3. Drop Pocket ID via Docker Compose on port 1411, point id.yourdomain.com at it via Caddy.
  4. Wire your existing apps to Pocket ID via OIDC. For apps that don't speak OIDC natively (Uptime Kuma, n8n's basic auth, etc.), put oauth2-proxy in front of them with Pocket ID as the upstream IdP.
  5. Enroll your team members' passkeys once. Stop typing passwords forever.

If six months in you've outgrown Pocket ID (you added a team that needs LDAP, or a tenant boundary), Authentik or Zitadel will still be there. The OIDC client configurations in your downstream apps transfer over with a config swap, not a rewrite.

Frequently Asked Questions

Can I run any of these for free on Oracle Cloud Free Tier?

Yes — Pocket ID and Zitadel run comfortably on Oracle's Ampere A1 free tier (1 OCPU, 6GB RAM). Authentik works too but eats most of the RAM, leaving little for anything else. I ran Pocket ID + Caddy + a tiny Postgres on Oracle Free for four months before migrating to Hetzner for region latency reasons.

Is passkey-only really safe for a small team?

Yes, with one caveat: have a documented break-glass procedure. If a team member loses their only passkey device, you (the admin) need to be able to disable their account and issue a new enrollment link from the admin UI. Pocket ID handles this fine. Just don't be the only admin with the only passkey.

Will my OIDC clients break if I migrate IdPs later?

Usually no — the OIDC protocol is standardized. You change issuer, client_id, client_secret in each downstream app and you're done. The exception is anything using non-standard claims (custom groups, custom property mappings in Authentik) — those need re-mapping.

Does any of this work behind Cloudflare?

Yes, all three. Make sure to enable WebSocket support in your Cloudflare tunnel/zone config if you want live admin UI updates in Authentik. For passkey flows, Cloudflare's default settings work — no exotic configuration needed.

Pocket ID doesn't have TOTP — is that a deal-breaker for compliance?

For SOC 2 Type I and most ISO 27001 controls, passkey-only is actually stronger than TOTP, because passkeys are phishing-resistant by design. For some financial-services compliance regimes that hard-require "something you know + something you have", you'll need Authentik or Zitadel instead.

Final Take

Self-hosted SSO in 2026 isn't a one-size-fits-all decision. Pocket ID makes it almost insultingly easy for small teams that have embraced passkeys. Authentik is the swiss army knife for environments with legacy apps or complex auth requirements. Zitadel is the heavy-duty choice for B2B and Kubernetes-native deployments.

For the boring middle case — a solo dev or small team running a handful of internal tools on a single cheap VPS — Pocket ID is where I'd start in 2026. The 38 MB idle RAM, the one-evening setup time, and the passkey-first UX add up to something genuinely delightful, which is not a word I usually use about identity infrastructure.

The wrong choice here is no choice — every week you delay setting up SSO is another week of passwords in screenshots, expired tokens in .env files, and 2 AM "can you reset my admin login" Slack messages. Pick one and ship it this weekend.

Found this helpful?

Subscribe to our newsletter for more in-depth reviews and comparisons delivered to your inbox.