Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Sicherheit & Datenschutz 05.07.2026 · 9 min Lesezeit

Casdoor mit Docker installieren: Zentraler Auth-Server für OAuth 2.0, OIDC und SSO

Casdoor ist ein schlanker, selbst betriebener Auth-Server mit Weboberfläche, der OAuth 2.0, OIDC, SAML, LDAP, WebAuthn und MFA vereint. Die Anleitung zeigt Installation mit Docker Compose und PostgreSQL, Absicherung, HTTPS, Updates und Backup.

Neue Version verfügbar: casdoor 4.13.0. Diese Anleitung wird überarbeitet. Beschrieben ist casdoor 4.12.0.

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Symbolbild zur Anleitung: Casdoor mit Docker installieren

Wer mehrere selbst betriebene Dienste wie Gitea, Nextcloud, eine eigene API oder ein internes Wiki nutzt, pflegt ohne zentrale Anmeldung für jeden Dienst eigene Zugangsdaten. Casdoor schafft hier Abhilfe: Die in Go geschriebene Plattform arbeitet als zentraler Identity Provider (IdP) und unterstützt OAuth 2.0, OIDC, SAML, CAS, LDAP, WebAuthn, TOTP, SCIM 2.0 und RADIUS. Die laufende Verwaltung erfolgt vollständig in der Weboberfläche. Diese Anleitung zeigt, wie Sie Casdoor 4.12 mit Docker Compose und PostgreSQL auf einem Linux-Host einrichten, absichern und prüfen.

Voraussetzungen

  1. Docker Engine 20.10+ und Docker Compose v2 (Befehl docker compose). Falls noch nicht installiert: Docker und Docker Compose auf Linux installieren.
  2. Linux-Host oder VM, x86_64 oder ARM64.
  3. Mindestens 1 CPU-Kern und 1 GB RAM, 2 GB freier Speicher für Images, Datenbank und Logs; 2 Kerne und 4 GB RAM geben Reserve für weitere Dienste.
  4. Für HTTPS im Produktivbetrieb ein Reverse Proxy (Caddy, Traefik oder Nginx), siehe Schritt 6, und ein DNS-Eintrag wie auth.example.com.
  5. Ein zufälliges PostgreSQL-Passwort mit mindestens 16 Zeichen, z. B. aus openssl rand -hex 24.

Eckdaten auf einen Blick

EigenschaftWert
Docker-Imagecasbin/casdoor:4.12.0 (Stand 30.09.2026)
Plattformenlinux/amd64, linux/arm64
Webport8000 (konfigurierbar über httpport in app.conf)
DatenbankPostgreSQL, MySQL 8+, SQLite (nur Test), CockroachDB, MSSQL, Oracle, TiDB
ProtokolleOAuth 2.0, OIDC, SAML, CAS, LDAP, SCIM 2.0, WebAuthn, TOTP, RADIUS
MFA-MethodenTOTP (Authenticator-Apps), SMS, E-Mail, WebAuthn/FIDO2
LizenzApache 2.0
Volume / EnvBedeutung
./conf:/confPflicht: Verzeichnis mit app.conf (Datenbank-Verbindung, HTTP-Port u. a.)
./logs:/logsEmpfohlen: Casdoor-Logdateien
postgres_data:/var/lib/postgresql/dataPflicht für PostgreSQL: Persistenz der Datenbankdaten
RUNNING_IN_DOCKER=truePflicht in Docker: ersetzt localhost im DSN automatisch durch den richtigen Container-Hostnamen
POSTGRES_PASSWORDPflicht: sicheres Passwort für den PostgreSQL-Superuser

Schritt 1: Projektordner und Verzeichnisstruktur anlegen

Legen Sie den Projektordner an, z. B. /opt/casdoor/:

mkdir -p /opt/casdoor/conf /opt/casdoor/logs
cd /opt/casdoor

Casdoor läuft im Container als Benutzer mit UID/GID 1000. Damit er in logs/ schreiben und app.conf lesen kann, übergeben Sie ihm die Verzeichnisse:

chown -R 1000:1000 /opt/casdoor/conf /opt/casdoor/logs

Verifizieren: Die Verzeichnisstruktur sieht so aus:

ls -la /opt/casdoor/
# Erwartete Ausgabe:
# drwxr-xr-x  conf/   (Eigentümer: 1000)
# drwxr-xr-x  logs/   (Eigentümer: 1000)

Schritt 2: app.conf herunterladen und anpassen

Ohne conf/app.conf startet Casdoor nicht. Laden Sie die offizielle Vorlage:

curl -o /opt/casdoor/conf/app.conf \
  https://raw.githubusercontent.com/casdoor/casdoor/master/conf/app.conf

Die Vorlage ist auf MySQL eingestellt (driverName = mysql). Passen Sie mindestens diese Werte an:

; Datenbankverbindung für PostgreSQL
driverName = postgres
dataSourceName = user=casdoor password=IHR_SICHERES_PASSWORT host=db port=5432 sslmode=disable dbname=casdoor

; HTTP-Port (muss mit dem internen Port in compose.yaml übereinstimmen)
httpport = 8000

; Öffentliche URL, wichtig für OIDC-Redirect-URIs
; Lokal: http://localhost:8000
; Produktion: https://auth.example.com
origin = http://localhost:8000

; Optional: Redis für Session-Caching
; redisEndpoint = redis:6379

; LDAP-Server-Port (Vorlage: 389)
; ldapServerPort = 389

Ersetzen Sie IHR_SICHERES_PASSWORT durch dasselbe Passwort, das Sie gleich in .env festlegen. PostgreSQL erwartet Schlüssel-Wert-Paare mit Leerzeichen, nicht das MySQL-Format root:pass@tcp(...).

Verifizieren: Die Datei ist für UID 1000 lesbar:

ls -la /opt/casdoor/conf/app.conf
# Erwartete Ausgabe: -rw-r--r-- 1 1000 1000 ...

Schritt 3: .env mit Datenbankpasswort anlegen

Legen Sie .env mit dem PostgreSQL-Passwort an, exakt identisch mit dem Wert in app.conf:

# /opt/casdoor/.env
POSTGRES_PASSWORD=IHR_SICHERES_PASSWORT

Schränken Sie die Rechte ein, damit andere Systembenutzer das Passwort nicht lesen:

chmod 600 /opt/casdoor/.env

Verifizieren:

ls -la /opt/casdoor/.env
# Erwartete Ausgabe: -rw------- 1 root root ...
# Das Passwort darf nicht leer sein:
grep POSTGRES_PASSWORD /opt/casdoor/.env

Schritt 4: compose.yaml erstellen und Stack starten

Erstellen Sie /opt/casdoor/compose.yaml. Der Stack besteht aus Casdoor und PostgreSQL 16. condition: service_healthy sorgt dafür, dass Casdoor erst startet, wenn die Datenbank bereit ist. Der Port ist nur an 127.0.0.1 gebunden: Solange das Standardpasswort gilt, darf Casdoor nicht aus dem Netz erreichbar sein. Der Healthcheck nutzt wget, das im Alpine-basierten Image enthalten ist.

services:

  casdoor:
    image: casbin/casdoor:4.12.0
    container_name: casdoor
    restart: unless-stopped
    ports:
      - "127.0.0.1:8000:8000"
    volumes:
      - ./conf:/conf
      - ./logs:/logs
    environment:
      RUNNING_IN_DOCKER: "true"
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8000/api/health"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 30s

  db:
    image: postgres:16-alpine
    container_name: casdoor-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: casdoor
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: casdoor
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U casdoor -d casdoor"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s

volumes:
  postgres_data:

Starten Sie den Stack:

cd /opt/casdoor
docker compose up -d

Casdoor braucht beim ersten Start etwas Zeit für die Datenbankinitialisierung. Öffnen Sie den Browser erst, wenn im Log der Start des HTTP-Servers erscheint:

docker compose logs -f casdoor
# Warten, bis der HTTP-Server auf Port 8000 gestartet ist

Verifizieren:

docker compose ps
# Erwartete Ausgabe (beide Container im Status "running" / "healthy"):
# NAME           IMAGE                    STATUS
# casdoor        casbin/casdoor:4.12.0    Up X minutes (healthy)
# casdoor-db     postgres:16-alpine       Up X minutes (healthy)

# API-Healthcheck per curl:
curl -s http://localhost:8000/api/health
# Erwartete Ausgabe: JSON mit "status":"ok"

Schritt 5: Erst-Einrichtung in der WebUI

Öffnen Sie http://localhost:8000 auf dem Server. Von einem anderen Rechner aus erreichen Sie die Oberfläche vor der Proxy-Einrichtung per SSH-Tunnel: ssh -L 8000:127.0.0.1:8000 benutzer@server. Die Standardzugangsdaten lauten:

  1. Organisation: built-in
  2. Benutzername: admin
  3. Passwort: 123

Ändern Sie das Admin-Passwort sofort nach der ersten Anmeldung. Das Passwort 123 ist öffentlich bekannt. Sie ändern es im Benutzerprofil des Admins (Benutzername oben rechts, Bearbeiten). Seit Version 4.0 nutzt Casdoor eine neue Oberfläche; Menübezeichnungen können von älteren Screenshots abweichen.

In der Weboberfläche können Sie:

  1. Organisationen anlegen und Benutzer verwalten (einzeln oder per Import)
  2. Anwendungen registrieren und Client-ID und Client-Secret erzeugen
  3. Identity Provider einbinden (Google, GitHub, Microsoft Entra ID, LDAP, SAML-IdP)
  4. MFA erzwingen, pro Organisation, Anwendung oder Benutzer
  5. RBAC/ABAC-Richtlinien über die integrierte Casbin-Engine definieren

Um eine Anwendung wie Gitea oder Nextcloud anzubinden, legen Sie unter Applications eine neue Anwendung an und tragen Name, Redirect-URI und Protokoll (OIDC/OAuth 2.0) ein. Casdoor zeigt danach Client-ID und Client-Secret, die Sie in der Ziel-App als OIDC-Provider hinterlegen. Die Endpunkte liegen unter der öffentlichen Adresse aus origin, weil der Browser sie direkt aufruft:

  1. Authorization: https://auth.example.com/login/oauth/authorize
  2. Token: https://auth.example.com/api/login/oauth/access_token
  3. UserInfo: https://auth.example.com/api/userinfo
  4. Discovery (für Apps mit automatischer Erkennung): https://auth.example.com/.well-known/openid-configuration

Verifizieren: Melden Sie sich ab und mit dem neuen Admin-Passwort wieder an. Die Anmeldung mit 123 muss scheitern, und das Dashboard zeigt Organisationen, Benutzer und Anwendungen.

Schritt 6: HTTPS mit Reverse Proxy (Produktion)

Für den Produktivbetrieb terminiert ein Reverse Proxy TLS vor Casdoor und leitet an 127.0.0.1:8000 weiter. Caddy holt Zertifikate von Let's Encrypt automatisch; die Einrichtung beschreibt Caddy als Reverse Proxy einrichten.

Setzen Sie danach origin in conf/app.conf auf die öffentliche HTTPS-Adresse:

origin = https://auth.example.com

Starten Sie Casdoor neu:

cd /opt/casdoor
docker compose restart casdoor

Verifizieren:

# HTTPS-Antwort des Reverse Proxys prüfen:
curl -I https://auth.example.com
# Erwartete Ausgabe: HTTP/2 200 (oder 302 zum Login)

Schritt 7: Updates und Backup

Casdoor veröffentlicht häufig neue Versionen; Version 4.0 (September 2026) brachte eine neue Weboberfläche mit geänderten Pfaden für statische Dateien. Legen Sie deshalb den Tag fest (hier casbin/casdoor:4.12.0), lesen Sie vor jedem Update die Release Notes und sichern Sie vorher die Datenbank. Zum Aktualisieren passen Sie den Tag in compose.yaml an und führen aus:

cd /opt/casdoor
docker compose pull
docker compose up -d

Für das Backup zählen zwei Dinge:

  1. PostgreSQL-Datenbank: enthält Benutzer, Anwendungen, Richtlinien und Zertifikate. Sichern Sie sie regelmäßig mit pg_dump, siehe PostgreSQL-Backup automatisieren mit cron.
  2. conf/app.conf: enthält die Datenbankverbindung und origin.

Sicherung direkt aus dem laufenden Container:

docker exec casdoor-db pg_dump -U casdoor casdoor \
  | gzip > /opt/backups/casdoor_$(date +%Y%m%d).sql.gz

Verifizieren:

docker compose ps
# Beide Container müssen nach dem Update "healthy" sein:
# casdoor     casbin/casdoor:4.12.0    Up X minutes (healthy)
# casdoor-db  postgres:16-alpine       Up X minutes (healthy)

# Backup-Datei vorhanden und nicht leer:
ls -lh /opt/backups/casdoor_*.sql.gz

Troubleshooting / Typische Fehler

  1. „config file not found“ beim Start: ./conf ist gemountet, aber conf/app.conf fehlt. Laden Sie die Datei wie in Schritt 2.
  2. „dial tcp 127.0.0.1:5432: connect: connection refused“: In app.conf steht localhost als Datenbank-Host. Tragen Sie den Service-Namen db ein oder setzen Sie RUNNING_IN_DOCKER: "true".
  3. „invalid DSN“ bei PostgreSQL: Das MySQL-Format funktioniert nicht. Richtig: user=casdoor password=SECRET host=db port=5432 sslmode=disable dbname=casdoor.
  4. „502 Bad Gateway“: Casdoor initialisiert noch. Beobachten Sie docker compose logs -f casdoor und warten Sie auf den Start des HTTP-Servers.
  5. „Permission denied“ in ./logs: Der Ordner gehört root. Führen Sie chown -R 1000:1000 conf/ logs/ auf dem Host aus.
  6. Casdoor startet vor der Datenbank: depends_on ohne condition: service_healthy. Definieren Sie den Healthcheck beim db-Service wie gezeigt.
  7. LDAP-Port 389 lässt sich nicht binden: Setzen Sie in app.conf einen höheren Port, z. B. ldapServerPort = 1389, und veröffentlichen Sie ihn in compose.yaml.
  8. Interner Port stimmt nicht: Steht httpport = 9000 in app.conf, aber 8000 in compose.yaml, ist der Dienst nicht erreichbar. Beide Werte müssen übereinstimmen.
  9. Anmeldung bei der Ziel-App scheitert mit Redirect-Fehler: origin oder die Redirect-URI der Anwendung stimmt nicht exakt mit der aufgerufenen Adresse überein (Protokoll, Hostname, Pfad).

Häufige Fragen

Welche Datenbank soll ich verwenden?

PostgreSQL ist für den Produktivbetrieb die naheliegende Wahl, MySQL 8.0+ funktioniert ebenfalls. SQLite eignet sich nur für Tests, etwa mit dem Image casbin/casdoor-all-in-one; ohne Volume gehen die Daten beim Neuerstellen des Containers verloren.

Wie integriere ich Nextcloud oder Gitea als SSO-Client?

Legen Sie in Casdoor unter Applications eine Anwendung mit der Redirect-URI der Ziel-App an und wählen Sie OIDC. In Nextcloud oder Gitea tragen Sie Client-ID, Client-Secret und die Discovery-URL https://auth.example.com/.well-known/openid-configuration ein.

Wie aktiviere ich MFA für alle Benutzer?

In den Einstellungen der Organisation erzwingen Sie MFA für alle Mitglieder. Unterstützt werden TOTP (Authenticator-Apps), SMS, E-Mail und Sicherheitsschlüssel per WebAuthn/FIDO2. MFA lässt sich auch pro Anwendung oder Benutzer aktivieren.

Wie aktiviere ich HTTPS?

Über einen Reverse Proxy, der HTTPS auf Port 443 terminiert und an 127.0.0.1:8000 weiterleitet. Danach setzen Sie origin = https://auth.example.com und starten Casdoor neu (Schritt 6).

Sollte ich :latest oder eine feste Version verwenden?

Eine feste Version. Mit :latest zieht docker compose pull jederzeit eine neue Version, auch über Major-Grenzen wie 3.x auf 4.x hinweg. Update-Hinweise ohne automatisches Aktualisieren liefern Diun oder WUD, siehe Docker-Container automatisch aktualisieren.

Kann Casdoor selbst als LDAP-Server agieren?

Ja, für ältere Anwendungen, die nur LDAP sprechen. Die Vorlage aktiviert den LDAP-Server auf Port 389 (ldapServerPort); veröffentlichen Sie den Port in compose.yaml nur, wenn Sie ihn brauchen, und nur im internen Netz. Casdoor stellt dann Benutzer und Gruppen aus demselben Benutzerstamm per LDAP bereit.

Was ist SCIM 2.0 und wofür brauche ich es?

SCIM 2.0 (System for Cross-domain Identity Management) synchronisiert Benutzer und Gruppen automatisch zwischen Casdoor und Verzeichnisdiensten wie Microsoft Entra ID oder Okta. Neue Konten werden angelegt, gelöschte deaktiviert, ohne manuellen Import.

Fazit

Casdoor bündelt OAuth 2.0, OIDC, SAML, LDAP-Server, RADIUS und WebAuthn mit einer Casbin-Autorisierung in einem Container, der wenig Ressourcen braucht. Gegenüber Keycloak ist der Betrieb einfacher, dafür fehlen Funktionen wie die Realm-Isolation. Für KMU, die eine zentrale Anmeldung für Docker-basierte Dienste suchen, ist Casdoor eine Option, sofern das Standardpasswort sofort geändert, der Tag festgelegt und die Oberfläche nur über HTTPS erreichbar ist. Als nächste Schritte empfehlen sich Docker Compose absichern und der Vergleich in Single Sign-On: Authentik vs. Authelia.

Weiterführende Anleitungen und Quellen

  1. Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage
  2. Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
  3. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb
  4. Single Sign-On für den Self-Hosted-Stack: Authentik vs. Authelia mit Traefik Forward-Auth absichern
  5. MySQL & PostgreSQL Backup automatisieren mit cron
  6. Docker-Container automatisch aktualisieren nach dem Watchtower-Aus: Diun, WUD und Renovate im Vergleich
  7. Zitadel mit Docker installieren: Cloud-nativer Identity Server als Keycloak-Alternative

Offizielle Quellen: Casdoor-Dokumentation: Try with Docker | Casdoor GitHub-Repository | Casdoor Release Notes | casbin/casdoor auf Docker Hub.

Passende Anleitungen auf S-EDV

  1. Pocket ID mit Docker Compose installieren: Passkey-SSO
  2. Logto mit Docker installieren: Auth-Infrastruktur mit OIDC
  3. Keycloak auf dem Synology NAS installieren: SSO mit OIDC und SAML