Tinyauth mit Docker Compose: schlanker Login vor selbst gehosteten Diensten
Tinyauth setzt als einzelner Container eine Login-Seite vor Webdienste ohne eigene Anmeldung. Die Anleitung zeigt Docker Compose mit Traefik per Forward-Auth, bcrypt-Benutzer, Funktionstest, Anmeldesperre, Backup und typische Fehler.
Werbung Mit * 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

Viele selbst gehostete Werkzeuge (Dashboards, Statusseiten, Dateifreigaben) haben keine eigene Anmeldung und brauchen davor eine Schicht, die erst nach einem Login durchlässt. Authentik und Authelia sind bei zwei oder drei Diensten oft zu aufwendig. Tinyauth ist ein einzelner Container, per Umgebungsvariablen konfiguriert, per Forward-Auth vor Traefik, Caddy oder Nginx.
Alle Fehlermeldungen stammen von Tinyauth v5.2.0.
Was Tinyauth ist und wo die Grenzen liegen
Tinyauth ist ein Go-Dienst (AGPL-3.0) unter tinyauthapp/tinyauth (früher steveiliop56/tinyauth), aktuell v5.2.0 (07.09.2026). Forward-Auth: Der Reverse Proxy fragt bei jeder Anfrage zuerst Tinyauth, bei 200 geht sie durch, sonst folgt die Login-Seite mit Sitzungscookie für die übergeordnete Domain.
Stärken:
- Ein Container ohne Datenbank oder Redis, Benutzer als
benutzer:bcrypt-hashin Variable oder Datei, knapp 7 MiB RAM - Zugriffsregeln pro Anwendung (Benutzer, Gruppen, IP, Pfade), optional TOTP, OAuth, LDAP, Tailscale
Laut Doku ist Tinyauth für Homelabs und kleine Personenkreise gedacht, nicht für Produktion mit RBAC (dort empfiehlt das Projekt Authentik). Es fehlen:
- Verwaltungsoberfläche (Benutzer ändern heißt Konfiguration ändern und neu starten) und Selbstbedienung bei vergessenen Passwörtern.
- Rollen und Gruppenverwaltung (Gruppen nur aus OAuth oder LDAP).
- WebAuthn, Passkeys, Audit-Protokolle, SAML, Hochverfügbarkeit (nur TOTP).
Für zwei interne Werkzeuge ist Tinyauth pragmatisch, bei Dutzenden Konten oder SAML sind Authentik oder Authelia besser.
Voraussetzungen und Ressourcen
- Linux-Host (x86-64 oder ARM64) mit Docker Compose v2, 1 CPU-Kern, 512 MB RAM. Die Image-Tags tragen das
v(5.2.0liefert 404). - Eigene Domain mit Subdomains (
auth.example.com,app.example.com), Tinyauth und Anwendungen teilen das Cookie der übergeordneten Domain. - Reverse Proxy mit Forward-Auth (Traefik, Nginx Proxy Manager, SWAG, Caddy). Tinyauth braucht wenige MiB, Traefik etwa 130 MiB RAM.
| Punkt | Wert |
|---|---|
| Getestete Version | Tinyauth v5.2.0, Traefik v3.6 |
| Image | ghcr.io/tinyauthapp/tinyauth (linux/amd64, linux/arm64), Tags v5, v5.2.0, latest, Port 3000 |
| Persistente Daten | /data mit tinyauth.db (Sitzungen, OIDC-Daten) |
Schritt 1: Benutzer mit bcrypt-Hash anlegen
Ein Benutzer besteht aus Name, bcrypt-Hash und optional TOTP-Geheimnis (benutzer:hash:totp). Hash interaktiv erzeugen (ohne Passwort in der Shell-Historie):
# Fragt Benutzername und Passwort ab und gibt fertige Zeilen aus$ docker run -i -t --rm ghcr.io/tinyauthapp/tinyauth:v5 user create --interactiveNicht interaktiv mit --username und --password, --docker verdoppelt die Dollarzeichen:
# Achtung: das Passwort steht danach in der Shell-Historie$ docker run --rm ghcr.io/tinyauthapp/tinyauth:v5 user create --username admin --password 'IhrPasswort' --dockerCreated user 'admin'.
Environment variable:
TINYAUTH_AUTH_USERS=admin:$$2a$$10$$Jjo82URX...
CLI flags:
--auth.users=admin:$2a$10$Jjo82URX...Im environment-Block der compose.yaml gilt $$, in einer per env_file eingebundenen .env funktioniert das einfache Dollarzeichen. Mehrere Benutzer trennen Sie mit Kommas. Prüfen:
$ docker run --rm ghcr.io/tinyauthapp/tinyauth:v5 user verify --user 'admin:$2a$10$...' --username admin --password 'IhrPasswort'Richtig: ✓ User verified, falsch: password is incorrect: crypto/bcrypt: hashedPassword is not the hash of the given password (Exitcode 1).
user verify meldet ✓ User verified für Ihren Eintrag und Ihr Passwort.
Schritt 2: Verzeichnisstruktur und .env
/opt/tinyauth/
├── compose.yaml
├── .env
├── data/ # SQLite-Datenbank von Tinyauth
└── traefik/
├── dynamic.yaml # Router, Middleware, Services
└── acme/ # Zertifikate von Let's EncryptDie .env (Rechte 600) enthält die Einstellungen:
# Tinyauth-Konfiguration, Beispielwerte ersetzen
TINYAUTH_APPURL=https://auth.example.com
TINYAUTH_AUTH_USERS=admin:$2a$10$ERSETZEN.durch.eigenen.bcrypt.Hash.aus.user.create
TINYAUTH_AUTH_TRUSTEDPROXIES=172.16.0.0/12
TINYAUTH_AUTH_SECURECOOKIE=true
TINYAUTH_ANALYTICS_ENABLED=false
TINYAUTH_LABELPROVIDER=none| Variable | Bedeutung | Standard |
|---|---|---|
TINYAUTH_APPURL | Öffentliche URL (Cookie-Domain) | leer, Pflicht |
TINYAUTH_AUTH_USERS | Liste benutzer:hash, kommagetrennt | leer |
TINYAUTH_AUTH_USERSFILE | Datei mit Benutzern | leer |
TINYAUTH_AUTH_TRUSTEDPROXIES | Proxys, deren X-Forwarded-For gilt; nötig für IP-Regeln | leer |
TINYAUTH_AUTH_SECURECOOKIE | Cookie nur über HTTPS | false |
TINYAUTH_AUTH_SESSIONEXPIRY | Sitzungsdauer (s) | 86400 |
TINYAUTH_AUTH_LOGINMAXRETRIES / LOGINTIMEOUT | Fehlversuche bis Sperre, Sperrdauer (s) | 3 / 300 |
TINYAUTH_ANALYTICS_ENABLED | Heartbeat an api.tinyauth.app alle 12 Stunden | true |
TINYAUTH_LABELPROVIDER | ACL-Labels: auto, docker, kubernetes, none | auto |
Die Telemetrie ist standardmäßig aktiv (laut Doku Version, abgeleitete UUID, Zeitpunkt), in Unternehmensnetzen abschalten. TINYAUTH_LABELPROVIDER=none passt bei Regeln per Umgebungsvariablen.
ls -l /opt/tinyauth/.env zeigt -rw-------, docker compose config zeigt TINYAUTH_APPURL mit https://.
Schritt 3: compose.yaml mit Traefik und Beispieldienst
Das offizielle Beispiel bindet den Docker-Socket (faktisch Root) in Traefik ein, diese Variante nutzt den File-Provider. Tinyauth und die Anwendung veröffentlichen keine Hostports, sonst ließe sich der Login umgehen. Geschützter Dienst: traefik/whoami.
services:
traefik:
image: traefik:v3.6
restart: unless-stopped
command:
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.websecure.address=:443
- --certificatesresolvers.le.acme.email=admin@example.com
- --certificatesresolvers.le.acme.storage=/acme/acme.json
- --certificatesresolvers.le.acme.tlschallenge=true
- --providers.file.filename=/etc/traefik/dynamic.yaml
- --providers.file.watch=true
ports:
- 80:80
- 443:443
volumes:
- ./traefik/dynamic.yaml:/etc/traefik/dynamic.yaml:ro
- ./traefik/acme:/acme
whoami:
image: traefik/whoami:latest
restart: unless-stopped
tinyauth:
image: ghcr.io/tinyauthapp/tinyauth:v5.2.0
restart: unless-stopped
env_file: .env
volumes:
- ./data:/datatraefik/dynamic.yaml definiert die Middleware und hängt sie an den Router der Anwendung:
http:
middlewares:
tinyauth:
forwardAuth:
address: http://tinyauth:3000/api/auth/traefik
authResponseHeaders:
- Remote-User
- Remote-Name
- Remote-Email
routers:
tinyauth:
rule: Host(`auth.example.com`)
entryPoints: [websecure]
service: tinyauth
tls:
certResolver: le
whoami:
rule: Host(`app.example.com`)
entryPoints: [websecure]
middlewares: [tinyauth]
service: whoami
tls:
certResolver: le
services:
tinyauth:
loadBalancer:
servers:
- url: http://tinyauth:3000
whoami:
loadBalancer:
servers:
- url: http://whoami:80Der Router für Tinyauth bekommt keine Middleware (Schleife). authResponseHeaders reicht Remote-User, Remote-Name, Remote-Email weiter, weitere Dienste bekommen einen Router mit middlewares: [tinyauth].
docker compose config --services listet traefik, whoami und tinyauth; nur traefik hat einen ports-Eintrag.
Schritt 4: Installation und Start
- DNS-Einträge für
auth.example.comundapp.example.comauf die öffentliche IP des Hosts setzen. - Verzeichnisse anlegen und Rechte setzen.
- Benutzer erzeugen und in die
.enveintragen. - Stack starten und Logs prüfen.
$ sudo mkdir -p /opt/tinyauth/data /opt/tinyauth/traefik/acme
$ cd /opt/tinyauth
# compose.yaml, .env, traefik/dynamic.yaml wie oben anlegen$ sudo chmod 600 .env
# Stack starten$ docker compose up -d
# Log prüfen$ docker compose logs tinyauthEin erfolgreicher Start zeigt im Log diese beiden Zeilen:
INF Starting Tinyauth version: v5.2.0 stream=app
INF Starting server on http://0.0.0.0:3000 stream=appOhne TINYAUTH_AUTH_TRUSTEDPROXIES meldet das Log WRN Trusted proxies are not configured, IP access controls will NOT work. Tragen Sie das Subnetz aus docker network inspect ein.
Das Log zeigt Starting Tinyauth version: v5.2.0 und keine Warnung zu Trusted Proxies; docker compose ps listet alle drei Dienste als Up.
Schritt 5: Funktionstest und Healthcheck
Das Image bringt einen Healthcheck mit. Zu Healthchecks im Allgemeinen siehe Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only. Von Hand:
# Healthcheck im laufenden Container$ docker compose exec tinyauth tinyauth healthcheckDie Doku nennt docker compose exec tinyauth healthcheck, das scheitert (executable file not found). Richtig mit Binary: docker compose exec tinyauth tinyauth healthcheck.
Antworten von Tinyauth:
| Anfrage | Ergebnis |
|---|---|
| Ohne Cookie, Browser-User-Agent | 302 Found auf /login?login_for=app&redirect_uri=... |
| Ohne Cookie, curl | 401 Unauthorized mit Header X-Tinyauth-Location |
| Login mit falschem Passwort | 401, Log: Invalid password during login attempt |
| Login mit richtigem Passwort | 200 Login successful, Cookie HttpOnly; SameSite=Lax für die übergeordnete Domain |
| Mit gültigem Cookie | 200, Anwendung erhält Remote-User, Remote-Name, Remote-Email |
| Nach Logout, auch mit altem Cookie | 401 (Sitzung serverseitig ungültig) |
Gefälschter Header Remote-User: admin | 401 |
Browser (User-Agent mit Chrome, Gecko, AppleWebKit, Opera oder Edge) erhalten eine Weiterleitung, Skripte 401. Ablauf per curl:
# Login, Cookie speichern$ curl -c jar -H 'Content-Type: application/json' -d '{"username":"admin","password":"IhrPasswort"}' https://auth.example.com/api/user/login
# Geschützter Dienst mit Cookie (erwartet 200)$ curl -b jar -o /dev/null -w '%{http_code}\n' https://app.example.com/
# Abmelden$ curl -b jar -X POST https://auth.example.com/api/user/logoutOhne Cookie liefert https://app.example.com/ 401 oder 302, mit Cookie 200; tinyauth healthcheck meldet Tinyauth is healthy.
Schritt 6: Erstkonfiguration: TOTP und Anmeldesperre
Nach dem dritten Fehlversuch sperrt Tinyauth den Benutzernamen 300 Sekunden (schon der vierte Versuch liefert 429, auch mit richtigem Passwort). Wer Ihren Benutzernamen kennt, kann Sie aussperren, nutzen Sie statt admin einen schwer erratbaren Namen. Die Sperre liegt nur im Speicher.
Für TOTP erzeugen Sie einen TOTP-Benutzer (QR-Code für die Authenticator-App). Der neue Eintrag ersetzt den alten in TINYAUTH_AUTH_USERS. Für mehr als wenige Personen ist OIDC oder LDAP sinnvoller, zum zweiten Faktor siehe die Anleitung zu 2FA und MFA:
# TOTP-Geheimnis erzeugen$ docker run -i -t --rm ghcr.io/tinyauthapp/tinyauth:v5 totp generate --interactive
# Danach Tinyauth neu starten$ docker compose up -d --force-recreate tinyauthDie Anmeldung verlangt nach dem Passwort einen TOTP-Code, und nach drei Fehlversuchen antwortet Tinyauth mit HTTP 429.
Persistente Daten und Rechte
Unter /data liegt tinyauth.db (Sitzungen, OIDC), Benutzer stehen dort nicht, Sitzungen überleben einen Neustart. Der Prozess läuft als root, Backup und Aufräumen brauchen sudo.
sudo ls -l /opt/tinyauth/data zeigt tinyauth.db, und nach docker compose restart tinyauth bleibt die Sitzung gültig.
Schritt 7: Reverse Proxy, TLS und Netzwerkfreigabe
- HTTPS ist Pflicht. Setzen Sie
TINYAUTH_APPURLaufhttps://undTINYAUTH_AUTH_SECURECOOKIE=true, sonst setzt Tinyauth das Cookie ohneSecure(bei HTTP beobachtet). - Subdomain-Struktur. Die App-URL braucht die Form
sub.domain.tldoderdomain.tld, aufname.duckdns.orggeht es wegen Cookie-Beschränkungen nicht (weitere Subdomain-Ebene nutzen). - Andere Proxys. Nginx Proxy Manager, SWAG und Caddy haben eigene Doku-Anleitungen, bei Nginx Proxy Manager muss „Block Common Exploits“ auf dem Tinyauth-Host aus sein.
- Keine Umgehung. Nur Traefik darf in
docker compose psPorts zeigen. - Client-IP. Für IP-Regeln braucht Traefik in Docker eventuell
network_mode: host.
Die Entwicklertools des Browsers zeigen das Cookie tinyauth-session-… mit Secure für die übergeordnete Domain, docker compose ps zeigt Ports nur bei Traefik.
Schritt 8: Backup und Restore
Sichern Sie compose.yaml, .env, traefik/dynamic.yaml und data (die Datenbank enthält nur Sitzungen).
# Stoppen (konsistente SQLite-Datei)$ cd /opt/tinyauth
$ docker compose stop tinyauth
$ sudo tar czf /backup/tinyauth-$(date +%F).tgz compose.yaml .env traefik/dynamic.yaml data
$ docker compose start tinyauth# Restore$ cd /opt/tinyauth
$ docker compose stop tinyauth
$ sudo rm -rf data
$ sudo tar xzf /backup/tinyauth-2026-09-27.tgz
$ docker compose up -dNach Sichern, Leeren und Zurückspielen von data ist die Sitzung wieder gültig, ohne Restore liefert das Cookie 401 (der Login geht weiter).
tar tzf /backup/tinyauth-*.tgz listet .env und data/tinyauth.db, nach dem Restore gelingt die Anmeldung.
Schritt 9: Updates und Rollback
Pinnen Sie eine Version wie v5.2.0 und lesen Sie die Release-Notes:
# Nach Backup und Tag-Anpassung in compose.yaml$ docker compose pull tinyauth
$ docker compose up -d tinyauth
$ docker compose logs tinyauth | grep 'Starting Tinyauth version'Rollback innerhalb einer Hauptversion: alten Tag eintragen, Backup von data zurückspielen. v5 stellte das Schema auf TINYAUTH_<SECTION>_<KEY> um (Migrationshelfer in der Doku) und verweigert unbekannte TINYAUTH_-Variablen: v4 auf v5 ist kein Tag-Tausch, ein Rollback braucht die alte Konfiguration.
Das Log zeigt die neue Version nach Starting Tinyauth version, und der Zugriff auf die geschützte Anwendung funktioniert nach Login.
Typische Fehler und Diagnose
Diese Meldungen gibt Tinyauth bei den genannten Fehlern aus. Bei Konfigurationsfehlern beendet sich Tinyauth mit Exitcode 1 und der Container startet neu, die Ursache steht in docker compose logs tinyauth.
| Meldung | Ursache | Lösung |
|---|---|---|
failed to parse app url: invalid url | TINYAUTH_APPURL fehlt oder ist leer | Vollständige URL mit Schema setzen |
failed to get cookie domain: invalid app url, must be in format subdomain.domain.tld or domain.tld | App-URL wie http://localhost:3000 ohne Domain | Echte Domain mit Subdomain verwenden |
no authentication providers configured | Kein Benutzer, OAuth oder LDAP | TINYAUTH_AUTH_USERS oder einen Provider setzen |
failed to load users: invalid user format | Eintrag ohne Hash oder falsch maskiert | Mit user create neu erzeugen, mit user verify prüfen |
failed to decode configuration from environment variables: field not found, node: user | Tippfehler (TINYAUTH_AUTH_USER statt USERS) | Namen mit der Konfigurationsreferenz abgleichen |
Too many failed login attempts (HTTP 429) | Drei Fehlversuche, 300 Sekunden Sperre | Warten oder Tinyauth neu starten |
executable file not found in $PATH beim Healthcheck | Doku-Befehl ohne Binary-Namen | docker compose exec tinyauth tinyauth healthcheck |
Landet der Browser nach dem Login wieder auf der Anmeldeseite, liegen Tinyauth und Anwendung nicht unter derselben Domain, oder SECURECOOKIE=true trifft auf HTTP.
Saubere Deinstallation
Achtung: Die Schritte löschen Konfiguration, Benutzer-Hashes, Sitzungsdatenbank und Traefik-Zertifikate unwiderruflich. Sichern Sie vorher und entfernen Sie zuerst die Anwendungen hinter Tinyauth, sonst stehen sie nach dem Proxy-Umbau ungeschützt im Netz.
# Container und Netzwerk entfernen$ cd /opt/tinyauth
$ docker compose down -v --remove-orphans
# Images gezielt entfernen$ docker rmi ghcr.io/tinyauthapp/tinyauth:v5.2.0 traefik/whoami:latest
# Verzeichnis löschen (root-Dateien)$ sudo rm -rf /opt/tinyauthHäufige Fragen
Wann sind Authentik oder Authelia die bessere Wahl?
Bei vielen Konten, Rollen, SAML oder Passkeys. Tinyauth hat keine Verwaltungsoberfläche, keine Selbstbedienung bei vergessenen Passwörtern, keine eigene Rollen- und Gruppenverwaltung und als zweiten Faktor nur TOTP. Laut Doku ist es für Homelabs und kleine Personenkreise gedacht.
Warum landet der Browser nach dem Login wieder auf der Anmeldeseite?
Tinyauth und Anwendung liegen nicht unter derselben übergeordneten Domain, oder SECURECOOKIE=true trifft auf HTTP.
Warum antwortet Tinyauth trotz richtigem Passwort mit 429?
Nach dem dritten Fehlversuch sperrt Tinyauth den Benutzernamen für 300 Sekunden, schon der vierte Versuch liefert 429. Die Sperre liegt nur im Speicher. Ein schwer erratbarer Benutzername statt admin verhindert, dass Fremde Sie aussperren.
Wie kommen weitere Benutzer hinzu?
Erzeugen Sie den Eintrag mit tinyauth user create und hängen Sie ihn durch Komma getrennt an TINYAUTH_AUTH_USERS an. Benutzer ändern heißt Konfiguration ändern und Tinyauth neu starten.
Was gehört ins Backup?
Die Dateien compose.yaml, .env und traefik/dynamic.yaml sowie das Verzeichnis data. Die Benutzer stehen in der .env, die Datenbank in data enthält nur Sitzungen und OIDC-Daten.
Fazit
Tinyauth setzt mit einem einzelnen Container eine Anmeldung per Forward-Auth vor Werkzeuge, die selbst keine haben. Setzen Sie TINYAUTH_APPURL auf HTTPS und TINYAUTH_AUTH_SECURECOOKIE=true, lassen Sie nur Traefik Ports veröffentlichen und schalten Sie die Telemetrie ab. Für viele Konten, Rollen, SAML oder Passkeys sind Authentik oder Authelia die bessere Wahl.
Weiterführende Anleitungen und Quellen
- SSO mit Authentik oder Authelia und Traefik Forward-Auth
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS
- 2FA und MFA richtig einführen
Quellen
- tinyauthapp/tinyauth auf GitHub
- Release v5.2.0
- Tinyauth Doku: Getting Started
- Tinyauth Doku: Konfigurationsreferenz
- Tinyauth Doku: About
- Tinyauth Doku: Telemetry
- Traefik Doku: ForwardAuth: Funktionsweise der Middleware und
authResponseHeaders.


