Blog · Guides

How to choose and run a self-hosted identity provider

What it takes to self-host SSO and IAM: the open-source options (Casdoor, Keycloak, authentik, Zitadel, Authelia), what you need next to them, a production checklist, and a Docker Compose example.

Casdoor Team · October 25, 2026 · 6 min read

This guide is written by the team that builds Casdoor and describes the standards as published (listed under Sources), with notes on how Casdoor implements them as of October 25, 2026. Spotted a mistake? Tell us.

A self-hosted identity provider (IdP) is a sign-in server you run on your own machines: it holds your users, shows the login page, handles MFA, and issues tokens or assertions to your apps over OpenID Connect, OAuth 2.0 or SAML. This guide covers when self-hosting makes sense, the open-source servers worth looking at, and what it takes to run one in production.

Why self-host, and why not

Teams self-host their IdP for a few recurring reasons:

  • Data location. User records, password hashes and sign-in logs stay in your own data center or cloud account, which matters for regulated industries, governments and some regions' privacy laws.
  • Cost at scale. Hosted auth services usually bill per monthly active user. A self-hosted server costs the same whether you have 1,000 users or 1,000,000. See what 100,000 users cost on hosted services.
  • Private networks. Apps on an intranet or an air-gapped network can't reach a public SaaS login page.
  • Control. You choose the upgrade schedule, the database, the login page and the code itself.

The cost is operational. You are now responsible for patching a security-critical service, keeping it available (when the IdP is down, nobody can sign in to anything), backing up its database and protecting its signing keys.

Open-source options

Casdoor Keycloak authentik Zitadel Authelia
License Apache-2.0 Apache-2.0 MIT, enterprise features separate AGPL-3.0 Apache-2.0
Written in Go Java Python, behind a Go web server Go, with a Next.js login app Go
Database MySQL, PostgreSQL, SQLite, SQL Server and others PostgreSQL, MySQL, MariaDB, Oracle, SQL Server PostgreSQL (no Redis since 2025.10) PostgreSQL 14 to 18 SQLite, MySQL or PostgreSQL for its own state; users in a file or LDAP
User management and sign-up Yes Yes Yes Yes No
OIDC and SAML IdP Both Both Both Both OIDC; SAML is on its roadmap
LDAP and RADIUS Serves both Connects to existing LDAP servers Serves both, through outposts Uses LDAP as an upstream identity provider Uses LDAP as its user store
Managed cloud from the maintainers Yes No No Yes No

A few rules of thumb:

  • A few self-hosted apps behind a reverse proxy, users kept in a file: Authelia is the lightest.
  • Many apps, real user management, several protocols: Casdoor, Keycloak or authentik.
  • Multi-tenant B2B SaaS: Casdoor or Zitadel, both of which give each customer its own organization with its own admins.

For deeper comparisons, see Casdoor vs Keycloak vs authentik vs Zitadel and the top open-source IAM and SSO solutions.

What you need next to the IdP

The identity server itself is only one piece. Plan for:

  1. A domain and TLS. Put the IdP behind a reverse proxy (NGINX, Caddy, Traefik) or a load balancer that terminates HTTPS, on a stable hostname such as login.example.com. That hostname becomes the OIDC issuer and part of every SAML metadata file, so changing it later means reconfiguring every app.
  2. A production database. Use a managed or replicated SQL database rather than a file on the IdP's disk. SQLite is fine for a trial, not for production.
  3. Email delivery. Sign-up verification, password resets and email one-time codes need an SMTP server or an email API.
  4. SMS, if you send codes by text. An SMS provider account, plus rate limits and a captcha so attackers can't run up your bill.
  5. Backups you have restored at least once. The database holds users, password hashes, MFA secrets and, in most IdPs, the token signing keys.
  6. Monitoring. A health check, uptime alerts, and somewhere to keep sign-in and audit logs.
  7. Shared sessions for more than one replica. Running two or more copies behind a load balancer usually needs a shared session store; Casdoor uses Redis for that.

Production checklist

  • Serve only over HTTPS, and set the IdP's public origin so the issuer URL and redirects use your real hostname, not an internal address.
  • Set a strong password for the first administrator, turn on MFA for every admin account, and don't use the default admin account day to day.
  • Allow only exact redirect URIs for each application, with no wildcards.
  • Turn on brute-force protection: account lockout or a captcha after failed sign-ins.
  • Keep the signing certificates' private keys in the database or a secret store, not in a Git repository, and plan how you will rotate them.
  • Back up the database daily and test a restore.
  • Subscribe to the project's security advisories and upgrade promptly; an IdP is the first thing attackers probe.
  • Use the trial images and embedded databases only for trials.

Example: Casdoor with Docker Compose and PostgreSQL

Casdoor is a single Go service with a SQL database, so a production-shaped setup is two containers. Every app.conf option can be passed as an environment variable:

services:
  db:
    image: postgres:17
    environment:
      POSTGRES_USER: casdoor
      POSTGRES_PASSWORD: change-me
      POSTGRES_DB: casdoor
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U casdoor"]
      interval: 5s
      retries: 10

  casdoor:
    image: casbin/casdoor:latest
    depends_on:
      db:
        condition: service_healthy
    environment:
      driverName: postgres
      dataSourceName: "user=casdoor password=change-me host=db port=5432 sslmode=disable dbname=casdoor"
      dbName: casdoor
      origin: https://login.example.com
    ports:
      - "8000:8000"

volumes:
  db-data:

For PostgreSQL the database name appears twice, in dbName and inside dataSourceName. Start it with docker compose up -d, point your reverse proxy at port 8000, and open the site: on a new database, Casdoor asks you to set the password of the built-in/admin account before anything else. From there, create an organization and an application for each app, and connect apps over OIDC, SAML, CAS, LDAP or RADIUS.

To run more than one replica, set redisEndpoint so sessions are shared, or use the Casdoor Kubernetes operator, which can run several replicas with PostgreSQL, Redis and an Ingress.

Self-hosted or managed: the same software

Self-hosting doesn't have to be a one-way decision. Casdoor Cloud runs the same open-source Casdoor as a dedicated instance with its own database, $24/month billed yearly, with no per-user fees. You can start managed and move to your own servers later, or the other way round, by moving the database. See pricing.

FAQ

What is the easiest identity provider to self-host? For a homelab with a handful of apps behind a reverse proxy, Authelia. For a full identity provider with user management and SAML, Casdoor is a single Go binary plus a SQL database, and has an all-in-one Docker image with an embedded SQLite database for trying it out.

How much hardware does a self-hosted IdP need? Less than you might think: sign-ins are short requests, and a small virtual machine handles thousands of users. It depends on the project: authentik's Docker Compose guide asks for at least 2 CPU cores and 2 GB of RAM, while a single Go service such as Casdoor runs in far less. Size the database for growth and keep it backed up.

Is a self-hosted IdP less secure than a SaaS one? Not inherently, but the security is now your job: patching, TLS, backups, admin MFA and monitoring. If nobody on your team can own that, a managed instance is the safer choice.

Can I self-host and still offer enterprise SSO to my customers? Yes. Casdoor, Keycloak, authentik and Zitadel can all accept SAML and OIDC connections from your customers' identity providers, such as Entra ID or Okta, with no per-connection fee.