Nextcloud absichern & optimieren: alle Warnungen abarbeiten (Teil 2)
Die Admin-Übersicht deiner Nextcloud grün bekommen: HSTS-Header, E-Mail-Versand, Zwei-Faktor-Pflicht und Brute-Force-Schutz mit echten IPs einrichten.
Inhaltsverzeichnis
Deine Nextcloud läuft – aber in der Admin-Übersicht leuchten gelbe Warnungen, es gibt keine funktionierende E-Mail und kein zweiter Faktor schützt deine Konten. In diesem zweiten Teil machen wir aus „läuft" ein „sauber abgesichert und flott": Wir arbeiten jede Warnung ab, bis die Übersicht grün ist.
Was bauen wir?
Am Ende zeigt die Sicherheits- & Einrichtungsübersicht deiner Nextcloud keine Warnungen mehr. Konkret bauen wir auf der Installation aus Teil 1 auf und ergänzen: den fehlenden HSTS-Sicherheitsheader über Traefik, ein konfiguriertes Wartungsfenster, den funktionierenden E-Mail-Versand (für Passwort-Resets und Benachrichtigungen), eine erzwungene Zwei-Faktor-Authentifizierung und einen Brute-Force-Schutz, der die echten Angreifer-IPs sieht – die Grundlage für Fail2ban.
Getestet ist alles gegen Nextcloud 34.0.1 hinter Traefik v3.7 auf Debian 13 mit PHP 8.5. Das ist Fleißarbeit, aber genau die Fleißarbeit, die in 90 % aller Nextcloud-Anleitungen fehlt – und die den Unterschied zwischen „irgendwie online" und „vernünftig betrieben" ausmacht.
Voraussetzungen
- Eine laufende Nextcloud wie in
Nextcloud selbst hosten (Teil 1) aufgesetzt:
klassisches
nextcloud-Image hinter Traefik, mit MariaDB, Redis und Cron-Sidecar. Die Container-Namen aus Teil 1 (nc-app,nc-db,nc-redis,nc-cron) und der Compose-Ordner~/nextcloudsind hier die Basis. - SSH-Zugriff auf den Server und das Kommandozeilen-Werkzeug
occ– wir rufen es wie in Teil 1 im App-Container auf:docker exec -u www-data nc-app php occ <befehl>. - Ein Traefik-Reverse-Proxy mit dem
proxy-Netz und dem Resolverlewie im Tutorial Reverse Proxy mit Traefik – die Sicherheits-Header hängen wir als Traefik-Middleware an.
occ im Griff behalten
occ ist Nextclouds Admin-Werkzeug. Weil die Container in Teil 1 feste Namen bekommen
haben (container_name), sprichst du den App-Container direkt an – egal, in welchem
Verzeichnis du bist:
docker exec -u www-data nc-app php occ statusDu solltest installed: true und deine Version sehen. Diesen Präfix
(docker exec -u www-data nc-app php occ …) kürzen wir im Folgenden nicht ab – so kannst
du jeden Befehl direkt kopieren. Nur die wenigen docker compose …-Befehle (etwa der
Container-Neustart in Schritt 3) führst du weiterhin aus dem Ordner ~/nextcloud aus.
Schritt für Schritt
Schritt 1: Die Admin-Übersicht als Bestandsaufnahme lesen
Melde dich als Administrator an und öffne Administrationseinstellungen → Übersicht. Oben steht der Abschnitt „Sicherheits- & Einrichtungswarnungen". Direkt nach einer Standardinstallation sieht das so aus:

Nextcloud unterscheidet drei Stufen: gelbe Warnungen (⚠, solltest du beheben), blaue Hinweise (ℹ, meist optional) und stillschweigend bestandene Prüfungen. Bei unserer frischen Instanz stehen drei Warnungen und ein paar Hinweise an:
- ⚠ Beginn des Wartungsfensters ist nicht gesetzt (Schritt 2)
- ⚠ MIME-Type-Migrationen verfügbar (Schritt 2)
- ⚠ HTTP-Header – der
Strict-Transport-Security-Header fehlt (Schritt 3) - ℹ E-Mail-Test – noch kein Mailserver hinterlegt (Schritt 4)
- ℹ Zwei-Faktor-Konfiguration – 2FA ist verfügbar, aber nicht verpflichtend (Schritt 5)
Denselben Bericht bekommst du auch auf der Kommandozeile – praktisch, um den Fortschritt zwischendurch zu prüfen, ohne durch die Weboberfläche zu klicken:
docker exec -u www-data nc-app php occ setupchecksDer Befehl gibt jede Prüfung mit ✓, ⚠ oder ✗ aus. Genau diese Liste arbeiten wir jetzt von oben nach unten ab.
Schritt 2: Die zwei schnellen Warnungen beheben
Zwei Warnungen sind mit je einem Befehl erledigt.
Wartungsfenster festlegen. Nextcloud führt einmal täglich rechenintensive
Aufräumjobs aus (Vorschauen, Aktivitäten, Kalender-Wiederholungen). Ohne definiertes
Zeitfenster laufen die irgendwann – auch mitten am Tag. Leg einen Startzeitpunkt fest,
zu dem kaum jemand arbeitet. Der Wert ist eine volle Stunde in UTC; 1 legt den
Beginn auf 01:00 UTC – der Check meldet danach das Fenster von 1:00 bis 7:00 UTC:
docker exec -u www-data nc-app php occ config:system:set maintenance_window_start --type=integer --value=1Zur Kontrolle bestätigt der Setup-Check danach:
✓ Maintenance window start: Maintenance window to execute heavy background jobs is between 1:00 UTC and 7:00 UTCMIME-Type-Migrationen ausführen. Gelegentlich lernt Nextcloud neue Dateitypen (etwa für bessere Icons und Vorschauen). Diese Migration läuft bei Updates nicht automatisch, weil sie auf großen Instanzen dauern kann. Auf einer frischen Cloud ist sie in Sekunden durch:
docker exec -u www-data nc-app php occ maintenance:repair --include-expensiveDu siehst eine Liste abgearbeiteter Reparaturschritte (u. a. Repair mime types).
Danach meldet der Check Mimetype migrations available: None. Zwei Warnungen weniger.
Und die blauen Hinweise?
Schritt 3: Den HSTS-Sicherheitsheader über Traefik setzen
Die dritte Warnung ist die wichtigste: Der Strict-Transport-Security-Header (HSTS)
fehlt. Er weist den Browser an, diese Domain ausschließlich über HTTPS anzusprechen –
auch dann, wenn jemand http:// eintippt oder ein Angreifer die Verbindung umzubiegen
versucht. Ohne HSTS bleibt ein kleines Zeitfenster für Downgrade-Angriffe offen.
Weil unsere Nextcloud hinter Traefik sitzt, setzen wir den Header im Proxy, nicht in
Nextcloud – dort gehört er hin, denn Traefik terminiert das TLS. Ergänze in der
compose.yaml deiner Nextcloud (aus Teil 1) die Middleware nc-secure und häng sie an
den Router. Konkret ändern sich zwei Stellen im labels-Block von nc-app.
Erstens die Router-Zeile um nc-secure erweitern:
- "traefik.http.routers.nc.middlewares=nc-dav,nc-secure"Zweitens die Header-Middleware definieren (direkt bei den anderen nc-app-Labels):
- "traefik.http.middlewares.nc-secure.headers.stsSeconds=15552000"
- "traefik.http.middlewares.nc-secure.headers.stsIncludeSubdomains=true"stsSeconds=15552000 sind 180 Tage – der von Nextcloud geforderte Mindestwert. Übernimm
die Änderung und lade nur den App-Container neu:
docker compose up -d nc-appPrüfe nach ein paar Sekunden von deinem eigenen Rechner aus, dass der Header wirklich ausgeliefert wird:
curl -sS -I https://cloud.DEINE_DOMAIN/ | grep -i strict-transportDu solltest genau das sehen:
strict-transport-security: max-age=15552000; includeSubDomainsIn der Admin-Übersicht wird die HTTP-Header-Warnung damit grün: „Your server is correctly
configured to send security headers." Die übrigen Header (X-Content-Type-Options,
X-Frame-Options, Referrer-Policy …) liefert Nextcloud selbst aus – nur HSTS musste vom
Proxy kommen.
preload ist eine Einbahnstraße
stsIncludeSubdomains=true erweitert den HTTPS-Zwang auf alle Subdomains von
cloud.DEINE_DOMAIN (nicht auf Geschwister wie www.DEINE_DOMAIN – der Header gilt
immer nur für den Host, der ihn ausliefert). Bewusst nicht gesetzt ist
stsPreload=true: Damit würdest du signalisieren, dass du die Domain in die
HSTS-Preload-Liste der Browser eintragen lassen willst – und
so ein Eintrag ist nur mit wochenlangem Vorlauf wieder rückgängig zu machen. Falls du
das eines Tages bewusst willst: Die Preload-Liste akzeptiert nur max-age ≥ 31536000
(1 Jahr) – mit den 15552000 oben wäre das Flag ohnehin wirkungslos. Setze preload
nur, wenn wirklich jeder Dienst unter der Domain dauerhaft HTTPS spricht; der Header
ist auch ohne vollwertig.Schritt 4: E-Mail-Versand einrichten
Ohne funktionierenden Mailversand kann Nextcloud keine Passwort-Resets verschicken, keine Freigabe-Benachrichtigungen und keine Sicherheitswarnungen – und der Hinweis „E-Mail-Test" bleibt stehen. Das holen wir nach.
Öffne Administrationseinstellungen → Grundeinstellungen und scroll zum Abschnitt „E-Mail-Server". Trag die Zugangsdaten deines Mail-Anbieters ein:
- Sendemodus:
SMTP - Verschlüsselung:
SSL/TLS(Port 465) oderSTARTTLS(Port 587) – nie unverschlüsselt - Absenderadresse: z. B.
cloud@DEINE_DOMAIN - Serveradresse: Host und Port deines Anbieters
- Authentifizierung: einschalten und Benutzername/Passwort hinterlegen
Trag oben unter Persönliche Informationen eine E-Mail-Adresse für dein Admin-Konto ein (dorthin geht die Testmail). Dann klick auf „Test-E-Mail senden". Kommt die Mail an, bestätigt Nextcloud das mit einer grünen Meldung:

App-Passwort statt Kontopasswort
Schritt 5: Zwei-Faktor-Authentifizierung erzwingen
Ein gestohlenes Passwort ist der häufigste Weg, wie Konten übernommen werden. Ein zweiter Faktor (ein zeitbasierter Code aus einer Authenticator-App, TOTP) macht das Passwort allein wertlos. Nextcloud bringt den passenden Anbieter schon mit – wir müssen ihn nur aktivieren und zur Pflicht machen.
Aktiviere zunächst die TOTP-App (sie ist im Lieferumfang enthalten):
docker exec -u www-data nc-app php occ app:enable twofactor_totpJeder Nutzer richtet seinen zweiten Faktor danach selbst ein – unter Persönliche Einstellungen → Sicherheit → „TOTP (Authenticator-App)". Beim Aktivieren zeigt Nextcloud einen QR-Code, den man mit einer App wie Aegis, andOTP oder Google Authenticator scannt. Zusätzlich empfiehlt sich die App „Zwei-Faktor-Backup-Codes" – die einmaligen Codes retten dich, wenn das Handy verloren geht.
Damit niemand die Absicherung „vergisst", erzwingst du 2FA für die Administratoren. Im Web findest du das unter Administrationseinstellungen → Sicherheit → „Zwei-Faktor- Authentifizierung erzwingen", per Kommandozeile geht es so:
docker exec -u www-data nc-app php occ twofactorauth:enforce --on --group=admin
Sperr dich nicht selbst aus
docker exec -u www-data nc-app php occ twofactorauth:enforce --off. Einen
einzelnen festgefahrenen Faktor entfernst du mit
… php occ twofactorauth:disable BENUTZER totp.Schritt 6: Brute-Force-Schutz mit echten IPs – Basis für Fail2ban
Nextcloud drosselt fehlgeschlagene Logins von Haus aus: Nach mehreren Fehlversuchen
verzögert es weitere Anfragen derselben IP. Dieser Schutz steht und fällt aber damit,
dass Nextcloud die echte Client-IP sieht – und nicht die interne IP von Traefik. Genau
das leistet die TRUSTED_PROXIES-Einstellung aus Teil 1.
Ob es funktioniert, siehst du unter Administrationseinstellungen → Sicherheit im Kasten „Brute-Force-Zulassungsliste" (im Screenshot oben). Dort steht deine aktuelle, korrekt erkannte öffentliche IP:
Ihre aktuelle IP-Adresse wird als "DEINE_IP" erkannt. Diese Adresse wird derzeit nicht gedrosselt.Steht da stattdessen eine 172.x.x.x-Adresse aus dem Docker-Netz, greift TRUSTED_PROXIES
nicht – dann würde der Brute-Force-Schutz alle Nutzer über einen Kamm scheren und im
Zweifel Traefik selbst sperren. In dem Fall zurück zu Teil 1, Schritt 2/3.
Harte Sperren mit Fail2ban. Die eingebaute Drosselung verzögert nur; wer Angreifer
richtig aussperren will, kombiniert Nextcloud mit
Fail2ban. Nextcloud protokolliert jeden Fehlversuch im
JSON-Log – und dank TRUSTED_PROXIES mit der echten IP:
{"level":2,"time":"2026-07-18T08:14:05+00:00","remoteAddr":"203.0.113.47","user":"--","app":"no app in context","method":"POST","url":"/login","message":"Login failed: BENUTZER (Remote IP: 203.0.113.47)"}Dieses Log liegt im Nextcloud-Volume. Den Pfad auf dem Host findest du so:
docker inspect -f '{{ range .Mounts }}{{ if eq .Destination "/var/www/html" }}{{ .Source }}{{ end }}{{ end }}' nc-appDarunter liegt die Datei data/nextcloud.log. Auf die zeigst du einen Fail2ban-Filter,
der auf remoteAddr matcht, plus ein Jail nach dem Muster aus dem
Fail2ban-Tutorial. So wandert nach ein paar
Fehlversuchen die Angreifer-IP direkt in die Firewall – bevor die Anfrage Nextcloud
überhaupt erreicht.
Schritt 7: Caching & PHP prüfen – das Performance-Fundament
Zum Schluss vergewissern wir uns, dass die Performance-Basis steht. Vieles davon hat Teil 1
über die REDIS_HOST-Variable schon automatisch eingerichtet – prüfen schadet trotzdem
nicht, denn genau hier wird eine Nextcloud zäh oder flott.
Nextcloud nutzt drei Cache-Rollen. Kontrolliere alle drei:
docker exec -u www-data nc-app php occ config:system:get memcache.local
docker exec -u www-data nc-app php occ config:system:get memcache.distributed
docker exec -u www-data nc-app php occ config:system:get memcache.lockingErwartet:
\OC\Memcache\APCu
\OC\Memcache\Redis
\OC\Memcache\Redis- Lokaler Cache (APCu): hält häufig genutzte Daten im RAM des PHP-Prozesses – der spürbarste Beschleuniger im Alltag.
- Verteilter Cache (Redis): teilt Cache-Daten über Prozesse hinweg, wichtig sobald App- und Cron-Container zusammenspielen.
- File-Locking (Redis): verhindert, dass zwei Zugriffe dieselbe Datei gleichzeitig verändern und sie beschädigen. Der Grund, warum wir in Teil 1 überhaupt Redis eingebaut haben.
Passt das Zusammenspiel, meldet docker exec -u www-data nc-app php occ setupchecks die
Zeile ✓ Memcache: Configured. (Bestandene Prüfungen zeigt die Web-Übersicht nicht an –
dort tauchen nur Warnungen und Hinweise auf, deshalb kontrollierst du das hier per CLI.)
OPcache – der Bytecode-Cache von PHP – ist im offiziellen nextcloud-Image bereits
sinnvoll vorkonfiguriert (u. a. opcache.interned_strings_buffer=32). Du musst hier also
nichts nachziehen; die früher berüchtigte OPcache-Warnung taucht mit aktuellen Images gar
nicht mehr auf. Nachschauen kannst du bei Bedarf so:
docker exec -u www-data nc-app php -i | grep opcache.interned_strings_bufferDamit ist die Übersicht warnungsfrei:

Vorschaubilder gezielt erzeugen
occ-Cronjob erzeugt Vorschaubilder im Voraus, statt sie beim ersten Öffnen langsam on
the fly zu berechnen. Ergänzt du sie, begrenze über
occ config:system:set preview_max_x --value=2048 (und preview_max_y) die maximale
Vorschaugröße, sonst wächst der Speicherbedarf schnell.Wenn es nicht funktioniert
Symptom: Nach dem Traefik-Neustart erscheint der HSTS-Header nicht in der curl-Ausgabe.
Ursache & Lösung: Meist ist die Middleware nicht am Router. Prüfe, dass die Zeile
traefik.http.routers.nc.middlewares beide Middlewares nennt (nc-dav,nc-secure) und
dass die drei nc-secure-Header-Labels im nc-app-Block stehen. Danach
docker compose up -d nc-app. Traefik übernimmt geänderte Labels erst beim Neu-Erstellen
des Containers.
Symptom: Der E-Mail-Test schlägt fehl („Es gab ein Problem beim Senden der E-Mail").
Ursache & Lösung: Fast immer Port/Verschlüsselung oder Authentifizierung. Kombiniere
SSL/TLS mit Port 465 oder STARTTLS mit Port 587 – nicht kreuzweise. Nutzt dein
Anbieter 2FA, brauchst du ein App-Passwort (siehe Schritt 4). Details stehen im
Nextcloud-Log: docker exec -u www-data nc-app php occ log:tail 20.
Symptom: Du kommst nach dem Erzwingen von 2FA selbst nicht mehr rein.
Ursache & Lösung: Du hattest noch keinen zweiten Faktor eingerichtet. Hebe die Pflicht
per Kommandozeile auf, richte deinen Faktor in Ruhe ein und schalte sie danach wieder
scharf: docker exec -u www-data nc-app php occ twofactorauth:enforce --off.
Symptom: Im Brute-Force-Kasten steht eine 172.x.x.x-Adresse statt deiner echten IP.
Ursache & Lösung: TRUSTED_PROXIES passt nicht zum tatsächlichen proxy-Subnetz.
Ermittle es mit docker network inspect proxy -f '{{(index .IPAM.Config 0).Subnet}}' und
trag den Wert in der nc-app-Umgebung ein (Teil 1, Schritt 2). Sonst sperrt der
Brute-Force-Schutz im Ernstfall den Proxy und damit alle Nutzer.
Symptom: Nach einem Reboot meldet Nextcloud „Redis went away" oder wird sehr langsam.
Ursache & Lösung: Der App-Container ist vor Redis gestartet. Stelle sicher, dass
nc-redis in depends_on steht (Teil 1) und mit restart: unless-stopped läuft – dann
fängt Docker den Startreihenfolge-Fall selbst ab.
Wartung & Backups
- Übersicht nach jedem Update prüfen. Neue Nextcloud-Versionen bringen neue Checks
mit. Wirf nach jedem Upgrade einen Blick auf Administrationseinstellungen → Übersicht
oder lass
occ setupcheckslaufen – so fängst du neue Warnungen früh ab. - Regelmäßig den offiziellen Security-Scan nutzen. Der Nextcloud Security Scan prüft deine Domain von außen und vergibt eine Note. Mit HSTS und aktuellen Versionen ist A/A+ das realistische Ziel; fällt die Note, ist meist ein Update überfällig.
- Zweite Faktoren im Blick behalten. Bewahre die Backup-Codes getrennt vom Handy auf.
Verliert ein Nutzer sein Gerät, entfernst du seinen Faktor mit
occ twofactorauth:disable BENUTZER totp, danach richtet er ihn neu ein. - App-Passwörter aufräumen. Jeder verbundene Client (Desktop, Handy) bekommt ein eigenes App-Passwort. Unter Persönliche Einstellungen → Sicherheit siehst du alle Geräte und kannst einzelne bei Verlust gezielt widerrufen.
- Die Absicherung ersetzt kein Backup. All das schützt vor fremdem Zugriff, nicht vor Datenverlust. Die konsistente Sicherung aus Datenbank-Dump und Datenverzeichnis bleibt Pflicht – siehe den Wartungsabschnitt in Teil 1 und Backups mit Restic. Ehrlich zum Aufwand: Plane den monatlichen Update-Durchgang mit einem kurzen Blick auf die Übersicht fest ein – dann bleibt deine Cloud dauerhaft grün.
Feedback per E-Mail: feedback@serverkueche.de
Das könnte dir auch schmecken

Immich selbst hosten: dein privates Foto-Backup hinter Traefik
Immich mit Docker hinter Traefik aufsetzen: die selbst gehostete Alternative zu Google Fotos – mit automatischem …

Paperless-ngx selbst hosten: papierloses Büro mit OCR
Paperless-ngx mit Docker hinter Traefik aufsetzen: Dokumente per OCR durchsuchbar archivieren – mit Volltextsuche, Tags …

Uptime Kuma installieren: Server-Monitoring hinter Traefik
Uptime Kuma hinter Traefik aufsetzen und deine Dienste überwachen: Monitore, Benachrichtigungen und eine Status-Seite – …