Nextcloud selbst hosten: Lohnt sich das 2026 noch?
Nextcloud 34 selbst betreiben: was es wirklich an RAM, Platz und Zeit kostet, wo es überraschend langsam wird — und warum das naheliegende Backup-Verfahren sich bei uns nicht zurückspielen ließ. Mit nachgemessenen Werten aus dem eigenen Homelab.
Von Niclas Hennrich · Veröffentlicht: · 19 Min. Lesezeit
Getestet mit
- Nextcloud 34.0.3
- PostgreSQL 16
- Redis 8
- Docker Engine 29.7.2
- Docker Compose 5.5.0
- Debian 13
Technisch verifiziert am
Kurz gesagt: Nextcloud lohnt sich, wenn du Dateien, Kalender, Kontakte und Freigaben für mehrere Geräte oder Personen unter eigener Kontrolle betreiben willst. Die Installation ist nicht das Problem — bei uns lief die Instanz nach 20 Sekunden und braucht im Leerlauf 168 MiB RAM. Der Aufwand steckt im Betrieb: Updates kommen nicht von selbst, Warnungen meldet niemand, und das Backup-Verfahren, das in fast jeder Anleitung steht, ließ sich bei uns nicht zurückspielen.
Was du bekommst und was du dafür übernimmst #
| Ziel | Eigene Cloud mit Dateien, Kalender, Kontakten, Freigabelinks und Apps |
| Schwierigkeit | Mittel — Docker Compose und ein Reverse Proxy müssen sitzen |
| Aufwand einmalig | Installation unter einer Minute, Grundkonfiguration und Backup-Einrichtung ein bis zwei Stunden |
| Aufwand laufend | Updates etwa alle vier Wochen, Backup-Kontrolle, Restore-Übung |
| Du brauchst | Dauerlaufenden Server mit Docker, festen Namen oder feste IP, rund 4 GB Platz vor der ersten eigenen Datei, ein separates Backup-Ziel |
| Getestet | Ja — eigene Testinstanz, vermessen und Restore durchgespielt |
Lohnt sich Nextcloud für dich? #
Nextcloud ist kein Dropbox-Ersatz, den man installiert und dann vergisst. Es ist eine PHP-Anwendung mit Datenbank, Cache und Hintergrundjobs — also ein Server, den du betreibst.
Nextcloud lohnt sich, wenn du …
- mehr als Dateisynchronisation willst: Kalender, Kontakte, Freigaben und Dokumente in einem System, mit einer Benutzerverwaltung
- ohnehin einen Server mit Docker betreibst — 168 MiB RAM fallen dort nicht ins Gewicht
- mit mittleren und großen Dateien arbeitest: Dokumente, Fotos, Videos
- Freigabelinks an Leute schicken willst, die kein Konto haben
- bereit bist, Backup und Restore einmal richtig aufzusetzen und zu testen
Nextcloud lohnt sich weniger, wenn du …
- nur Dateien zwischen eigenen Geräten abgleichen willst — dafür sind Datenbank, Webserver und Benutzerverwaltung drei Dienste zu viel
- sehr viele kleine Dateien ablegen willst: Quellcode-Bäume, Mail-Archive, Abhängigkeitsverzeichnisse. Wir haben 3,24 Dateien pro Sekunde gemessen — das ist keine Zahl, mit der man arbeiten möchte
- keine laufende Wartung leisten willst: Updates kommen nicht von selbst, Warnungen meldet niemand, und ein ungetestetes Backup fällt erst im Ernstfall auf
- HTTPS ohne Zusatzkomponente erwartest — ohne Reverse Proxy bleibt es bei einfachem HTTP im lokalen Netz
Unsere Einschätzung: Für ein bis zwei Personen, die im Kern Dateisync suchen, ist Nextcloud Overkill. Ab Kalender und Kontakten dreht sich das, weil die Alternative sonst „drei Dienste statt einer" heißt. Der ehrlichste Satz zur Entscheidung stammt aus unserem eigenen Betrieb: Die Installation kostet Minuten, der verantwortungsvolle Betrieb kostet dauerhaft Aufmerksamkeit.
Ob sich das auch finanziell rechnet, hängt an Hardware und Strom — dafür haben wir den Cloud-vs.-Selfhosting-Rechner.
Welche Version, und wie lange bekommt sie Updates? #
Nextcloud veröffentlicht etwa alle vier Monate eine neue Hauptversion und pflegt jede davon ein Jahr mit Wartungs-Releases. Danach gibt es keine Sicherheitsupdates mehr. Stand August 2026:
| Version | Erschienen | Support-Ende |
|---|---|---|
| 34 (Hub 26 Spring) | Juni 2026 | Juni 2027 |
| 33 (Hub 26 Winter) | Februar 2026 | Februar 2027 |
| 32 (Hub 25 Autumn) | September 2025 | September 2026 |
Version 35 ist für September 2026 geplant. Wer heute neu aufsetzt, nimmt 34 — das ist auch die Version, die wir vermessen haben. Wer noch auf 32 sitzt, hat kein Update-Problem, sondern ein Zeitproblem.
Die aktuelle Fassung dieser Tabelle steht immer im Release-Zeitplan im Nextcloud-Wiki.
Systemanforderungen #
Aus den offiziellen Anforderungen für Nextcloud 34:
| PHP | 8.3, 8.4, 8.5 empfohlen — 8.2 ist abgekündigt |
| PostgreSQL | 14 bis 18, 18 empfohlen |
| MariaDB | 10.6, 10.11, 11.4, 11.8 empfohlen |
| MySQL | 8.0, 8.4 |
| SQLite | 3.24+, ausdrücklich nur für Tests |
| Webserver | Apache 2.4 mit mod_php oder php-fpm (empfohlen), oder nginx mit php-fpm |
| RAM | mindestens 128 MB je Prozess, empfohlen 512 MB je Prozess |
„Je Prozess" ist die Angabe, die am häufigsten falsch gelesen wird: Das ist kein Gesamtwert für den Server. Unsere frisch installierte Instanz kam im Leerlauf mit 168 MiB für alle vier Container zusammen aus — unter Last stieg allein der Nextcloud-Container aber auf 284 MiB. Mehrere gleichzeitige Anfragen bedeuten mehrere PHP-Prozesse; für eine Familieninstanz plant man deshalb sinnvollerweise mit ein bis zwei Gigabyte, nicht mit 168 MiB.
Beim offiziellen Docker-Image musst du dich um PHP und Webserver nicht kümmern — beides steckt im Image und passt zur jeweiligen Nextcloud-Version.
Welche Architektur wir aufbauen #
Client (Web, Desktop-Sync, Android/iOS, CalDAV/CardDAV)
│
│ HTTPS
▼
Reverse Proxy Zertifikat, HTTPS-Terminierung
│ (Caddy, nginx, Traefik — deine Wahl)
│ HTTP, nur lokal
▼
nextcloud:apache ◄────────────── cron
│ │ │ (gleiches Image, gleiches Volume,
│ │ │ entrypoint /cron.sh)
│ │ └──────────► redis Cache + File Locking
│ └─────────────► postgres Datenbank
└────────────────► Volume config, data, custom_apps, themesVier Container, ein Reverse Proxy. Warum genau so:
- PostgreSQL statt SQLite, weil SQLite offiziell nur für Tests vorgesehen ist und ein späterer Wechsel unnötige Arbeit mit Fehlerrisiko bedeutet.
- Redis, weil Nextcloud sonst die Datenbank für File Locking benutzt. Der Unterschied war bei uns in den Systemprüfungen direkt sichtbar: Testinstanz „Transactional File Locking ✓", die ältere Produktivinstanz ohne Redis meldete Locking über die Datenbank.
- Ein eigener Cron-Container, weil der empfohlene Ausführungsmodus für Hintergrundjobs echtes Cron ist — nicht AJAX, das nur läuft, wenn jemand die Weboberfläche öffnet.
- Reverse Proxy getrennt, weil auf einem Homeserver selten nur ein Dienst läuft und Zertifikate an genau einer Stelle gehören.
Es gibt mit Nextcloud All-in-One eine offizielle Alternative, die diesen Stack samt Backup-Lösung hinter einem Master-Container versteckt. Das ist bequem, gibt aber Kontrolle über Containernamen, Volumes und Netzwerk ab. Wenn du bereits Docker Compose fährst, bleib bei den Einzelcontainern.
Installation #
1. Verzeichnis und Zugangsdaten anlegen #
sudo mkdir -p /opt/nextcloud
cd /opt/nextcloudDie Datenbank-Zugangsdaten kommen in eine eigene Datei, die Datenbank- und
Nextcloud-Container gemeinsam lesen — so steht das Passwort genau einmal im
System und nicht in der compose.yaml:
umask 077
cat > db.env <<'EOF'
POSTGRES_DB=nextcloud
POSTGRES_USER=nextcloud
POSTGRES_PASSWORD=CHANGE_ME
EOFErsetze CHANGE_ME durch ein langes, zufälliges Passwort:
openssl rand -base64 32Prüfen:
ls -l db.envErwartet: -rw-------. Steht dort etwas anderes, korrigiere mit
chmod 600 db.env. Und: db.env gehört nicht in ein Git-Repository.
2. compose.yaml schreiben #
sudo nano /opt/nextcloud/compose.yamlservices:
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db:/var/lib/postgresql/data
env_file:
- db.env
redis:
image: redis:8-alpine
restart: unless-stopped
app:
image: nextcloud:34-apache
restart: unless-stopped
ports:
# Nur lokal gebunden — von außen erreichbar ist allein der Reverse Proxy
- "127.0.0.1:8080:80"
volumes:
- nextcloud:/var/www/html
environment:
- POSTGRES_HOST=db
- REDIS_HOST=redis
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.example.com
- OVERWRITEPROTOCOL=https
- OVERWRITEHOST=nextcloud.example.com
- TRUSTED_PROXIES=172.16.0.0/12
env_file:
- db.env
depends_on:
- db
- redis
cron:
image: nextcloud:34-apache
restart: unless-stopped
# Gleiches Image und gleiches Volume wie app — das ist Pflicht,
# sonst läuft der Cron gegen eine andere Installation.
volumes:
- nextcloud:/var/www/html
entrypoint: /cron.sh
depends_on:
- db
- redis
volumes:
db:
nextcloud:Was du anpassen musst:
nextcloud.example.com→ dein tatsächlicher Name. Betreibst du Nextcloud nur im LAN ohne Domain, trägst du hier Hostname oder IP mit Port ein und lässtOVERWRITEPROTOCOL,OVERWRITEHOSTundTRUSTED_PROXIESweg.TRUSTED_PROXIES→ das Netz, aus dem dein Reverse Proxy kommt.
Zur Datenbankversion: Wir haben mit postgres:16 gemessen — deshalb steht
sie hier. Offiziell empfohlen ist inzwischen PostgreSQL 18; unterstützt sind 14
bis 18. Wenn du neu aufsetzt und nicht exakt unseren Teststand nachbauen willst,
ist 18 die bessere Wahl.
Warum ein fester Tag und nicht latest: Weil Nextcloud keine übersprungenen
Hauptversionen erlaubt. Mit latest kann ein docker compose pull dich über
eine Hauptversion hinwegtragen, und die Installation bleibt beim Upgrade stehen.
Der Versionssprung soll eine Entscheidung sein, kein Nebeneffekt.
3. Starten #
cd /opt/nextcloud
sudo docker compose up -dPrüfen:
sudo docker compose psErwartet: vier Dienste, alle running — app, cron, db, redis.
Wie schnell das geht, haben wir gemessen: docker compose up -d brauchte 0,81
Sekunden, nach 7,95 Sekunden antwortete Nextcloud über HTTP. Das gilt allerdings
nur, wenn die Images bereits lokal liegen — beim ersten Mal kommt der Download
von rund 3 GB dazu.
Ist app in einer Neustartschleife, sieh dir die Logs an:
sudo docker compose logs --tail=50 appDer häufigste Fehler beim Erstlauf: app startet schneller, als PostgreSQL
initialisiert ist. Ein docker compose restart app löst das; kommt der Fehler
wieder, stimmen die Werte in db.env nicht überein.
4. Reverse Proxy davorsetzen #
Nextcloud lauscht jetzt auf 127.0.0.1:8080. Der Reverse Proxy terminiert HTTPS
und reicht die Anfragen weiter. Mit Caddy sind das zwei Zeilen:
nextcloud.example.com {
reverse_proxy 127.0.0.1:8080
}Caddy holt das Zertifikat selbst. Mit nginx oder Traefik ist es mehr Konfiguration, aber dieselbe Aufgabe. Wichtig in jedem Fall: großzügige Limits für Upload-Größe und Timeouts, sonst brechen große Dateien ab.
Prüfen:
curl -I https://nextcloud.example.comErwartet: 200 oder eine Weiterleitung auf /login. Kommt 400, kennt
Nextcloud den Hostnamen nicht — siehe
Trusted Domains.
5. Admin-Konto anlegen #
Ruf https://nextcloud.example.com im Browser auf. Weil die Datenbank bereits
über Umgebungsvariablen konfiguriert ist, fragt der Einrichtungsassistent nur
noch nach Benutzername und Passwort des Administrators. Bei uns dauerte die
eigentliche Installation 11,76 Sekunden.
Warum über den Browser und nicht über NEXTCLOUD_ADMIN_USER /
NEXTCLOUD_ADMIN_PASSWORD: Beide Variablen funktionieren und sind für
automatisiertes Aufsetzen gedacht — sie schreiben das Admin-Passwort aber in
eine Datei auf der Platte und in die Container-Umgebung. Für eine Installation,
die du einmal von Hand machst, gibt es dafür keinen Grund.
Der erste Benutzer ist Administrator. Leg dir für den täglichen Gebrauch ein zweites, normales Konto an.
Die vier Warnungen nach der Installation #
Frisch installiert meldete occ setupchecks bei uns vier Punkte. Drei davon
waren mit je einem Befehl erledigt, die vierte braucht HTTPS:
| Warnung | Behebung | Dauer bei uns |
|---|---|---|
| Cron lief noch nie | Cron-Container + occ background:cron | sofort |
| kein Wartungsfenster gesetzt | maintenance_window_start setzen | sofort |
| offene Mimetype-Migration | occ maintenance:repair --include-expensive | 0,96 s |
| fehlende Datenbank-Indizes | occ db:add-missing-indices | 0,43 s |
| fehlende HTTP-Header (HSTS) | braucht HTTPS, also den Reverse Proxy | bleibt offen |
Die Sekundenangaben gelten für eine leere Instanz. Nextcloud warnt ausdrücklich, dass Mimetype-Migration und Index-Lauf auf gewachsenen Installationen deutlich länger dauern können.
Alle folgenden Befehle laufen über occ, das Kommandozeilenwerkzeug von
Nextcloud, als Webserver-Benutzer:
sudo docker compose exec --user www-data app php occ statusErwartet: installed: true und die laufende Version.
Hintergrundjobs auf Cron umstellen #
Der cron-Container läuft bereits, aber Nextcloud muss wissen, dass es den
Cron-Modus benutzen soll — Standard ist AJAX:
sudo docker compose exec --user www-data app php occ background:cronAus dem echten Betrieb: Beim ersten Cron-Lauf brach die Ausführung bei uns mit
SQLSTATE[23505] Unique violation … duplicate key value violates unique constraint class_indexab. Das sah nach einem Datenbankdefekt aus, war aber keiner: Der Cron-Container und ein von Hand gestartetercron.php-Lauf liefen gleichzeitig und wollten denselben Hintergrundjob erstmalig registrieren. Der zweite, allein laufende Durchgang lief fehlerfrei durch. Ein Cron-Container ersetzt den manuellen Aufruf — er ergänzt ihn nicht.
Der erste Cron-Lauf dauerte bei uns 75,5 Sekunden, jeder weitere 0,31 Sekunden. Der erste Lauf arbeitet die anfänglichen Hintergrundjobs ab; wenn er lange läuft, ist das normal.
Optional das Wartungsfenster für nicht zeitkritische Jobs setzen — 1 bedeutet
01:00 bis 05:00 UTC:
sudo docker compose exec --user www-data app \
php occ config:system:set maintenance_window_start --type=integer --value=1Prüfen: Administrationseinstellungen → Grundeinstellungen zeigt bei den Hintergrundaufgaben „Cron", und die letzte Ausführung liegt weniger als 15 Minuten zurück.
Caching — meist schon erledigt #
Empfohlen wird APCu als lokaler Cache und Redis für verteilten Cache und File Locking.
Der Redis-Teil war bei uns ohne eigene Konfiguration aktiv: Das offizielle
Image setzt memcache.distributed und memcache.locking allein aufgrund der
Umgebungsvariable REDIS_HOST. Das ist einer der Punkte, an denen Nextcloud
besser ist als sein Ruf.
APCu ergänzt du bei Bedarf:
sudo docker compose exec --user www-data app \
php occ config:system:set memcache.local --value='\OC\Memcache\APCu'Prüfen: Unter Administrationseinstellungen → Übersicht darf keine Warnung zu Memory-Cache oder Transactional File Locking mehr stehen.
Telefonregion setzen #
Ohne diese Einstellung meckert die Admin-Übersicht, und Nutzer können Telefonnummern nicht ohne Ländervorwahl speichern:
sudo docker compose exec --user www-data app \
php occ config:system:set default_phone_region --value=DETrusted Domains und Trusted Proxies verstehen #
Diese beiden Parameter sind der häufigste Grund, warum eine frische Nextcloud „kaputt" wirkt — und beide sind Sicherheitsmechanismen, keine Schikane.
trusted_domains ist die Liste der Hostnamen, unter denen sich Nutzer anmelden
dürfen. Die Doku nennt den Zweck ausdrücklich: Sie verhindert Host Header
Poisoning. Steht ein angefragter Name nicht in der Liste, antwortet Nextcloud
mit HTTP 400 — hart und ohne freundliche Seite.
# Alle aktuell eingetragenen Domains anzeigen
sudo docker compose exec --user www-data app \
php occ config:system:get trusted_domains
# Einen weiteren Eintrag an Position 1 setzen
sudo docker compose exec --user www-data app \
php occ config:system:set trusted_domains 1 --value=nextcloud.example.comAus dem echten Betrieb: Genau das ist uns passiert. Nach zwei Netz-Umzügen standen in den
trusted_domainsunserer Produktivinstanz noch zwei alte Adressen, die aktuelle fehlte. Nextcloud antwortete darauf mit HTTP 400 — der Server war nie kaputt, die Konfiguration war seit den Umzügen nur nicht mehr wahr. Aufgefallen ist es erst, als ein Monitoring-Check die Anwendung über die aktuelle Adresse ansprach; über den gewohnten Weg funktionierte alles.trusted_domainsgehört auf die Checkliste jeder Netzwerkänderung, genau wie DNS und SSH-Konfiguration.
trusted_proxies sagt Nextcloud, von welchen Adressen weitergeleitete Anfragen
kommen dürfen. Nur für diese Quellen wertet Nextcloud den
X-Forwarded-For-Header aus. Ohne diese Einschränkung könnte jeder Client seine
eigene IP-Adresse fälschen — was Brute-Force-Schutz und Protokollierung wertlos
macht.
Prüfen: Melde dich mit falschem Passwort an und sieh im Nextcloud-Log nach,
welche IP protokolliert wurde. Steht dort die Adresse deines Reverse Proxy statt
die des Clients, ist trusted_proxies nicht korrekt gesetzt.
Funktioniert alles? Die Abnahme #
Geh diese Liste einmal komplett durch, bevor du echte Daten hochlädst:
docker compose pszeigtapp,cron,db,redisalsrunninghttps://nextcloud.example.comliefert die Anmeldeseite über HTTPS- Anmeldung mit dem Admin-Konto funktioniert
- Eine große Datei hochladen und wieder herunterladen, Prüfsumme vergleichen
- Einen Freigabelink erzeugen und in einem privaten Fenster öffnen
- Administrationseinstellungen → Übersicht zeigt keine roten Warnungen
- Hintergrundaufgaben stehen auf „Cron", letzte Ausführung ist frisch
- Kein Hinweis zu Memory-Cache oder File Locking mehr
- Desktop-Client oder Handy-App verbindet sich und synchronisiert
Der Upload-und-Download-Test mit Prüfsumme ist der wichtigste Punkt. Er deckt Proxy-Limits, Timeouts und Rechteprobleme in einem Durchgang auf:
dd if=/dev/urandom of=test.bin bs=1M count=500
sha256sum test.binNach dem Hoch- und Herunterladen dieselbe Prüfsumme erneut bilden. Weichen sie
ab oder bricht der Upload bei einer festen Größe ab, liegt es fast immer am
Reverse Proxy — client_max_body_size bei nginx, Timeouts bei allen.
Unsere Messwerte #
Gemessen am 27. August 2026 in einer eigenen Testinstanz neben der Produktivinstanz — eigene Volumes, eigenes Netz, eigener Port, nach den Messungen restlos zurückgebaut.
Teststand: Nextcloud 34.0.3 (nextcloud:34-apache), PostgreSQL 16, Redis 8,
Docker 29.7.2 mit Compose 5.5.0 auf Debian 13.6. Host: 6-Kern-x86-Desktop-CPU
(35 W TDP), 16 GB RAM, NVMe-SSD.
Bis zur laufenden Instanz #
| Schritt | Dauer |
|---|---|
docker compose up -d | 0,81 s |
| bis Nextcloud über HTTP antwortet | 7,95 s |
occ maintenance:install | 11,76 s |
Zusammen keine 20 Sekunden — vorausgesetzt, die Images liegen bereits lokal.
Grundverbrauch, frisch installiert #
| Container | RAM im Leerlauf |
|---|---|
| Nextcloud (Apache + PHP) | 115,7 MiB |
| PostgreSQL | 40,7 MiB |
| Redis | 10,2 MiB |
| Cron | 1,7 MiB |
| Summe | 168,3 MiB |
CPU im Leerlauf praktisch null. Auf der Platte: 935 MB Installation, davon 573 MB allein mitgelieferte Apps, plus 15 MB Datenbank. Die Container-Images belegen zusätzlich rund 3 GB. Der Grundzoll vor der ersten eigenen Datei liegt also bei etwa 4 GB.
Transferverhalten #
Loopback-Messung, also ohne Netzwerkbegrenzung. Die Werte beschreiben Server- und Speicherleistung, nicht das, was ein Client im LAN erreicht:
| Test | Dauer | Durchsatz |
|---|---|---|
| Upload 100 MB | 1,15 s | 86,8 MiB/s |
| Upload 1 GB | 7,28 s | 140,7 MiB/s |
| Download 100 MB | 0,53 s | 189,6 MiB/s |
| Download 1 GB | 2,70 s | 378,9 MiB/s |
| Upload 1000 × 10 KB | 308,07 s | 3,24 Dateien/s |
Das ist der wichtigste Befund der Messreihe: 12 MB in tausend kleinen Dateien brauchten 42-mal länger als 1 GB am Stück. Jede Datei ist eine eigene HTTP-Anfrage mit eigener Anmeldung, eigener Sperre und eigener Datenbanktransaktion.
Damit die Zahl nicht falsch gelesen wird: Wir haben sequentiell gemessen, mit je einer neuen Verbindung pro Datei. Ein echter Desktop-Client öffnet mehrere Verbindungen parallel und ist deutlich schneller. Die Größenordnung des Unterschieds zwischen großen und kleinen Dateien bleibt aber.
Unter Last #
Während des 1-GB-Uploads lag der Nextcloud-Container bei rund 47 % einer CPU, der RAM stieg von 115,7 auf 284 MiB. Datenbank und Redis blieben bei nahezu 0 %. Beim reinen Dateitransfer ist die Datenbank also nicht der Engpass.
Speicher mit Daten #
Nach 2,1 GB großen Dateien plus 1000 kleinen: 3,1 GB im Volume, Datenbank von 15 auf 17 MB gewachsen bei 1067 Dateien. Die Datenbank wächst sehr langsam mit der Dateizahl — zum Vergleich unsere Produktivinstanz: 7592 Dateien, 46 MB Datenbank.
Alle Werte sind Einzelläufe ohne Mittelung über mehrere Durchgänge. Die vollständige Messreihe mit Methodik steht im LAB-Eintrag.
Security #
Die offizielle Härtungsdoku nennt als Kernpunkte:
- HTTPS ist nicht optional. Ohne verschlüsselte Verbindung ist die Instanz offen für Man-in-the-Middle-Angriffe. Alle HTTP-Anfragen per 301 auf HTTPS umleiten.
- HSTS setzen, empfohlen mit
max-age=15552000; includeSubDomains. - Datenverzeichnis außerhalb des Web-Roots — beim offiziellen Image bereits so gelöst.
trusted_domainsundtrusted_proxieskorrekt setzen.- Brute-Force-Schutz. Nextcloud bringt eigenen mit; zusätzlich empfiehlt die
Doku fail2ban gegen
nextcloud.log. - Administrative Aktionen einschränken über
allowed_admin_ranges. - Eigene Subdomain, damit die Same-Origin-Policy Nextcloud von anderen Diensten trennt.
- Debug-Modus aus im Produktivbetrieb.
Dazu zwei Punkte aus eigener Erfahrung:
Zwei-Faktor-Authentifizierung für alle Konten mit Administrationsrechten. Nextcloud liefert dafür Apps mit (TOTP, WebAuthn) — aktiviere sie, bevor die Instanz aus dem Internet erreichbar ist, nicht danach.
Muss sie überhaupt aus dem Internet erreichbar sein? Wenn du und deine Geräte ohnehin per VPN ins Heimnetz kommen, ist eine Nextcloud, die nur im LAN lauscht, deutlich schwerer anzugreifen. Der Preis: Freigabelinks an Dritte funktionieren dann nicht. Das ist eine echte Abwägung — für viele Homelabs ist der VPN-Weg die bessere Antwort. Wie das geht, steht im Guide zu WireGuard auf der OPNsense.
Und ein Punkt, der leicht untergeht: Container-Updates sind Sicherheitsarbeit. Automatische Systemupdates decken Images aus Drittquellen nicht ab — PostgreSQL, Redis und der Reverse Proxy bekommen ihre Sicherheitsupdates nur, wenn du sie aktualisierst.
Backup — und die 583 Bytes, die alles entscheiden #
Die offizielle Doku benennt fünf Bestandteile: config, data, custom_apps,
themes und die Datenbank. Dazu kommt, was sie nicht erwähnt, weil sie den
Container-Fall nicht voraussetzt: compose.yaml und db.env.
Und ein sechster Punkt, der in fast keiner Anleitung steht — und ohne den das Backup wertlos ist: die Datenbankrollen.
Der Nextcloud-Installer legt eine eigene Datenbankrolle an und trägt sie in die
config.php ein. Rollen sind in PostgreSQL aber Cluster-Objekte und stecken
nicht im Dump einer einzelnen Datenbank. Ein Backup nach dem Verfahren, das
überall steht, enthält sie also nicht — und der Restore scheitert. Bei uns mit
HTTP 500 und password authentication failed.
Es geht um 583 Bytes und 0,11 Sekunden:
cd /opt/nextcloud
# 1. Wartungsmodus an — keine Schreibzugriffe mehr
sudo docker compose exec --user www-data app php occ maintenance:mode --on
# 2. Datenbank sichern
sudo docker compose exec -T db \
pg_dump -U nextcloud nextcloud > nextcloud-db-$(date +%F).sql
# 3. Die Cluster-Rollen sichern — DAS ist der Schritt, der meistens fehlt
sudo docker compose exec -T db \
pg_dumpall -U nextcloud --roles-only > nextcloud-rollen-$(date +%F).sql
# 4. Volume mit config, data, custom_apps und themes sichern
sudo docker run --rm \
-v nextcloud_nextcloud:/quelle:ro \
-v /pfad/zum/backup:/ziel \
alpine tar czf /ziel/nextcloud-files-$(date +%F).tar.gz -C /quelle .
# 5. Wartungsmodus aus
sudo docker compose exec --user www-data app php occ maintenance:mode --offDer Volume-Name in Schritt 4 ist <projektname>_nextcloud — bei einem
Verzeichnis /opt/nextcloud also nextcloud_nextcloud. Nachsehen mit
docker volume ls.
Was das bei uns gekostet hat (3,1 GB Quelldaten, 1067 Dateien):
| Schritt | Dauer | Größe |
|---|---|---|
| Datenbank-Dump | 0,28 s | 406 KB |
| Rollen-Dump | 0,11 s | 583 B |
Dateien als tar.gz | 83,87 s | 2,17 GB |
| Backup gesamt | 84,78 s | 2,2 GB |
Die Zeit steckt praktisch vollständig im Packen der Dateien — und exakt so lange
ist die Instanz im Wartungsmodus, also für Nutzer nicht erreichbar. Bei
Datenmengen im dreistelligen Gigabyte-Bereich wird das zum Thema; dann lohnt es,
über Dateisystem-Snapshots statt tar nachzudenken.
Prüfen:
ls -lh nextcloud-db-*.sql nextcloud-rollen-*.sql
head -5 nextcloud-db-*.sql
grep -c "CREATE ROLE" nextcloud-rollen-*.sqlDer Datenbank-Dump muss mit PostgreSQL-Kopfzeilen beginnen und darf nicht 0 Byte
groß sein. Im Rollen-Dump muss mindestens eine CREATE ROLE-Zeile stehen — sonst
hast du genau das Backup, das sich nicht zurückspielen lässt.
Wie viel Platz du für mehrere Versionen brauchst, rechnet der Backup-Speicher-Rechner. Wohin die Kopien gehören, steht in der Backup-Strategie zuhause.
Restore — und warum die Reihenfolge Teil des Verfahrens ist #
Ein Backup, das nie zurückgespielt wurde, ist eine Vermutung. Wir haben es getestet: Restore aus der Testinstanz in eine dritte, komplett leere Instanz. Er hat im dritten Anlauf funktioniert. Die beiden Fehlschläge sind der wertvollste Teil dieses Guides.
Fehlschlag 1 — HTTP 500, password authentication failed. Die fehlenden
Cluster-Rollen, siehe oben. Ohne sie existiert der Datenbankbenutzer aus der
config.php im Ziel schlicht nicht.
Fehlschlag 2 — permission denied for table oc_appconfig. Die Rollen waren
zwar da, aber nach dem Schema eingespielt worden. Der Dump enthält zwar
ALTER TABLE … OWNER TO-Anweisungen, die liefen aber ins Leere, weil die Rolle
zu diesem Zeitpunkt noch nicht existierte. Alle 131 Tabellen gehörten danach dem
falschen Benutzer.
Daraus folgt die Reihenfolge:
cd /opt/nextcloud
# 1. Stack stoppen, alte Volumes entfernen
sudo docker compose down -v
# 2. Nur Datenbank und Redis starten
sudo docker compose up -d db redis
# 3. ZUERST die Rollen — vor allem anderen
cat nextcloud-rollen-JJJJ-MM-TT.sql | \
sudo docker compose exec -T db psql -U nextcloud postgres
# 4. Dann erst den Datenbank-Dump
cat nextcloud-db-JJJJ-MM-TT.sql | \
sudo docker compose exec -T db psql -U nextcloud nextcloud
# 5. Dateien zurückspielen
sudo docker volume create nextcloud_nextcloud
sudo docker run --rm \
-v nextcloud_nextcloud:/ziel \
-v /pfad/zum/backup:/quelle:ro \
alpine tar xzf /quelle/nextcloud-files-JJJJ-MM-TT.tar.gz -C /ziel
# 6. Stack starten
sudo docker compose up -dFehlschlag 3 — die wiederhergestellte Instanz startet im Wartungsmodus.
status.php meldete maintenance: true, WebDAV antwortete mit HTTP 503. Das ist
kein Fehler, sondern Logik: Das Backup wurde korrekterweise im Wartungsmodus
erstellt, also stand maintenance: true in der gesicherten config.php und kam
mit zurück. Deshalb gehört dieser Schritt fest in die Checkliste:
sudo docker compose exec --user www-data app php occ maintenance:mode --offPrüfen — und zwar mehr als „die Seite lädt":
sudo docker compose exec --user www-data app php occ status
sudo docker compose exec --user www-data app php occ files:scan --allWir haben zusätzlich vor dem Backup die MD5-Prüfsummen zweier Dateien notiert und sie nach dem Restore erneut gebildet — einmal direkt und einmal nach einem Download über WebDAV. Erst wenn die übereinstimmen, ist der Restore bestätigt.
Was der Restore gekostet hat:
| Schritt | Dauer |
|---|---|
| Datenbank einspielen | 2,01 s |
| Dateien zurückspielen | 31,37 s |
| Gesamt | 33,38 s |
Wiederhergestellt: 1067 Dateien in 7 Ordnern, Prüfsummen identisch.
Zwei Lehren, die über Nextcloud hinausgehen: Rollen vor Schema — die
Reihenfolge ist Teil des Verfahrens, nicht Geschmackssache. Und: Fehlerausgaben
beim Einspielen nicht nach /dev/null schicken. Genau die Zeilen, die man
wegwirft, sind die Diagnose. Der erste Fehlschlag war minutenlang nur ein
nichtssagender HTTP 500, bis ein direkter PHP-Aufruf die eigentliche Meldung
zeigte.
Updates #
Zwei Regeln, die Nextcloud von den meisten Containern unterscheiden:
- Hauptversionen dürfen nicht übersprungen werden. Erst auf die letzte Patch-Version der aktuellen Hauptversion, dann auf die nächste.
- Nach einem Hauptversions-Upgrade müssen die Hintergrund-Migrationen
durchlaufen — die Doku empfiehlt,
cron.phpdafür zwei bis drei Mal laufen zu lassen, bevor die nächste Hauptversion drankommt.
cd /opt/nextcloud
# Vorher: Backup. Immer — inklusive Rollen-Dump.
# 1. Tag in der compose.yaml hochziehen, z. B. 34-apache → 35-apache
sudo nano compose.yaml
# 2. Neues Image holen und Container ersetzen
sudo docker compose pull
sudo docker compose up -d
# 3. Upgrade-Schritte ausführen
sudo docker compose exec --user www-data app php occ upgrade
sudo docker compose exec --user www-data app php occ maintenance:mode --offPrüfen:
sudo docker compose exec --user www-data app php occ statusErwartet: die neue Version, maintenance: false, keine Fehlermeldung. Danach die
Admin-Übersicht auf neue Warnungen ansehen — nach Upgrades fehlen gelegentlich
Datenbank-Indizes, die occ db:add-missing-indices nachträgt.
Weil cron und app dasselbe Image benutzen, wird der Cron-Container
automatisch mit aktualisiert. Genau deshalb müssen beide denselben Tag tragen.
Was hier nicht getestet ist #
LabKompass trennt zwischen dem, was wir nachgeprüft haben, und dem, was aus Dokumentation stammt.
Selbst gemessen und getestet: Installationsdauer, RAM- und CPU-Verbrauch im
Leerlauf und unter Last, Speicherbedarf, Upload- und Download-Durchsatz,
Verhalten bei vielen kleinen Dateien, die Systemwarnungen nach der Installation
und ihre Behebung, Backup-Umfang und -Dauer, der vollständige Restore inklusive
der drei Fehlschläge, der trusted_domains-Befund und die Cron-Kollision.
Aus offizieller Dokumentation: Versionen und Support-Zeiträume, Systemanforderungen, die Härtungsempfehlungen, die Upgrade-Regeln und die Reverse-Proxy-Parameter.
Redaktionelle Einschätzung: die Abwägung, für wen sich Nextcloud lohnt, und die Empfehlung, Nextcloud eher hinter VPN als offen ins Internet zu stellen.
Nicht getestet — und deshalb hier nicht behauptet: Desktop-Sync-Client und Mobil-App, kollaboratives Bearbeiten, Mehrbenutzerbetrieb, HTTPS hinter einem Reverse Proxy und ein echtes Hauptversions-Update. Zum Messzeitpunkt war 34.0.3 die aktuelle Version, ein Sprung auf 35 stand also nicht an. Die Transferwerte sind Loopback-Messungen ohne Netzwerk dazwischen, und jeder Wert ist ein Einzellauf ohne Mittelung.
Fazit #
Nextcloud lohnt sich 2026 weiterhin — aber nicht als „einfache eigene Cloud", sondern als Anwendung mit Betriebsaufwand. Die Installation kostet Sekunden, der verantwortungsvolle Betrieb kostet dauerhaft Aufmerksamkeit.
Das ist keine Floskel, sondern das Ergebnis unserer eigenen Messreihe: Unsere Produktivinstanz lief monatelang unauffällig — und hatte trotzdem stillstehende Hintergrundjobs, eine seit zwei Netz-Umzügen tote Adresskonfiguration und Datei-Locking über die Datenbank. Nichts davon meldet sich von selbst.
Wer den Aufwand einplant, bekommt viel Funktion für wenig Hardware: 168 MiB RAM im Leerlauf, Dateien, Kalender, Kontakte und Freigaben in einem System. Wer ihn nicht einplant, betreibt eine Instanz mit stehenden Jobs und einem Backup, das sich nicht zurückspielen lässt.
Der nächste sinnvolle Schritt ist deshalb nicht die nächste App, sondern der Restore: Spiel dein Backup einmal in eine leere Instanz zurück, bevor du dich im Ernstfall darauf verlassen musst. Wir haben drei Anläufe gebraucht — und keiner der drei Fehler wäre ohne diesen Test aufgefallen.
Häufige Fragen
- Lohnt sich Nextcloud noch, wenn ich nur Dateien synchronisieren will?
- Meist nicht. Für reine Dateisynchronisation zwischen ein paar Geräten ist ein schlanker Sync-Dienst ohne Datenbank, Webserver und Benutzerverwaltung der ehrlichere Weg. Interessant wird Nextcloud, sobald Kalender, Kontakte, Freigabelinks an Dritte, mehrere Nutzerkonten oder eine Weboberfläche dazukommen.
- Wie viel RAM braucht Nextcloud wirklich?
- In unserer frisch installierten Testinstanz waren es 168 MiB für alle vier Container zusammen: Nextcloud 116, PostgreSQL 41, Redis 10 und der Cron-Container 2 MiB. Während eines 1-GB-Uploads stieg der Nextcloud-Container auf 284 MiB und lastete etwa eine halbe CPU aus. Die offizielle Empfehlung von 512 MB bezieht sich auf einen einzelnen PHP-Prozess, nicht auf den Server — mehrere gleichzeitige Anfragen brauchen entsprechend mehr.
- Warum ist Nextcloud bei vielen kleinen Dateien so langsam?
- Weil jede Datei eine eigene HTTP-Anfrage mit eigener Anmeldung, eigener Sperre und eigener Datenbanktransaktion ist. Bei uns brauchten 1000 Dateien à 10 KB — zusammen 12 MB — mit 308 Sekunden 42-mal länger als 1 GB am Stück. Ein echter Sync-Client parallelisiert und ist schneller, aber die Größenordnung des Unterschieds bleibt. Wer Quellcode-Bäume oder Mail-Archive ablegen will, sollte das vorher wissen.
- Reicht ein pg_dump als Backup der Nextcloud-Datenbank?
- Nein, und das ist die teuerste Falle. Der Nextcloud-Installer legt eine eigene Datenbankrolle an und trägt sie in die config.php ein. Rollen sind in PostgreSQL Cluster-Objekte und stecken nicht im Dump einer einzelnen Datenbank. Unser Restore scheiterte genau daran mit HTTP 500. Es fehlten 583 Bytes, die ein pg_dumpall --roles-only in 0,11 Sekunden mitsichert.
- Brauche ich zwingend Redis?
- Nextcloud läuft auch ohne, benutzt dann aber die Datenbank für File Locking. In unserer Testinstanz war Redis nach dem Setzen einer einzigen Umgebungsvariable aktiv — das offizielle Image konfiguriert memcache.distributed und memcache.locking selbst. Der Unterschied war in den Systemprüfungen direkt sichtbar. Bei diesem Aufwand gibt es keinen guten Grund, darauf zu verzichten.
- Kann ich beim Update eine Hauptversion überspringen?
- Nein. Nextcloud erlaubt kein Überspringen von Hauptversionen. Du aktualisierst erst auf die letzte Patch-Version deiner aktuellen Hauptversion und dann auf die nächste — und lässt danach den Cron zwei bis drei Mal laufen, damit die Hintergrund-Migrationen fertig werden, bevor die nächste Hauptversion drankommt.
- Warum antwortet Nextcloud mit HTTP 400 statt mit einer Fehlerseite?
- Weil der angefragte Hostname nicht in trusted_domains steht. Nextcloud lehnt unbekannte Host-Header hart ab, um Host-Header-Poisoning zu verhindern. Das passiert typischerweise nach einem IP-Wechsel, einem Domainwechsel oder wenn ein Reverse Proxy einen anderen Namen weitergibt als erwartet.
Aus dem echten Betrieb
Diese Seite ist aus realer Arbeit im Homelab entstanden:
Weiterlesen
Security
Backup-Strategie für zuhause: Die 3-2-1-Regel praktisch umgesetzt
RAID ist kein Backup: Wie du mit der 3-2-1-Regel, Versionierung und einer Offsite-Kopie deine Daten wirklich absicherst — mit konkretem Setup fürs Homelab.
Hardware
Alten PC als Homeserver nutzen: Was er taugt und was er wirklich kostet
Der ausgemusterte Office-PC oder All-in-One als erster Homeserver: wann sich das lohnt, wann der Stromverbrauch die Ersparnis auffrisst und wie du sinnvoll startest.
Selfhosting
Unraid vs. Proxmox vs. TrueNAS: Welches System für deinen Homeserver?
Die drei großen Homeserver-Systeme im ehrlichen Vergleich: Stärken, Schwächen, Storage-Philosophie und eine klare Empfehlung je nach Einsatzzweck.