Nextcloud-Migration: Vom Shared Hosting zu Docker Compose

Wer seine Nextcloud von einem klassischen Hosting-Paket auf einen eigenen Server mit Docker umzieht, merkt schnell: Der Teufel steckt im Detail. In dieser Anleitung zeige ich dir, wie du den Umzug angeehen kannst, PHP-Limits sprengst und dein System mit Caddy absicherst.
📋 Voraussetzungen
- Ein Linux-Server mit installiertem Docker und Docker Compose.
- Ein Backup deiner alten Nextcloud (Dateien + Datenbank-Dump).
- Eine Domain (z.B.
share.deine-domain.de), die auf deinen Server zeigt.
Schritt 1: Die Verzeichnisstruktur
Wir trennen Code, Daten und Konfiguration sauber, um Updates und Backups zu vereinfachen.
mkdir -p /software/nextcloud/{nextcloud_install,config,data,db,backups}
- nextcloud_install: Hier liegt der Programmcode.
- config: Hier liegt die lebenswichtige
config.php. - data: Deine Dateien und der
tmp-Ordner für Uploads.
Schritt 2: Docker Compose Setup
Erstelle eine docker-compose.yml im Verzeichnis /software/nextcloud. Das Herzstück ist die Trennung von App, Datenbank und Redis (Caching).
services:
db:
image: mariadb:10.11
container_name: nextcloud-db
volumes:
- ./db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=dein_passwort
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud_user
- MYSQL_PASSWORD=dein_db_passwort
app:
image: nextcloud:latest
container_name: nextcloud-app
depends_on:
- db
- redis
volumes:
- ./nextcloud_install:/var/www/html
- ./config:/var/www/html/config
- ./data:/var/www/html/data
environment:
- MYSQL_PASSWORD=dein_db_passwort
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud_user
- MYSQL_HOST=db
- REDIS_HOST=redis
- PHP_MEMORY_LIMIT=1G
- PHP_UPLOAD_LIMIT=16G
redis:
image: redis:alpine
container_name: nextcloud-redis
cron:
image: nextcloud:latest
container_name: nextcloud-cron
volumes:
- ./nextcloud_install:/var/www/html
- ./config:/var/www/html/config
- ./data:/var/www/html/data
entrypoint: /cron.sh
depends_on:
- db
- redisSchritt 3: Der Umzug der Daten (Die "Pfad-Falle")
Nachdem du deinen Datenbank-Dump importiert und deine Dateien in den data-Ordner kopiert hast, kommt der wichtigste Teil: Pfade anpassen
Shared Hoster nutzen oft Pfade wie /var/www/vhosts/hosting123/....
Docker nutzt intern immer /var/www/html.
- Öffne deine
config/config.php. - Ändere
datadirectoryauf:'datadirectory' => '/var/www/html/data',. - Entferne alte
apps_paths, falls vorhanden.
Schritt 4: Große Uploads ermöglichen (bis 20GB)
Standardmäßig blockieren viele Instanzen bei 512MB.
Wir brauchen drei Anpassungen:
4.1. Caddyfile (Proxy)
Dein Reverse Proxy muss den "Body" zulassen:
share.deine-domain.de {
# 1. Komprimierung für schnellere Ladezeiten
encode zstd gzip
# 2. Logging für Fehleranalyse
log {
output file /var/log/caddy/share.deine-domain.log
}
# 3. Sicherheits-Header (Wichtig für das Nextcloud-Security-Rating)
header {
# HSTS aktivieren (vorgeschriebene 6 Monate)
Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
# Clickjacking-Schutz
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy no-referrer-when-downgrade
# Server-Tag verstecken (Sicherheit geht vor)
-Server
}
# 4. Die "Schleuse" für große Uploads (z.B. Home Assistant Backups)
request_body {
max_size 20GB
}
# 5. Der Reverse Proxy zum Docker-Container
reverse_proxy localhost:11000 {
# Verhindert Pufferung, damit große Uploads nicht im RAM hängen
flush_interval -1
# Wichtige Header für die Erkennung der IP und Protokolle
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
# Timeouts für extrem langsame/große Uploads
transport http {
read_timeout 3600s
write_timeout 3600s
}
}
}
4.2. Die .user.ini
Erstelle im Ordner nextcloud_install eine Datei namens .user.ini, da Docker-Umgebungen diese für PHP-Limits nutzen:
upload_max_filesize=16G
post_max_size=16G
memory_limit=1G
max_execution_time=3600
4.3. Chunk-Size erhöhen
Tippe diesen Befehl im Terminal, um Nextcloud zu sagen, dass sie Dateien in größeren Stücken hochladen soll:
docker exec --user www-data nextcloud-app php occ config:app:set files max_chunk_size --value 104857600Schritt 5: Automatisierung mit systemd-Timern
Wenn dein System kein crontab besitzt oder du eine robustere Lösung suchst, sind systemd-Timer die erste Wahl. Wir benötigen zwei Dinge pro Aufgabe: Einen .service (Was soll getan werden?) und einen .timer (Wann soll es getan werden?).
5.1 Der tägliche Backup-Job
Dieser Job sichert nachts um 03:00 Uhr die Datenbank und die Konfiguration.
1. Service-Datei erstellen: sudo nano /etc/systemd/system/nextcloud-backup.service
[Unit]
Description=Nextcloud Backup Service
After=docker.service
[Service]
Type=oneshot
ExecStart=/bin/bash /software/nextcloud/backup.sh
User=root
[Install]
WantedBy=multi-user.target
2. Timer-Datei erstellen: sudo nano /etc/systemd/system/nextcloud-backup.timer
[Unit]
Description=Trigger Nextcloud Backup daily at 3am
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
5.2 Der Nextcloud Hintergrund-Job (Cron)
Nextcloud muss alle 5 Minuten Aufgaben wie das Versenden von Benachrichtigungen oder das Aufräumen von Dateisperren erledigen. Ohne diesen Job wird dein System mit der Zeit langsam.
1. Service-Datei erstellen: sudo nano /etc/systemd/system/nextcloud-cron.service
[Unit]
Description=Trigger Nextcloud Cron.php inside Docker
[Service]
Type=oneshot
# Hier nutzen wir docker exec, um den Befehl im Container als www-data auszuführen
ExecStart=/usr/bin/docker exec --user 33 nextcloud-koralle-app php -f /var/www/html/cron.php
2. Timer-Datei erstellen: sudo nano /etc/systemd/system/nextcloud-cron.timer
[Unit]
Description=Run Nextcloud Cron every 5 minutes
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
[Install]
WantedBy=timers.target
5.3 Aktivierung und Überwachung
Nachdem die Dateien angelegt wurden, müssen sie dem System bekannt gemacht werden.
Einmalig laden und aktivieren:
# Systemd neu laden
sudo systemctl daemon-reload
# Timer aktivieren und sofort starten
sudo systemctl enable --now nextcloud-backup.timer
sudo systemctl enable --now nextcloud-cron.timer
Status und Fehlersuche: Einer der größten Vorteile von systemd ist das Journal. Du kannst genau sehen, ob und wann ein Job gelaufen ist:
- Timer-Liste anzeigen:
systemctl list-timers - Logs des Cron-Jobs einsehen:
journalctl -u nextcloud-cron.service -f - Logs des Backups prüfen:
journalctl -u nextcloud-backup.service
Wait, then there is more...
Schritt 6: Daten-Migration & Datenbank-Import
Bevor du docker compose up startest, müssen deine alten Daten an den richtigen Ort. Hier ist der präzise Ablauf:
6.1. Den Datenbank-Dump vorbereiten und importieren
Du hast von deinem alten Hoster eine .sql oder .sql.gz Datei. Der Trick bei Docker: Du musst die Daten in den laufenden Container schieben oder sie beim Starten automatisch einlesen lassen.
Variante A: Der manuelle Import (wenn der Container schon läuft)
- Kopiere den Dump auf deinen Server.
Schiebe den Dump per „Pipe“ direkt in den Container:
cat dein_backup.sql | docker exec -i nextcloud-db mariadb -u nextcloud_user -pdein_db_passwort nextcloud
Hinweis: Falls die Datei komprimiert ist, nutze zcat dein_backup.sql.gz | ....
Variante B: Der automatische Import (beim ersten Start) MariaDB-Container haben ein spezielles Verzeichnis: /docker-entrypoint-initdb.d/. Alles, was dort liegt, wird beim ersten Erstellen der Datenbank ausgeführt.
Ergänze in der docker-compose.yml beim db-Service:YAML
volumes:
- ./db:/var/lib/mysql
- ./dein_backup.sql:/docker-entrypoint-initdb.d/init.sql
6.2. Die Dateirechte (Permissions) – Der Stolperstein #1
Auf dem Shared Hosting gehörten deine Dateien einem User wie web123. Im Docker-Container ist es immer der User www-data mit der ID 33. Wenn die Rechte nicht stimmen, bekommst du einen "Internal Server Error".
Bevor du startest, korrigiere die Besitzer auf dem Host-System:
# Gehe in dein Nextcloud-Hauptverzeichnis
cd /software/nextcloud
# Setze den Besitzer für alle Ordner auf die ID 33 (www-data in Docker)
sudo chown -R 33:33 nextcloud_install config data apps
6.3. Der erste Login & App-Updates
Sobald die Container laufen (docker compose up -d), wird Nextcloud bemerken, dass die Datenbank von einem anderen Server kommt.
Apps aktualisieren: Da die alten App-Dateien evtl. nicht zur neuen Nextcloud-Version im Docker-Image passen:Bash
docker exec --user 33 nextcloud-app php occ upgradeIndizes reparieren: Nach einem Import fehlen oft Optimierungen:Bash
docker exec --user 33 nextcloud-app php occ db:add-missing-indices
Wartungsmodus prüfen: Falls die Seite nicht lädt, schalte den Wartungsmodus aus:Bash
docker exec --user 33 nextcloud-app php occ maintenance:mode --off
Was tun bei Fehlern?
Wenn nach dem Import nur eine weiße Seite erscheint, ist der erste Blick immer in die Logs:
- Docker-Ebene:
docker compose logs -f app - Nextcloud-Ebene:
tail -f /software/nextcloud/data/nextcloud.log
Oft sind es verwaiste Einträge in der oc_storages Tabelle der Datenbank, die noch auf den alten Pfad des Hosters zeigen. Mit occ files:scan --all zwingst du Nextcloud, die Dateistruktur neu einzulesen.
Fazit
Der Umzug zu Docker ist kein reiner Dateitransfer, sondern ein Konfigurations-Projekt. Der Lohn ist ein System, das exakt so skaliert, wie du es brauchst – egal ob für kleine Dokumente oder massive Home-Assistant-Backups.