Logto mit Docker installieren: Moderne Auth-Infrastruktur mit OIDC, OAuth 2.1 und Multi-Tenancy
Logto ist eine quelloffene Alternative zu Auth0 mit OIDC, OAuth 2.1, Multi-Tenancy und Enterprise-SSO. Diese Anleitung zeigt, wie Sie Logto mit Docker Compose in etwa 20 Minuten aufsetzen, typische Fehler vermeiden und die Admin Console absichern.
Neue Version verfügbar: logto 1.44.0. Diese Anleitung wird überarbeitet. Beschrieben ist logto 1.43.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

Wer eine eigene SaaS-Anwendung baut oder selbst gehostete Dienste mit zentralem Login ausstattet, muss entscheiden: Anmeldung selbst entwickeln oder einem Anbieter überlassen? Logto (MPL-2.0, aktuell 1.43.0) ist eine quelloffene Authentifizierungsplattform, die vollständiges OIDC und OAuth 2.1 implementiert und dabei Multi-Tenancy, Enterprise-SSO über SAML, RBAC und passwortlose Logins mitbringt. Im Unterschied zu Auth0 oder Okta entstehen keine nutzungsabhängigen Kosten, und Code und Daten bleiben bei Ihnen. Der Betrieb erfolgt per docker compose, einzige Abhängigkeit ist PostgreSQL.
Voraussetzungen
- Docker Engine (≥ 24) oder Docker Desktop sowie Docker Compose v2 (Befehl:
docker compose) auf einem Linux-Host (amd64 oder arm64), einer VM oder einem NAS; ist das noch nicht eingerichtet, lesen Sie zuerst die Docker- und Compose-Grundlageninstallation für Ubuntu/Debian. - Mindestens 1 CPU-Kern und 1 GB RAM frei für Logto und PostgreSQL zusammen; für den Produktivbetrieb 2 Kerne und 2 GB.
- Freie Ports 3001 und 3002 auf dem Host.
- Ein Texteditor für
.envundcompose.yamlsowiecurlzur Verifikation. - Für den Produktivbetrieb: Eine eigene Domain mit HTTPS-Zertifikat und ein Reverse Proxy (Nginx, Traefik oder Caddy). Eine Anleitung dazu bietet Caddy als Reverse Proxy mit automatischem HTTPS.
- Optional:
opensslzur Erzeugung eines sicheren KEK-Schlüssels für den Secret Vault.
Schritt 1: Projektordner anlegen
Legen Sie einen eigenen Ordner für den Logto-Stack an. Alle Konfigurationsdateien liegen dort, das vereinfacht Updates und Backups.
mkdir -p /opt/logto
cd /opt/logtoWer lieber im Home-Verzeichnis arbeitet, verwendet ~/logto; der Rest der Anleitung bleibt gleich.
Verifizieren: ls -la /opt/logto zeigt den noch leeren Ordner ohne Fehlermeldung.
Schritt 2: .env-Datei mit sicheren Secrets anlegen
Logto und PostgreSQL benötigen mehrere Umgebungsvariablen. Legen Sie sie in einer .env-Datei ab, die nie in ein Repository gehört:
# /opt/logto/.env
# Pflicht: PostgreSQL-Passwort (mind. 20 Zeichen, keine Sonderzeichen die die URL brechen)
POSTGRES_PASSWORD=ihr_sicheres_db_passwort_hier
# Produktion: Eigene Domain des Core-Service (bestimmt den OIDC Issuer – VOR dem ersten Start setzen!)
LOGTO_ENDPOINT=https://auth.beispiel.de
# Produktion: Eigene Domain der Admin Console
LOGTO_ADMIN_ENDPOINT=https://admin.auth.beispiel.de
# Produktion: Localhost-Zugang zur Admin Console sperren (auf 1 setzen sobald Reverse Proxy aktiv)
ADMIN_DISABLE_LOCALHOST=
# Optional: AES-256-KEK für Secret Vault (erzeugen mit: openssl rand -base64 32)
SECRET_VAULT_KEK=
# Optional: Statement-Timeout in ms; bei PgBouncer auf DISABLE_TIMEOUT setzen
DATABASE_STATEMENT_TIMEOUT=Für den lokalen Test-Betrieb reicht ein gesetztes POSTGRES_PASSWORD; LOGTO_ENDPOINT und LOGTO_ADMIN_ENDPOINT bleiben leer. Für den Produktivbetrieb setzen Sie beide Domain-Variablen vor dem ersten produktiven Einsatz: Eine spätere Änderung ändert den OIDC-Issuer, ausgestellte Tokens werden ungültig, und alle angebundenen Anwendungen müssen den neuen Issuer übernehmen.
Den KEK-Schlüssel (Key Encryption Key) erzeugen Sie einmalig mit:
openssl rand -base64 32Verifizieren: Nach chmod 600 /opt/logto/.env zeigt ls -l /opt/logto/.env die Rechte -rw-------, und grep POSTGRES_PASSWORD /opt/logto/.env zeigt Ihr eigenes Passwort statt des Platzhalters.
Schritt 3: compose.yaml erstellen
Der offiziellen docker-compose.yml fehlen ein persistentes Volume und eigene Zugangsdaten. Die folgende Variante ergänzt beides:
# /opt/logto/compose.yaml
# Persistentes Volume, Zugangsdaten aus .env, festgelegte Versionen
services:
logto:
image: svhd/logto:1.43.0 # Tags ohne "v"; fuer Updates Tag anpassen
container_name: logto
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
ports:
# Nur lokal erreichbar; von aussen ausschliesslich ueber den Reverse Proxy (Schritt 6)
- "127.0.0.1:3001:3001" # Core Service: OIDC-Endpunkte, Management API, Anmeldung
- "127.0.0.1:3002:3002" # Admin Console
entrypoint: ["sh", "-c", "npm run cli db seed -- --swe && npm start"]
environment:
# Pflicht
- DB_URL=postgres://logto:${POSTGRES_PASSWORD}@postgres:5432/logto
- TRUST_PROXY_HEADER=1
# Produktion: eigene Domains (beeinflusst OIDC Issuer!)
- ENDPOINT=${LOGTO_ENDPOINT:-}
- ADMIN_ENDPOINT=${LOGTO_ADMIN_ENDPOINT:-}
# Optional
- ADMIN_DISABLE_LOCALHOST=${ADMIN_DISABLE_LOCALHOST:-}
- SECRET_VAULT_KEK=${SECRET_VAULT_KEK:-}
- DATABASE_STATEMENT_TIMEOUT=${DATABASE_STATEMENT_TIMEOUT:-}
postgres:
image: postgres:17-alpine
container_name: logto-db
restart: unless-stopped
user: postgres
environment:
POSTGRES_USER: logto
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: logto
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U logto -d logto"]
interval: 5s
timeout: 5s
retries: 10
start_period: 30s
volumes:
postgres_data:
driver: localWichtige Details zu dieser Konfiguration:
- Healthcheck mit
-U logto -d logto: Logto startet das Seeding erst, wenn PostgreSQL Verbindungen annimmt. Die Parameter passen den Test an den hier verwendeten Benutzer an. - Persistentes Volume
postgres_data: Ohne dieses Volume legt PostgreSQL nach dem Neuerstellen des Containers eine leere Datenbank an. - Entrypoint mit
--swe: Übernehmen Sie den Befehl unverändert aus der offiziellen Datei (--swe= skip when exists). Ist die Datenbank bereits initialisiert, überspringt Logto das Seeding. TRUST_PROXY_HEADER=1: Nötig, sobald ein Reverse Proxy vorgelagert ist, sonst schlägt die Anmeldung über HTTPS fehl.
Verifizieren: docker compose config --quiet im Ordner /opt/logto endet ohne Ausgabe, und docker compose config --images zeigt svhd/logto:1.43.0 und postgres:17-alpine.
Schritt 4: Stack starten
Starten Sie alle Container im Hintergrund:
cd /opt/logto
docker compose up -dBeim ersten Start lädt Docker die Images. Der Logto-Container wartet auf den PostgreSQL-Healthcheck und startet dann das Seeding; das dauert meist 30 bis 60 Sekunden.
Laufende Logs beobachten:
docker compose logs -f logtoNach dem Seeding meldet das Log, dass Core und Admin-App laufen, etwa Admin app is running at http://localhost:3002.
Verifizieren:
docker compose psErwartete Ausgabe (beide Container Up, postgres mit healthy):
NAME IMAGE STATUS
logto svhd/logto:1.43.0 Up 2 minutes
logto-db postgres:17-alpine Up 2 minutes (healthy)Anschließend den Core-Service per curl prüfen:
curl -I http://localhost:3001/oidc/.well-known/openid-configurationErwartete Antwort: HTTP/1.1 200 OK. Antwortet der OIDC-Discovery-Endpunkt, arbeitet der Core-Service.
Schritt 5: Admin-Account einrichten
Öffnen Sie im Browser http://localhost:3002. Da die Ports nur an 127.0.0.1 gebunden sind, nutzen Sie von einem anderen Rechner einen SSH-Tunnel: ssh -L 3002:localhost:3002 -L 3001:localhost:3001 benutzer@server. Beim ersten Aufruf zeigt Logto einen Assistenten zur Erstellung des Admin-Accounts.
Wichtig: Logto OSS unterstützt nur einen Administrator. Wählen Sie eine dauerhaft erreichbare E-Mail-Adresse und ein starkes Passwort. Danach gelangen Sie zur Admin Console mit dem vollständigen Dashboard für Applications, Connectors, Users, Enterprise SSO und RBAC.
| Bereich | URL (lokal) | Funktion |
|---|---|---|
| OIDC Discovery | http://localhost:3001/oidc/.well-known/openid-configuration | OIDC-Metadaten, Issuer, Endpunkte |
| Management API | http://localhost:3001/api | REST-API für Usermanagement, Apps, Connectors |
| Admin Console | http://localhost:3002 | Web-UI für die gesamte Konfiguration |
Verifizieren: Nach dem Login erscheint das Logto-Dashboard; unter „Applications“ lässt sich eine Test-Application anlegen. Rufen Sie die Admin Console nur über localhost oder HTTPS auf, über eine IP-Adresse mit HTTP blockiert der Browser die Web Crypto API (Crypto.subtle unavailable).
Schritt 6: Reverse Proxy und HTTPS einrichten (Produktion)
Für den Produktivbetrieb müssen beide Ports (3001 und 3002) hinter einem HTTPS-Reverse-Proxy liegen. Eine vollständige Anleitung für Nginx mit TLS bietet Nginx als Reverse Proxy mit TLS manuell einrichten. Für automatisches HTTPS ohne Zertifikatsverwaltung empfiehlt sich Traefik als Docker-Reverse-Proxy.
Ein minimales Nginx-Server-Block-Beispiel für den Core-Service:
server {
listen 443 ssl;
server_name auth.beispiel.de;
ssl_certificate /etc/letsencrypt/live/auth.beispiel.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/auth.beispiel.de/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Pflicht: Logto erkennt HTTPS-Kontext über diesen Header
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $http_host;
}
}Derselbe Block wird für admin.auth.beispiel.de mit proxy_pass http://127.0.0.1:3002 benötigt. Danach in der .env die Domain-Variablen setzen und den Stack neu starten:
# .env anpassen:
# LOGTO_ENDPOINT=https://auth.beispiel.de
# LOGTO_ADMIN_ENDPOINT=https://admin.auth.beispiel.de
# ADMIN_DISABLE_LOCALHOST=1
docker compose down
docker compose up -dAchtung: War LOGTO_ENDPOINT vorher nicht gesetzt (lokaler Test), sind alle bisherigen Tokens ungültig.
Verifizieren:
curl -I https://auth.beispiel.de/oidc/.well-known/openid-configurationErwartete Antwort: HTTP/2 200. Im JSON zeigt "issuer" auf https://auth.beispiel.de/oidc. Ein falscher Issuer ist die häufigste Ursache für Token-Validierungsfehler.
Schritt 7: Updates und Backup
Vor jedem Update sichern Sie die Datenbank und lesen die Release Notes. Tragen Sie dann den neuen Tag in der compose.yaml ein:
cd /opt/logto
# Vorher Datenbank sichern
docker exec logto-db pg_dump -U logto logto > /opt/logto/backup_$(date +%Y%m%d).sql
# Update durchfuehren und Datenbank-Migrationen anwenden
docker compose pull
docker compose run --rm -e CI=true --entrypoint "sh -c 'npm run alteration deploy latest'" logto
docker compose up -dDie Schemaänderungen neuer Versionen spielt alteration deploy ein (Aufruf wie im offiziellen Kubernetes-Beispiel); das Seeding beim Start übernimmt das nicht.
Für automatisierte PostgreSQL-Backups bietet sich ein Cronjob mit pg_dump an – eine vollständige Anleitung dazu liefert die Anleitung zum Automatisieren von PostgreSQL-Backups.
Für die Eckdaten des Stacks auf einen Blick:
| Eigenschaft | Wert |
|---|---|
| Image | svhd/logto:1.43.0 (Docker Hub, amd64 und arm64) |
| Image (alternativ) | ghcr.io/logto-io/logto |
| Image-Größe | ca. 288 MB |
| Port Core Service | 3001 (OIDC, Management API, Sign-in-Flow) |
| Port Admin Console | 3002 (Web-UI) |
| Datenbank (Pflicht) | PostgreSQL 14+ |
| Redis | Optional (nur Multi-Instanz) |
| Volume (Pflicht) | postgres_data:/var/lib/postgresql/data |
| Lizenz | Mozilla Public License 2.0 |
| Aktuelle Version | 1.43.0 (31. August 2026) |
Verifizieren:
docker compose ps
# Beide Container müssen Status "Up" zeigen.
docker compose logs --tail=20 logto
# Keine Fehler zu Image/Port/Volume/Env.Troubleshooting / Typische Fehler
- Admin Console zeigt „Crypto.subtle unavailable“: Die Web Crypto API funktioniert nur in sicheren Kontexten. Ursache ist ein Aufruf über HTTP mit IP-Adresse statt
localhost. Lösung: Entwederhttp://localhost:3002verwenden oder HTTPS per Reverse Proxy einrichten. - Sign-in schlägt fehl hinter Nginx/Traefik:
TRUST_PROXY_HEADER=1ist nicht gesetzt, oder der Proxy sendet keinenX-Forwarded-Proto: https-Header. Beide Bedingungen müssen erfüllt sein. - Logto startet nicht, Postgres bleibt „unhealthy“: Prüfen Sie mit
docker compose logs postgres, obPOSTGRES_PASSWORDgesetzt ist und der Healthcheck-Benutzer zuPOSTGRES_USERpasst. - Datenverlust nach
docker compose down: Kein persistentes Volume definiert. Lösung:postgres_datain dercompose.yamlund impostgres-Service eintragen. - OIDC Token-Validierungsfehler nach Domain-Wechsel:
LOGTO_ENDPOINTwurde nach dem ersten Start geändert, damit auch der Issuer. Lösung: Issuer in allen angebundenen Anwendungen anpassen, Benutzer neu anmelden lassen. - CORS-Fehler bei API-Zugriffen:
LOGTO_ADMIN_ENDPOINTstimmt nicht exakt mit der anfragenden Origin überein (z. B. abschließender Slash, http statt https). Exakt mit Schema und ohne abschließenden Slash setzen:https://admin.auth.beispiel.de. - PgBouncer / Connection-Pooler-Fehler:
DATABASE_STATEMENT_TIMEOUT=DISABLE_TIMEOUTin der.envsetzen, wenn PgBouncer vorgelagert ist. - Management API liefert 404: Community-Tutorials referenzieren oft Cloud-URLs (
[tenant-id].logto.app/api). Bei OSS lautet der Endpunkthttps://[eigene-domain]/apibzw.http://localhost:3001/api. - Umgebung ohne Internetzugang, Admin-Registrierung hängt:
--disable-admin-pwned-password-checkannpm run cli db seedim Entrypoint anhängen (Prüfung gegen Have I Been Pwned entfällt). - Invalid ID Token ohne erkennbaren Grund: Uhrzeitabweichung zwischen Server und Client. NTP aktivieren:
sudo timedatectl set-ntp true.
Häufige Fragen
Brauche ich Redis für Logto?
Nein. Redis ist optional und nur für den zentralen Cache mehrerer Logto-Instanzen hinter einem Load Balancer gedacht. Für eine Einzelinstanz reicht PostgreSQL.
Wie richte ich den ersten Admin-Account ein?
Über den Assistenten beim ersten Aufruf von http://localhost:3002, siehe Schritt 5. Logto OSS unterstützt nur einen Administrator.
Was ist der Unterschied zwischen Logto OSS und Logto Cloud?
Logto Cloud ist der gehostete Dienst des Herstellers mit mehreren Administratoren, Logto OSS die selbst gehostete Version (MPL-2.0). Die Management-API-Basis-URL unterscheidet sich: OSS nutzt die eigene Domain (https://[domain]/api), Cloud nutzt [tenant-id].logto.app/api.
Unterstützt Logto Enterprise SSO wie SAML?
Ja. Logto unterstützt SAML 2.0 und OIDC als Enterprise Connector. Die Konfiguration erfolgt in der Admin Console unter „Enterprise SSO“. Unterstützte Provider sind unter anderem Okta, Azure AD/Entra ID und Google Workspace.
Wie aktualisiere ich Logto auf eine neue Version?
Wie in Schritt 7: Backup mit pg_dump, neuen Tag eintragen (Format svhd/logto:1.43.0, ohne „v“), Images laden, alteration deploy ausführen, Stack starten.
Kann ich Logto hinter einem Nginx-Reverse-Proxy betreiben?
Ja. Beide Ports (3001 und 3002) müssen als separate Server-Blöcke konfiguriert werden. Nötig sind die Header X-Forwarded-Proto und X-Forwarded-Host sowie TRUST_PROXY_HEADER=1, sonst schlägt die Anmeldung fehl.
Welche Architekturen unterstützt das Logto-Image?
Die Release-Tags von svhd/logto gibt es für linux/amd64 und linux/arm64, also auch für Raspberry Pi 4/5 und ARM-Server. Nur der Entwicklungs-Tag edge ist auf amd64 beschränkt.
Fazit
Logto bietet OIDC, OAuth 2.1 und Enterprise-SSO als selbst gehostete Plattform auf Docker-Basis. Die Einrichtung dauert rund 20 Minuten, wenn LOGTO_ENDPOINT vor dem produktiven Einsatz korrekt gesetzt ist; eine spätere Änderung betrifft alle angebundenen Anwendungen. Für Teams, die Auth0 oder Okta ablösen wollen, ist Logto eine sachliche Alternative. Wer nur Single Sign-On für interne Dienste sucht, findet mit Authentik oder Authelia möglicherweise einen schlankeren Einstieg.
Weiterführende Anleitungen und Quellen
- Docker Compose: Multi-Container-Stacks aufbauen – Grundlagenwissen zu Compose-Syntax, Netzwerken und Volumes
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only – Produktionshärtung für Compose-Stacks
- Single Sign-On für den Self-Hosted-Stack: Authentik vs. Authelia – Vergleich der SSO-Alternativen mit Traefik Forward-Auth
- MySQL & PostgreSQL Backup automatisieren mit cron – pg_dump, Rotation und Cloud-Sync für PostgreSQL
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- Passbolt mit Docker installieren: Team-Passwortmanager
Offizielle Quellen: Logto OSS – Get Started · Logto Deployment and Configuration · logto-io/logto auf GitHub · svhd/logto auf Docker Hub


