Wer Nextcloud heute aufsetzt bekommt nicht nur einen simplen Dateispeicher. Mit Features wie integriertem Office, Kalender- und Kontaktsynchronisation (CalDAV/CardDAV), Videochats und KI-Funktionen ist es das Schweizer Taschenmesser für die eigene IT-Infrastruktur. Nun zeige ich euch, wie ihr dies in wenigen Minuten mit Docker realisiert. Traefik dient uns hier als Reverse Proxy und stellt später den Dienst verschlüsselt per TLS bereit.
| Datum | Änderungen |
|---|---|
| 29.03.2020 | Erstellung dieser Anleitung |
| 26.04.2020 | Optimierungen (letztes Kapitel) hinzugefügt. |
| 04.09.2020 | DockerCompose angepasst, damit alles wieder funktioniert. |
| 05.09.2020 | Integration mit Collabora Office hinzugefügt. |
| 19.08.2021 | Fehler mit Datenbank behoben. Danke an Peter. |
| 02.01.2022 | Formatierungsfehler der Docker Compose Datei behoben. |
| 05.01.2022 | Anleitung für Nextcloud 23.0 angepasst. |
| 03.04.2022 | Kleinigkeiten angepasst. |
| 26.07.2022 | getestet mit Nextcloud 24.0.3 |
| 08.09.2022 | Labels für Traefik + CrowdSec angepasst; TRUSTED_PROXIES, OVERWRITEPROTOCOL, OVERWRITECLIURL,OVERWRITEHOST werden nun per Docker Compose festgelegt und nicht später von Hand. |
| 21.09.2022 | Kapitel 6.5 Cron hinzugefügt |
| 18.01.2023 | Links zu CrowdSec hinzugefügt, MariaDB Parameter –log-bin=ROW entfernt, MariaDB Parameter MARIADB_AUTO_UPGRADE=1 hinzugefügt. |
| 29.05.2023 | Update auf neue Traefik Anleitung, Kapitel 2.1 (Traefik IP ermitteln) entfernt |
| 12.07.2023 | MariaDB auf Version 10.6 festgesetzt |
| 10.01.2024 | MariaDB auf Version 10.11 festgesetzt. Danke an @goover |
| 10.01.2024 | Kapitel 6.5 OnlyOffice integrieren hinzugefügt |
| 04.02.2024 | Kapitel 2 um Dockerfile für bz2 erweitert |
| 10.03.2024 | Kapitel 7 – Nextcloud updaten hinzugefügt |
| 12.03.2024 | Kapitel 6.2, 6.3 hinzugefügt. Trusted Proxy in Docker Compose Datei angepasst |
| 06.05.2024 | Kapitel 2.2 angepasst um “latest”, Kapitel 2.1 “DAV” Traefik Labels entfernt. Danke an @burgsth |
| 20.05.2024 | Kapitel 6.4 hinzugefügt |
| 19.09.2024 | Kapitel 6.6 hinzugefügt |
| 15.11.2024 | Link Traefik v3 hinzugefügt, Kapitel 6.5 und 6.6 hinzufügt |
| 15.09.2025 | Docker Image statt Dockerfile als Standard, Kapitel 11 hinzugefügt. Danke an @buggy5151 |
| 01.01.2026 | Kapitel 6.7, 6.8 hinzugefügt |
| 01.04.2026 | Kapitel 2.3 (AppSec) hinzugefügt |
| 16.09.2026 | Komplett überarbeitet: Passwörter in .env; Nextcloud auf Hauptversion 34 und MariaDB 11.4 festgelegt; TRUSTED_PROXIES korrigiert; .well-known-Weiterleitung, Upload-Limits per Umgebungsvariablen und Cron-Container ergänzt; Einstellungen per occ statt config.php; neue Kapitel Update-Regeln, AppAPI mit HaRP, Umstellung bestehender Installationen und Fehlerbehebung. Danke an @bernds, @kru, @snxrcs und alle Kommentatoren. |
Ihr habt Nextcloud bereits nach einer älteren Version dieser Anleitung installiert? Dann springt direkt zu Kapitel 14 – Bestehende Installation umstellen.
0. Grundvoraussetzung
- Docker & Docker Compose v2 (Debian / Ubuntu)
- Traefik ab v3.6 mit CrowdSec installieren und konfigurieren
Als Grundlage meiner Anleitung dient die offizielle Nextcloud Anleitung für Docker.
1. Ordner anlegen
Zuerst legen wir uns passende Ordner-Strukturen an.
mkdir -p /opt/containers/nextcloud/{database,app,daten}
2. Docker Grundlagen
2.1 Proxy Netzwerk IP Adressbereich ermitteln
Damit Nextcloud später weiß, welchen Proxys es vertrauen darf, ermitteln wir nun den korrekten IP Adressbereich unseres Netzwerks “proxy”. Dazu gebt ihr folgendes ein:
docker network inspect proxy -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}'Code-Sprache: JavaScript (javascript)
Bei mir sieht die Ausgabe so aus:
docker network inspect proxy -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
172.31.128.0/18Code-Sprache: JavaScript (javascript)
Merkt euch diesen IP Adressbereich für die spätere Konfiguration.
2.2 env Dateien anlegen
Damit wir keine Kennwörter in unserer Docker Compose Datei haben, lagern wir diese nun in eine .env Datei aus. Dazu legt ihr folgende Datei an:
nano /opt/containers/nextcloud/.env
Inhalt:
# Eure Nextcloud-Domain (ohne https://)
NEXTCLOUD_DOMAIN=nextcloud.euredomain.de
# Subnetz des Docker-Netzwerks "proxy" (siehe Kapitel 2.1)
PROXY_SUBNET=172.31.128.0/18
# Passwörter (nur A-Z, a-z, 0-9)
MYSQL_ROOT_PASSWORD=HIER_PASSWORT_1
MYSQL_PASSWORD=HIER_PASSWORT_2
REDIS_PASSWORD=HIER_PASSWORT_3Code-Sprache: PHP (php)
Eure Nextcloud Domain passt ihr nach euren Wünschen an. Die Kennwörter kennt ihr selbst festlegen oder euch mit folgendem Befehl sichere Kennwörter generieren lassen:
for i in 1 2 3; do dd if=/dev/urandom bs=1024 count=1 2>/dev/null | tr -dc 'A-Za-z0-9' | cut -c1-32; doneCode-Sprache: JavaScript (javascript)
Anschließend ändern wir noch die Zugriffsrechte auf die Datei:
chmod 600 /opt/containers/nextcloud/.env
2.3 Docker Compose anlegen
Nun legen wir die eigentliche Docker Datei an. Hierfür habe ich mir die offizielle Nextcloud Compose genommen und diese abgeändert für Traefik. Bei der öffiziellen Seite könnt ihr auch immer die aktuelle Version ermitteln. Dies solltet ihr tun, da wir hier das Image auf Version 34 festsetzen.
nano /opt/containers/nextcloud/docker-compose.yml
Inhalt
services:
nextcloud-db:
image: mariadb:11.4
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_INITDB_SKIP_TZINFO: "1"
MARIADB_AUTO_UPGRADE: "1"
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- ./database:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- default
nextcloud-redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
networks:
- default
nextcloud-app:
image: nextcloud:34
container_name: nextcloud-app
restart: unless-stopped
depends_on:
nextcloud-db:
condition: service_healthy
nextcloud-redis:
condition: service_started
environment:
# Datenbank und Redis
MYSQL_HOST: nextcloud-db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
REDIS_HOST: nextcloud-redis
REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
# Reverse Proxy (Traefik)
TRUSTED_PROXIES: ${PROXY_SUBNET}
APACHE_DISABLE_REWRITE_IP: "1"
OVERWRITEPROTOCOL: https
OVERWRITEHOST: ${NEXTCLOUD_DOMAIN}
OVERWRITECLIURL: https://${NEXTCLOUD_DOMAIN}
# PHP und Apache
PHP_MEMORY_LIMIT: 1024M
PHP_UPLOAD_LIMIT: 16G
PHP_OPCACHE_MEMORY_CONSUMPTION: "256"
APACHE_BODY_LIMIT: "0"
volumes:
- ./app:/var/www/html
- ./daten:/var/www/html/data
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.nextcloud.rule=Host(`${NEXTCLOUD_DOMAIN}`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls.certresolver=http_resolver"
- "traefik.http.routers.nextcloud.middlewares=nextcloud-dav,default@file"
- "traefik.http.middlewares.nextcloud-dav.redirectregex.regex=^https://(.*)/.well-known/(?:card|cal)dav"
- "traefik.http.middlewares.nextcloud-dav.redirectregex.replacement=https://$${1}/remote.php/dav"
- "traefik.http.middlewares.nextcloud-dav.redirectregex.permanent=true"
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
networks:
- proxy
- default
nextcloud-cron:
image: nextcloud:34
container_name: nextcloud-cron
restart: unless-stopped
entrypoint: /cron.sh
depends_on:
- nextcloud-app
environment:
PHP_MEMORY_LIMIT: 1024M
volumes:
- ./app:/var/www/html
- ./daten:/var/www/html/data
networks:
- default
networks:
proxy:
external: trueCode-Sprache: PHP (php)
Hier müsst ihr nichts mehr anpassen, da ihr bereits alle Anpassungen in der .env Datei gemacht hat.
Was hat sich zu früher geändert?
- Wir verwenden jetzt eine feste Version von Nextcloud statt “latest”, da so bei einem Update sichergestellt ist, dass ihr innerhalb der Hauptversion bleibt. Ein Update von 30 auf 34 ist nämlich so nicht möglich und dies wird durch diesen Schritt sichergestllt.
- Wir haben überall Healthchecks, damit Nextcloud erst startet, wenn die Datenbank verfügbar ist
- Das PHP Uploadlimit wurde auf 16 GB erhöht und bei Apache komplett aufgehoben.
- Ein eigener Container für die Nextcloud Hintergrundjobs
2.4 Dockerfile erstellen (optional)
Wenn ihr das Nextcloud Image erweitern wollt, dann müsst ihr diese Schritte noch tun. Grundsätzlich ist das aber nicht notwendig.
Zuerst passt ihr folgendes an:
vorher:
nextcloud-app:
#build: .
image: nextcloud:34
nachher:
nextcloud-app:
build: .
#image: nextcloud:latestCode-Sprache: CSS (css)
Nun erstellen wir uns ein Dockerfile. Dies hat den Grund, dass wir so die Erweiterung bz2 zusätzlich installieren können. Dazu gebt ihr folgendes ein:
nano /opt/containers/nextcloud/Dockerfile
Inhalt:
FROM nextcloud:34
RUN apt-get update && apt-get install -y libbz2-dev && rm -rf /var/lib/apt/lists/*
RUN docker-php-ext-install bz2Code-Sprache: JavaScript (javascript)
Nun lassen wir uns das Image bauen. Dazu gebt ihr folgendes ein:
cd /opt/containers/nextcloud
docker compose build --no-cache
3. AppSec Whitelist (Optional)
Falls ihr CrowdSec AppSec aktiviert habt, müsst ihr noch eine Whitelist erstellen, damit sich Nextcloud später überhaupt korrekt starten lässt. Es kann sein, dass zudem noch weitere Freigaben für den korrekten Betrieb benötigt werden. Zuerst legen wir uns eine Whitelist an:
cat << 'EOF' > /opt/containers/traefik-crowdsec-stack/data/crowdsec/config/appsec-rules/nextcloud-whitelist.yaml
name: custom/nextcloud-whitelist
seclang_rules:
# Whitelist für Nextcloud Firstrunwizard (DELETE)
- "SecRule REQUEST_URI \"@beginsWith /apps/firstrunwizard/\" \"id:13001,phase:1,pass,nolog,noauditlog,ctl:ruleRemoveById=911100,msg:'Whitelist Nextcloud firstrunwizard Methods'\""
- "SecRule REQUEST_URI \"@beginsWith /apps/firstrunwizard/\" \"id:13002,phase:2,pass,nolog,noauditlog,ctl:ruleRemoveById=949110,ctl:ruleRemoveById=980170,msg:'Whitelist Nextcloud firstrunwizard Anomaly'\""
# Whitelist für Nextcloud Text App (PUT) - Session-ID dynamisch abgefangen
- "SecRule REQUEST_URI \"@beginsWith /apps/text/session/\" \"id:13003,phase:1,pass,nolog,noauditlog,ctl:ruleRemoveById=911100,msg:'Whitelist Nextcloud text session Methods'\""
- "SecRule REQUEST_URI \"@beginsWith /apps/text/session/\" \"id:13004,phase:2,pass,nolog,noauditlog,ctl:ruleRemoveById=949110,ctl:ruleRemoveById=980170,msg:'Whitelist Nextcloud text session Anomaly'\""
# Whitelist für Nextcloud Heartbeat / User Status (PUT)
- "SecRule REQUEST_URI \"@beginsWith /ocs/v2.php/apps/user_status/api/v1/heartbeat\" \"id:13005,phase:1,pass,nolog,noauditlog,ctl:ruleRemoveById=911100,msg:'Whitelist Nextcloud heartbeat Methods'\""
- "SecRule REQUEST_URI \"@beginsWith /ocs/v2.php/apps/user_status/api/v1/heartbeat\" \"id:13006,phase:2,pass,nolog,noauditlog,ctl:ruleRemoveById=949110,ctl:ruleRemoveById=980170,msg:'Whitelist Nextcloud heartbeat Anomaly'\""
EOFCode-Sprache: PHP (php)
Nun müssen wir noch eine Anpasung vornehmen, damit die Whitelist auch genutzt wird:
nano /opt/containers/traefik-crowdsec-stack/data/crowdsec/config/appsec-configs/mrks-config.yaml
Dort fügt ihr einfach “- custom/nextcloud-whitelist” hinzu:
name: custom/mrks-config
default_remediation: ban
inband_rules:
- custom/nextcloud-whitelist
- crowdsecurity/base-config
- crowdsecurity/vpatch-*
- crowdsecurity/generic-*
- crowdsecurity/crs
- crowdsecurity/experimental-*
outofband_rules:
- crowdsecurity/appsec-generic-test
Nun starten wir Traefik neu, damit die Änderungen übernommen werden:
cd /opt/containers/traefik-crowdsec-stack
docker compose up -d --force-recreate
4. Nextcloud Server starten
Den Server startet ihr wie gewohnt mit folgendem Befehl:
docker compose -f /opt/containers/nextcloud/docker-compose.yml up -d
5. Nextcloud einrichten
Nextcloud sollte die Datenbank Verbindung nun automatisch erkennen und euch direkt zur Erstellung des Admin Kontos führen:

Jetzt solltet ihr folgendes sehen. Gebt hier nun folgendes ein:
Administrator-Konto anlegen
- Benutzername: Wie euer Nextcloud Admin heißen soll
- Passwort: Wählt ein Passwort
Wenn ihr anschließend auf “Installieren” klickt, dauert es ca. 30 Sekunden, bis die Webseite neu lädt und ihr folgendes angezeigt bekommt. Hier könnt ihr auf “Überspringen” klicken oder alle “Empfohlen Apps” direkt mit installieren lassen.

Anschließend werdet ihr von diesem Startbildschirm begrüßt.

6. occ komfortabel nutzen (optional)
occ ist ein Kommandozeilentool von Nextcloud. Es ermöglicht euch verschiedene Parameter anzupassen. Da Nextcloud in einem Docker Container läuft, ist der Befehl immer etwas länger, zum Beispiel so:
docker exec -u www-data nextcloud-app php occ status
Damit der Befehl “kürzer” ist, legen wir uns ein kleines Skript an (Danke @bernds) für den Tipp:
nano /usr/local/bin/occ
Inhalt:
#!/bin/bash
# occ-Befehle im Nextcloud-Container als www-data ausführen
if [ -t 0 ]; then
TTY="-it"
else
TTY="-i"
fi
exec docker exec $TTY -u www-data nextcloud-app php occ "$@"Code-Sprache: PHP (php)
Anschließend machen wir die Datei noch ausführbar:
chmod +x /usr/local/bin/occ
Jetzt reicht es, wenn ihr nur noch occ eingebt um Befehle auszuführen:
occ status
7. Optimierungen
Wenn ihr oben rechts auf eueren “Buchstaben”. Dann wählt ihr “Einstellungen” -> “Übersicht” aus. Nun solltet ihr feststellen, dass Nextcloud noch “Optimierungsbedarf” sieht. Dies wollen wir nun tun.

Wir werden hier alle occ Befehle entsprechend mittels des Skripts in Kapitel 6 ausführen. Wenn ihr dies nicht wollt, so müsst ihr folgendes vor den Befehl schreiben:
docker exec -u www-data nextcloud-app php occ <Befehl>
statt
occ <Befehl>Code-Sprache: HTML, XML (xml)
7.1 Alle Warnungen in der Konsole anzeigen lassen
Damit ihr einen schnelleren Überblick über die Warnungen bekommt, könnt ihr euch diesen auch direkt in der Konsole anzeigen lassen:
occ setupcheck
7.2 Standardtelefonregion festlegen
Damit die Telefonnummern korrekt erkannt werden, gebt ihr für Deutschland folgendes ein:
occ config:system:set default_phone_region --value="DE"Code-Sprache: JavaScript (javascript)
Für Österreich “AT” und für die Schweiz “CH”.
7.3 Der Server hat keine konfigurierte Startzeit für das Wartungsfenster
Nextcloud führt aufwendige Hintergrundaufgaben bevorzugt in einem vierstündigen Wartungsfenster aus. Ihr legt nur fest, wann es beginnt. Wichtig ist, dass der Wert in UTC angegeben wird. “1” bedeutet also, dass es 2:00 Uhr (Winterzeit) oder 3:00 Uhr (Sommerzeit) sind.
occ config:system:set maintenance_window_start --type=integer --value=1Code-Sprache: JavaScript (javascript)
7.4 ihr werdet regelmäßig auf eurem Server durch Crowdsec gebannt
In diesem Fall solltet ihr diese Anleitung ausführen und eine Nextcloud Whitelist hinzufügen.
7.5 fehlende optionale Indizes erkannt
Ich bekomme noch folgende Fehlermeldung, dass “Einige fehlende optionale Indizes wurden erkannt. Gelegentlich werden neue Indizes hinzugefügt (von Nextcloud oder installierten Anwendungen), um die Datenbankleistung zu verbessern” fehlen. Dies könnt ihr so beheben:
occ db:add-missing-indicesCode-Sprache: CSS (css)
7.6 One or more mimetype migrations are available
Dies behebt ihr mit folgendem Befehl:
occ maintenance:repair --include-expensiveCode-Sprache: CSS (css)
7.7 Falsches Zeilenformat in Ihrer Datenbank gefunden
Die genaue Meldung
Falsches Zeilenformat in Ihrer Datenbank gefunden. ROW_FORMAT=Dynamic bietet die beste Datenbankleistung für Nextcloud. Bitte aktualisieren Sie das Zeilenformat in der folgenden Liste..Code-Sprache: PHP (php)
Um das Problem zu lösen erstellen wir uns ein Upgrade Skript:
nano /opt/containers/nextcloud/upgrade-db.sh
Inhalt:
#!/bin/bash
set -euo pipefail
DB_CONTAINER="nextcloud-db"
DB_NAME="nextcloud"
# ALTER-Befehle für alle Tabellen erzeugen, die noch nicht DYNAMIC sind
SQL=$(docker exec -i "$DB_CONTAINER" sh -c 'mariadb -u root -p"$MYSQL_ROOT_PASSWORD" -sN' <<EOF
SELECT CONCAT('ALTER TABLE \`', table_name, '\` ROW_FORMAT=DYNAMIC;')
FROM information_schema.tables
WHERE table_schema = '${DB_NAME}' AND engine = 'InnoDB' AND row_format <> 'Dynamic';
EOF
)
if [ -z "$SQL" ]; then
echo "Alle Tabellen haben bereits ROW_FORMAT=DYNAMIC."
exit 0
fi
echo "Folgende Befehle werden ausgeführt:"
echo "$SQL"
# Befehle ausführen
echo "$SQL" | docker exec -i "$DB_CONTAINER" sh -c "mariadb -u root -p\"\$MYSQL_ROOT_PASSWORD\" $DB_NAME"
echo "Fertig."Code-Sprache: PHP (php)
Das Skript nutzt das Root-Passwort, das bereits als Umgebungsvariable im Datenbank-Container hinterlegt ist. Ihr müsst also kein Passwort eintragen und es taucht auch nicht in der Prozessliste des Hosts auf. Wenn ihr den Nextcloud oder DB Containername geändert habt, so müsst ihr dies noch anpassen.
Anschließend machen wir das Skript noch ausführbar:
chmod +x /opt/containers/nextcloud/upgrade-db.sh
Jetzt fahren wir die Nextcloud Container herunter und starten nur die Datenbank.
cd /opt/containers/nextcloud
docker compose down
docker compose up -d nextcloud-db
Wichtig: Macht vor dem Ausführen des Skripts ein Backup der Datenbank
Nun starten wir unser Skript:
/opt/containers/nextcloud/upgrade-db.sh
Nachdem das Skript fertig ist, können wir Nextcloud starten:
cd /opt/containers/nextcloud
docker compose up -d
7.8 Cron Job benötigt mehr RAM
Falls eine Meldung folgender Art bei euch steht:
Cron job used more than 300 MB of ram after executing job
dann könnt ihr einfach den RAM erhöhen. Dazu öffnet ihr die Docker Compose Datei:
nano /opt/containers/nextcloud/docker-compose.yml
Wir haben das PHP_MEMORY_LIMIT bereits bei der aktuellen Konfiguration erhöht: PHP_MEMORY_LIMIT: 1024M
Sollte dies bei euch noch nicht der Fall sein, so fügt / ändert diesen Wert noch in eurer Docker Compose. Ihr müsst den Wert bei den nextcloud Container sowie nextcloud-cron Container ändern.
Anschließend muss der gesamte Container neu gestartet werden.
cd /opt/containers/nextcloud
docker compose up -d --force-recreate
8. Große Dateien hochladen
8.1 Parameter in der Docker Compose anpassen
Wir haben die Docker Compose bereits so gändert, dass Dateien bis 16 GB hochgeladen werden können. Dies könnt ihr folgendermaßen überprüfen:
docker exec nextcloud-app php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"Code-Sprache: JavaScript (javascript)
Die Ausgabe sollte folgendes sein:
docker exec nextcloud-app php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"
max_memory_limit => -1 => -1
memory_limit => 1024M => 1024M
post_max_size => 16G => 16G
upload_max_filesize => 16G => 16GCode-Sprache: PHP (php)
Sollte dies nicht der Fall sein, so kopiert / passt folgende Werte in der Docker Compose an:
PHP_MEMORY_LIMIT: 1024M
PHP_UPLOAD_LIMIT: 16G
PHP_OPCACHE_MEMORY_CONSUMPTION: "256"
APACHE_BODY_LIMIT: "0"Code-Sprache: JavaScript (javascript)
8.2 Traefik Timeout verhindern
Traefik bricht Anfragen ab, wenn die Übertragung zu lange dauert (Danke an @kru für den Hinweis). Standardmäßig ist der Wert auf 60 Sekunden eingestellt. Dies kann bei langsamen / großen Uploads zu Fehlern führen wie:
BadRequest
Erwartete Dateigröße von 10485760 Bytes, aber 8306688 Bytes gelesen …
Um diesen Wert zu ändern, öffnet folgende Datei:
nano /opt/containers/traefik-crowdsec-stack/data/traefik/traefik.yml
Fügt dort folgendes an der korrekten Stelle hinzu:
transport:
respondingTimeouts:
readTimeout: 30m
so sieht der gesamte Block bei mir aus:
entryPoints:
ping:
address: ':88'
web:
address: ':80'
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ':443'
http3: {}
http:
middlewares:
- crowdsec@file
- default@file
transport:
respondingTimeouts:
readTimeout: 30m
Code-Sprache: JavaScript (javascript)
Anschließend startet ihr Traefik neu:
docker compose -f /opt/containers/traefik-crowdsec-stack/docker-compose.yml restart traefik
9. Nextcloud mittels CrowdSec absichern
Nun könnt ihr Nextcloud innerhalb weniger Minuten noch zusätzlich mittels CrowdSec absichern. Eine Anleitung dazu findet ihr hier.
10. Collabora Office integrieren
Ich habe hier eine Anleitung geschrieben, wie ihr in wenigen Minuten Collabora Office mittels Docker installiert und in Nextcloud integrieren könnt. Collabora Office ermöglicht euch ein “komplettes online Office” innerhalb von Nextcloud.

11. OnlyOffice integireren
Neben Collabora Office könnt ihr auch innerhalb weniger Minuten OnlyOffice mittels Docker installieren und integrieren. Es hat einen ähnlichen Funktionsumfang wie Collabora Office.

12. AppAPI einrichten (optional)
AppAPI ermöglicht externe Apps (ExApps), die in eigenen Docker-Containern laufen. Dazu gehören z. B. viele KI-Funktionen. Solche Apps braucht nicht jeder. Wenn ihr keine ExApps nutzen wollt, überspringt dieses Kapitel.
Für die Verbindung zwischen Nextcloud und den ExApps nutzt Nextcloud seit Version 32 HaRP. Der frühere Docker Socket Proxy (DSP) ist veraltet und soll mit Nextcloud 35 entfernt werden.
12.1 AppAPI installieren
Zuerst erzeugt ihr euch ein sicheres Kennwort:
dd if=/dev/urandom bs=1024 count=1 2>/dev/null | tr -dc 'A-Za-z0-9' | cut -c1-32Code-Sprache: JavaScript (javascript)
Fügt dann folgende Zeile in eure .env Datei ein zusammen mit eurem Kennwort:
nano /opt/containers/nextcloud/.env
Inhalt:
HARP_SHARED_KEY=HIER_PASSWORT_einfügen
Nun müssen wir den Container noch der Docker Compose hinzufügen:
nano /opt/containers/nextcloud/docker-compose.yml
Fügt dort folgendes hinzu:
nextcloud-harp:
image: ghcr.io/nextcloud/nextcloud-appapi-harp:release
container_name: nextcloud-harp
hostname: nextcloud-harp
restart: unless-stopped
environment:
HP_SHARED_KEY: ${HARP_SHARED_KEY}
NC_INSTANCE_URL: https://${NEXTCLOUD_DOMAIN}
HP_TRUSTED_PROXY_IPS: ${PROXY_SUBNET}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./harp-certs:/certs
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.nextcloud-exapps.rule=Host(`${NEXTCLOUD_DOMAIN}`) && PathPrefix(`/exapps/`)"
- "traefik.http.routers.nextcloud-exapps.entrypoints=websecure"
- "traefik.http.routers.nextcloud-exapps.tls.certresolver=http_resolver"
- "traefik.http.routers.nextcloud-exapps.middlewares=default@file"
- "traefik.http.services.nextcloud-exapps.loadbalancer.server.port=8780"
networks:
- proxy
- defaultCode-Sprache: PHP (php)
Anschließend starte ihr Nextcloud neu:
cd /opt/containers/nextcloud
docker compose up -d
12.2 Daemon registrieren
Dazu geht ihr in die Administrationseinstellungen:

Wählt nun “AppAPI” aus:

Klickt nun auf “Daemon registrieren”:

Gebt nun folgendes ein:

Parameter zum Kopieren
| Feld | Wert |
|---|---|
| Daemon Konfigurationsvorlage | HaRP Proxy (Docker) |
| HaRP-Host | nextcloud-harp:8780 |
| Geteilter HaRP-Schlüssel | euer HARP_SHARED_KEY aus der .env |
| Nextcloud-URL | https://nextcloud.euredomain.de |
| Als Standard-Daemon festlegen | aktiviert |
| HaRP aktivieren | aktiviert |
| FRP-Serveradresse | nextcloud-harp:8782 |
| Docker-Socket-Proxy-Port | 24000 (Standardwert, nicht ändern) |
| Docker-Netzwerk | nextcloud_default |
| Compute-Gerät | CPU (bzw. eure GPU, falls vorhanden) |
Das Netzwerk könnt ihr mit folgendem Befehl ermitteln:
docker network ls | grep nextcloud
So sieht meine Ausgabe aus:
docker network ls | grep nextcloud
dddaabdc69eb nextcloud_default bridge local
Anschließend könnt ihr die Verbindung überprüfen. Jetzt solltet ihr folgende Meldung erhalten:

Wenn das funktioniert hat, klickt auf die “3 Punkte” und wählt “Bereitstellung testen” aus:

Wenn der Test erfolgreich war, solltet ihr folgendes sehen. Bei mir hat dies mehrere Minuten gedauert.

13. Nextcloud updaten
13.1 Die wichtigste Regel
Nextcloud kann keine Hauptversionen überspringen. Von 33 geht es nur auf 34, von 34 nur auf 35 und so weiter. Wer z. B. von 32 direkt auf 34 springt, landet in einer Neustart-Schleife.
Welche Version bei euch läuft, seht ihr mit:
occ status
Das Update über die Weboberfläche („Updater“) ist bei Docker nicht vorgesehen. Updates erfolgen immer über ein neues Image.
13.2 Kleine Updates (innerhalb einer Hauptversion)
Solange in der docker-compose.yml nextcloud:34 steht, bekommt ihr mit folgenden Befehlen die neueste 34er-Version:
cd /opt/containers/nextcloud
docker compose pull
docker compose up -d
Beim Start erkennt der Container die neue Version und führt das Upgrade automatisch aus. Den Fortschritt seht ihr mit:
docker compose logs -f nextcloud-app
13.3 Update auf die nächste Hauptversion
Erstellt ein Backup. Prüft, ob alle eure Apps die neue Version schon unterstützen. Das seht ihr unter „Verwaltungseinstellungen“ → „Übersicht“. Ändert die Versionsnummer in der docker-compose.yml bei beiden Containern um genau eins:
nano /opt/containers/nextcloud/docker-compose.yml
Anpassungen:
vorher:
nextcloud-app:
image: nextcloud:34
nextcloud-cron:
image: nextcloud:34
nachher:
nextcloud-app:
image: nextcloud:35
nextcloud-cron:
image: nextcloud:35Code-Sprache: CSS (css)
Image laden und Container neu starten:
cd /opt/containers/nextcloud
docker compose pull
docker compose up -d
docker compose logs -f nextcloud-app
Nach dem Upgrade die üblichen Nacharbeiten erledigen:
occ app:update --all
occ db:add-missing-indices
occ maintenance:repair --include-expensive
occ setupcheckCode-Sprache: CSS (css)
13.4 Update mit eigenem Dockerfile
Wenn ihr das Image in Kapitel 2.4 erweitert habt, passt ihr die Versionsnummer in der ersten Zeile des Dockerfile an (z. B. FROM nextcloud:35) und baut das Image neu:
cd /opt/containers/nextcloud
docker compose build --pull
docker compose up -d
Für kleine Updates innerhalb einer Hauptversion reichen die letzten beiden Befehle.
13.5 MariaDB aktualisieren
Die Datenbank aktualisiert ihr unabhängig von Nextcloud. Erstellt vorher ein Backup, ändert die Version (z. B. mariadb:11.4 → neuere LTS-Version, sofern Nextcloud diese unterstützt) und startet neu. Dank MARIADB_AUTO_UPGRADE passt MariaDB die Datenbankdateien beim Start automatisch an:
cd /opt/containers/nextcloud
docker compose pull nextcloud-db
docker compose up -d
14. Bestehende Installation umstellen
Ihr habt Nextcloud nach einer älteren Version dieser Anleitung installiert? So stellt ihr auf den neuen Aufbau um, ohne Daten zu verlieren. Die Ordnerstruktur (database, app, daten) bleibt gleich.
14.1 Backup erstellen
Erstellt ein vollständiges Backup, indem ihr die Container beendet und das gesamte Verzeichnis kopiert bzw. die Datenbank und Konfiguration.
14.2 Installierte Version ermitteln
Gebt folgenden Befehl ein
docker exec -u www-data nextcloud-app php occ status
Merkt euch die Hauptversion. Bei mir zum Beispiel folgendes:
docker exec -u www-data nextcloud-app php occ status
- installed: true
- version: 34.0.4.1
- versionstring: 34.0.4Code-Sprache: CSS (css)
Die Hauptversion ist: 34.0.4
14.3 .env anlegen
Legt die .env wie in Kapitel 2.2 an, erzeugt aber keine neuen Passwörter. Übernehmt stattdessen die Passwörter aus eurer alten docker-compose.yml. Die Datenbank-Passwörter werden nur beim allerersten Start gesetzt. Mit neuen Passwörtern könnte sich Nextcloud nicht mehr mit der Datenbank verbinden.
Enthält eines eurer alten Passwörter ein $, setzt ihr den Wert in der .env in einfache Anführungszeichen, z. B. MYSQL_PASSWORD='abc$def'.
14.4 Neue docker-compose.yml anlegen
Übernehmt die Datei aus Kapitel 2.3 mit zwei Anpassungen:
- Nextcloud-Version: Tragt bei
nextcloud-appundnextcloud-croneure aktuelle Hauptversion aus Schritt 14.2 ein (z. B.nextcloud:34). Niemals eine niedrigere Version als die installierte, denn ein Downgrade ist nicht möglich. Auf neuere Versionen aktualisiert ihr anschließend wie in Kapitel 13. - MariaDB-Version: Behaltet zunächst eure bisherige Version (z. B.
mariadb:10.11). Die Datenbank aktualisiert ihr später separat nach Kapitel 13.5.
Falls ihr AppAPI mit nextcloud-appapi-dsp nutzt, lasst diesen Container vorerst in der Datei und stellt danach wie in Kapitel 12 um.
14.5 Host-Crontab entfernen
Der alte Cron-Eintrag auf dem Host wird durch den nextcloud-cron-Container ersetzt:
crontab -e
Löscht dort die Zeile:
*/5 * * * * docker exec -u www-data nextcloud-app php cron.php
14.6 Stack neu starten
Gebt folgendes ein:
cd /opt/containers/nextcloud
docker compose up -d --remove-orphans
docker compose logs -f nextcloud-app
14.7 Nacharbeiten
Richtet den occ-Befehl aus Kapitel 6 ein und führt dann aus:
occ background:cron
occ setupcheckCode-Sprache: CSS (css)
Die Einträge php_value upload_max_filesize und php_value post_max_size in der .user.ini braucht ihr nicht mehr, die Werte kommen jetzt aus der docker-compose.yml. Die Einträge default_phone_region und maintenance_window_start in eurer config.php bleiben einfach bestehen.

Ich habe die letzten Tage sehr viel Zeit damit verbracht Nextcloud bei mir zum laufen zu bekommen. Ich bin dabei aus meiner Sicht so ziemlich alle Anleitungen und Videos im Internet durchgegangen. Keine einzige funktioniert und die neuesten Kommentare bestätigen das auch. Aber ich kann Stand Heute sagen, dass diese Anleitung hier 100% funktioniert sofern man sich akkurat an die von Daniel beschriebenen Schritte hält.
Vielen Dank für diese TOP Anleitung. Ich hoffe, dass meine Nextcloud nun möglichst lange hält und nicht irgendein update von mariadb, traefik, docker oder nextcloud das ganze konstrukt zerschießt 🙂
Oder wenn doch, dass Christian die passende Lösung parat hat.
Gruß
Hi,
seit einigen Tagen bekomme ich im Dashboard => Einstellung etc.. folgende Meldung:#
“Einige Aufträge wurden seit Vor 7 Tagen nicht mehr ausgeführt. Bitte erwäge die Umstellung auf System-Cron”
Weiss jemand warum dies erscheint, und somit ist auch Nextcloud relativ langsam.
Guten Morgen Christian,
danke für deine schnelle Antwort, ich habe das gerade getestet und es hat mit traefik funktioniert, danke vielmals.
Als ich das zum laufen bekommen habe, habe ich mein Bitwarden auch angepasst (die middleware konnte ich in der compose die ich habe einfach herauslöschen und es hat geklappt 🙂 ) und es hat gestartet jetzt bekomme ich aber einen 525 SSL Handshake Fehler in traefik bekomme ich den Fehler
ACCESS CONTROL ALLOW CREDENTIALS false
Hast du eine Idee ? … Entschuldige meine Unkenntnis xD
Gruß
Marc
Guten Abend,
also die Anleitungen sind top, vielen vielen Dank dafür. Ich habe mich die letzten Tage mit den ganzen docker und docker-compose Sachen beschäftigt. Dank deiner Anleitung habe ich traefik gut ans laufen bekommen 🙂
Nachdem ich jetzt erfolgreich mein cloudflare DNS und bitwarden einegbunden habe , wollte ich mich an die Nextcloud wagen.
Wie ich gemerkt habe hast du einen Linux Server, daher habe ich das MariaDB Paket abgeändert und ich bekam ein ‘running’ von docker zurück.
Leider gibt mir traefik ein ‘middleware “secHeaders@file” does not exist´’ zurück, die Seite kann ich aufrufen, bekomme aber einen 404 Error zurück. Da ich absolut keine Ahnung habe was dem fehlt wollte ich hier mal Nachfragen. Google gab mir nicht so richtig hinweise darauf.
Ach mein System: ich benutze einen RaspberryPI 4 mit 4GB.
Ich hoffe mir kann hier geholfen werden.
Hallo Christian,
vielen Dank für die super Anleitung.
Ich habe mehrfach versucht ein Backup von meinem “normalen” nextcloud einzuspielen, ohne Erfolg. Jetzt habe ich mit “BernieO / calcardbackup” alles wichtige importiert.
Zu meiner Frage; für einen vollständigen Server benötige ich noch einen samba server. Leider klappt das nicht :(. Ich habe verschiedene container versucht, mit verschiedensten Anpassungen, doch nichts hat geholfen.
Kannst du mir oder jemand anderes vielleicht, helfen.
Hallo,
vielen Dank für die Anleitungen, (abgesehen von Portainer) war es ein schneller und problemloser Durchlauf. Wurde das Ganze auf echter Hardware oder auf einem V-Server installiert ?
Ich habe ein merkwürdiges Performance-Problem: Nach der reinen Grundinstallation (Docker+DockerCompose+Treafik+Nextcloud+mariaDB+Redis) inkl. den hier vorgeschlagenen Optimierungen dauert es rund 45-60 Sekunde im Webinterface von Nextcloud auch nur einen Ordner zu öffnen. Laut HTOP ist die RAM-Nutzung dabei bei ~500MB/16GB und die CPU(s)-Auslastung geht nicht über 30%.
Vorher lief auf dem vServer eine direkte Installation von Nextcloud+mariaDB+Redis (allerdings noch Nextcloud v19.irgendwas), da konnte ich so ein Verhalten nicht beobachten.
Könnte es sein, dass die Kombination Docker und NC auf einem V-Server einfach ungünstig ist ?
“Problem” gelöst! Sorry für soviel Unsinn. Ich habe mich zwischen “alter” und “neuer” Anleitung verirrt.
Jetzt läuft alles bestens !
Vielen Dank für die Anleitung. Ich habe Traefik auch ans Laufen bekommen und kann via Internet darauf zu greifen. Beim Versuch, den Nextcloud-Container zu installieren, also oben bei Schritt 3.) bekomme ich am Ende der Download- und Installationsnachrichten nur folgende Fehlermeldung:
ERROR: Cannot locate specified Dockerfile: Dockerfile
Was kann ich tun?
Vielen Dank für die Anleitung. Ich habe Traefik auch ans Laufen bekommen und kann via Internet darauf zu greifen. Beim Versuch, den Nextcloud-Container zu installieren, also oben bei Schritt 3.) bekomme ich nur folgende Fehlermeldung:
ERROR: Cannot locate specified Dockerfile: Dockerfile
Was kann ich tun?
Heyho Christian,
estmal coole Website und super tutorials.
Wie viele vor mir habe ich denoch ein Problem, dass ich mir nicht erklären kann.
Ich habe nach deiner Anleitung Traefik installiert und danach direkt den nextcloud container… Dann viel mir auf, dass die middleware secHeader@file nicht existiert. Also habe ich dein turorial befolgt, wie man die tls sicherheit erhöhen kann und somit auch dieser Fehler behoben werden sollte.
Ich bin den “code” jz an 3 verschiedenen Tagen 5 mal durchgegangen, um festzustellen, dass ich KEINE Schreibfehler habe und alles richtig befolgt habe. Nur jz bekomme ich wie ein Nutzer vor mir einen 404 Error auf allen Seiten (bzw. Sie sind nicht erreichbar). Da die middleware secHeader@file aber eh nur für ein verbesserte TLS Sicherheit zuständig war( so wie ich das verstanden habe). Habe ich den label eintrag in der traefik compose.yml , der auf die dynamic.yml verweißt gelöscht. Dann funktionierte traefik wieder. Bei der nextcloud compose.yml habe ich die Zeile, die auf die middleware verweißt gelöscht. und dann funktionierte Nextcloud. Soweit zu dem Werdegang, jz das eigentliche Problem.
Meine traefik/Nextcloud/Portainer Domains sind alle bei Strato gehostet und sind als Subdomains angemeldet. Ich habe einen A-Record hinterlegt, der auch meinen Server verweißt (bei allen drei dieselbe IP).
Im Heimnetzwerk funktioniert alles super, ich gebe traefik.domain.de ein bekomme das traefik dashboard. Bei Nextcloud ebenso. Aber sobald ich versuche meine Cloud von außen zu errreichen bekomme ich nur einen “Server braucht zu lange zum Antworten” ; Oder einfach nur einen Weißen Bildschirm ; oder ein “Server nicht erreichbar, sind Sie sicher aller richtig geschrieben zu haben”…
Hat das mit der fehlenden Middleware zu tun?
Ich weiß echt nichtmehr weiter–
MfG Joni