Zum Hauptinhalt springen
  1. Beiträge/
  2. Kleines Homelab/
  3. k3s-prod: Kubernetes Cluster Konfiguration und Anwendungsbereitstellung/

Nextcloud (neu)

Inhaltsverzeichnis

Nextcloud (nextcloud-new)
#

Neubau von apps/nextcloud nach Kubernetes-Prinzipien. Kernpunkt: statt eines Pods mit fünf Containern, die sich localhost und Volumes teilen, ist jede Komponente ein eigener Workload mit eigenem Lebenszyklus.

Die Ablösung erfolgt in-place: gleicher Namespace nextcloud, gleicher Gleicher Host, gleiche Volumes. Es gibt keinen Parallelbetrieb — der Cutover ist ein Wartungsfenster, kein sanfter Übergang.

Unterschiede zur Altinstallation
#

Aspekt Alt (apps/nextcloud) Neu (apps/nextcloud-new)
Nextcloud-Image ghcr.io/linuxserver/nextcloud (s6, nginx+php-fpm+cron in einem Container, root) library/nextcloud:*-fpm-alpine (ein php-fpm-Prozess, uid 33)
Chart bjw-s app-template offizielles nextcloud/nextcloud
Topologie 1 Pod, 5 Container 8 Workloads, je 1-2 Container
Webserver im Image gebündelt, Configs handgepflegt im PVC nginx-Sidecar, Config aus dem Chart generiert
Cron Daemon im Container CronJob-Ressource, alle 5 Minuten
DB / Cache Sidecar-Container eigene StatefulSets
ClamAV TCP 3310 auf Loopback, ein Pod eigener Pod, TCP 3310 über Service
Konfiguration config.php im PVC, Caching-Keys als ConfigMap Env + Chart-Werte in values.yaml
Credentials Klartext in values*.yaml Secret-Referenzen
Probes keine Liveness/Readiness/Startup pro Workload
Ressourcen Requests und Limits pro Container Requests und Limits pro Container
php-fpm www2.conf als ConfigMap nextcloud.phpConfigs
Startreihenfolge implizit (ein Pod) initContainer wartet auf DB und Cache
.well-known von der generierten nginx-Config abgedeckt

Funktionsabgleich
#

Jede Funktion der Altinstallation und wo sie im neuen Setup landet:

Funktion (alt) Neu Status
Deployment nextcloud, Container nextcloud Deployment nextcloud (fpm + nginx) ersetzt
Container db (mariadb:lts) StatefulSet nextcloud-mariadb (mariadb:11.8) ersetzt
Container redis (redis:8.4) StatefulSet nextcloud-redis (redis:8.4-alpine) ersetzt
Container clamav Deployment nextcloud-clamav ersetzt
Container ssh (PUID 1000) Deployment nextcloud-ssh (PUID 33) ersetzt
Service nextcloud-main :443 Service nextcloud :8080 (HTTP statt HTTPS zum Backend) ersetzt
Service nextcloud-main :3306 Service nextcloud-mariadb:3306 ersetzt
Service nextcloud-ssh-service, LoadBalancer auf Port 4022 (IPv4 und IPv6) gleicher Name, gleiche IP, gleicher Port unverändert
Ingress nextcloud → gleicher Host gleicher Name, gleicher Host unverändert
Certificate → nextcloud-server-tls unverändert unverändert
Middleware nextcloud-stripprefix unverändert unverändert
ConfigMap clamav-config gleicher Name, auf das Nötige eingekürzt ersetzt
Cron (im LSIO-Container) CronJob nextcloud-cron ersetzt
phpMyAdmin (values-phpmyadmin.yaml, auskommentiert) Deployment nextcloud-phpmyadmin unter /php jetzt aktiv
icloudpd privat (values-private.yaml, auskommentiert) Deployment nextcloud-icloudpd-private vorhanden, replicas: 0
icloudpd shared (values-shared.yaml, auskommentiert) Deployment nextcloud-icloudpd-shared vorhanden, replicas: 0
Collabora (in values.yaml auskommentiert) nicht übernommen — im Chart über collabora.enabled nachrüstbar entfällt
PVC nextcloud-clamav-socket entfällt, ClamAV läuft über TCP entfällt
PVC nextcloud-ssh-config ersetzt durch nextcloud-sshd-config Hostkeys werden kopiert

Die beiden icloudpd-Workloads stehen auf replicas: 0, weil sie auch in der Altinstallation nicht aktiv sind (in kustomization.yaml auskommentiert). Aktivierung ist eine Ein-Zeilen-Änderung, siehe Schritt 11.

Komponenten
#

Workload Typ Image Service
nextcloud Deployment library/nextcloud:32.0.9-fpm-alpine + library/nginx:1.29-alpine nextcloud:8080
nextcloud-cron CronJob dito
nextcloud-mariadb StatefulSet library/mariadb:11.8 nextcloud-mariadb:3306
nextcloud-redis StatefulSet library/redis:8.4-alpine nextcloud-redis:6379
nextcloud-clamav Deployment clamav/clamav:1.5.3_base nextcloud-clamav:3310
nextcloud-phpmyadmin Deployment library/phpmyadmin:5.2-apache nextcloud-phpmyadmin:80
nextcloud-ssh Deployment lscr.io/linuxserver/openssh-server nextcloud-ssh-service LB :4022
nextcloud-icloudpd-private Deployment icloudpd/icloudpd:1.32.2 — (replicas 0)
nextcloud-icloudpd-shared Deployment icloudpd/icloudpd:1.32.2 — (replicas 0)

Versionspinning
#

Chart 8.9.1 bringt App-Version 32.0.6 mit, die Altinstallation läuft auf 32.0.9. Ein Downgrade verweigert Nextcloud beim Start, deshalb überschreibt values.yaml den Image-Tag explizit auf 32.0.9-fpm-alpine. Das Label app.kubernetes.io/version zeigt dadurch 32.0.6 an — kosmetisch, aber gut zu wissen, bevor man sich über die Diskrepanz wundert.

Nextcloud überspringt keine Major-Versionen. Der Upgrade-Pfad nach der Migration ist einzeln: 32 → 33 (Chart 9.1.4) → 34 (Chart 9.2.5).

php-fpm-Tuning
#

Verifiziert in docker.io/library/nextcloud:34.0.3-fpm-alpine:

1pm.max_children = 5          (www.conf, Zeile 127)
2request_terminate_timeout    nicht gesetzt
3slowlog                      nicht gesetzt
4apc.shm_size = 32M

Das ist exakt die Konstellation, die am 20.08.2026 die Altinstallation lahmgelegt hat: fünf hängende Requests belegen alle Worker, und weil kein Terminate-Timeout greift, erholt sich die Instanz bis zum manuellen Neustart nicht mehr. Jeder weitere Request läuft in den nginx-Timeout. Ohne Gegenmaßnahme hätte der Cutover den Ausfall mitgenommen.

nextcloud.phpConfigs legt deshalb zz-zyria.conf nach /usr/local/etc/php-fpm.d/. Die Reihenfolge im Image ist docker.conf, www.conf, zz-docker.conf — unsere Datei kommt alphabetisch zuletzt und gewinnt.

Drei Kopplungen, die man nicht einzeln anfassen darf:

  • pm.max_children = 24 setzt das CPU-Limit von 4 voraus. Ohne Limit können 24 Amok-Worker einen ganzen Node belegen.
  • 24 Worker brauchen etwa 3 GiB. Das Memory-Limit musste deshalb von 2Gi auf 8Gi, sonst greift der OOM-Killer, bevor PHP sein eigenes memory_limit zieht.
  • request_terminate_timeout = 900 kappt effektiv den fastcgi_read_timeout 3600s des nginx-Sidecars. Das ist Absicht: ein Worker, der eine Stunde hängt, ist genau das Szenario, das vermieden werden soll. Wer sehr lange Einzelrequests braucht, muss beide Werte gemeinsam anheben.

apc.shm_size geht nicht über phpConfigs: das Chart mountet diese Dateien bei nginx.enabled: true nach /usr/local/etc/php-fpm.d/, wo nur Pool-Direktiven gelten. Auch php_admin_value[] hilft nicht, weil APCu sein Shared-Memory-Segment beim Modul-Init im Master anlegt. Deshalb der Umweg über die ConfigMap nextcloud-php-ini nach /usr/local/etc/php/conf.d/zz-zyria.ini.

Der Slowlog liegt unter /tmp und ist damit beim Pod-Neustart weg. Im offiziellen Image gibt es kein persistentes Log-Verzeichnis, und der Webroot unter /var/www/html wird von der Integritätsprüfung erfasst. Beim Cutover prüfen, ob slowlog = /proc/self/fd/2 funktioniert — dann landet er im Container-Log und damit in fluent-bit.

Trusted Proxies
#

TRUSTED_PROXIES stand auf 10.42.0.0/16, dem k3s-Default. Weicht der Cluster davon ab oder laeuft er Dual-Stack, muss der Wert beide Familien abdecken. Die tatsaechlichen Bereiche liefert:

1kubectl get nodes -o custom-columns=NAME:.metadata.name,CIDRS:.spec.podCIDRs
2kubectl get pod -n kube-system -l app.kubernetes.io/name=traefik \
3  -o custom-columns=NAME:.metadata.name,IPS:.status.podIPs

Fehlt das v6-Präfix, wird jeder über IPv6 eingehende Request nicht als Proxy-Request erkannt: Nextcloud protokolliert dann die Traefik-Pod-IP als remoteAddr, Brute-Force-Schutz und Rate-Limiting treffen den Ingress statt den Angreifer — und ein einzelner auffälliger v6-Client bremst alle anderen mit aus. Im Log der Altinstallation standen 15 solcher Einträge, in denen eine ULA-Adresse aus dem Pod-Netz als vermeintliche Client-Adresse auftauchte — das ist das Erkennungsmerkmal für einen fehlenden v6-Eintrag.

Der Wert ist space-separiert (reverse-proxy.config.php im Image macht explode(' ', …)), nicht komma-separiert.

Vor dem Cutover prüfen: Die Altinstallation vertraut zusätzlich 172.16.0.0/12 sowie zwei öffentlichen v6-Präfixen des Hosters. Ob dort noch etwas davorhängt, das diese Adressen braucht, ist ungeklärt — falls ja, gehören sie in die Liste. Die konkreten Werte stehen in der values.yaml der Altinstallation.

Storage
#

storage.yaml übernimmt die PV/PVC-Definitionen aus apps/nextcloud/storage.yaml wortgleich. Das ist keine Redundanz, sondern Voraussetzung: PVC-Specs sind weitgehend immutable, jede Abweichung führt beim Wechsel der ArgoCD-Application zu einem Sync-Fehler statt zu einer Übernahme.

PVC Größe Inhalt Herkunft
nextcloud-data 350 Gi Nutzdaten übernommen
nextcloud-clamav-db 2 Gi Virensignaturen übernommen
icloudpd-cookie 10 Mi Apple-Session-Cookies übernommen
nextcloud-html 10 Gi Webroot: App-Code, config/, custom_apps/ neu
nextcloud-sshd-config 100 Mi SSH-Hostkeys neu
data-nextcloud-mariadb-0 10 Gi MariaDB (volumeClaimTemplate) neu
data-nextcloud-redis-0 1 Gi Redis-AOF (volumeClaimTemplate) neu
nextcloud-config 5 Gi altes LSIO-/config Rückfallebene
nextcloud-db 10 Gi alter MariaDB-Bestand Rückfallebene
nextcloud-redis 1 Gi alter Redis-Bestand Rückfallebene

ReadWriteOnce + podAffinity: nextcloud-data ist RWO. Alle Pods, die es mounten — die Nextcloud-App, die Cron-CronJob, SSH und icloudpd — sind per podAffinity an den Node der App gebunden.

Datenverzeichnis bleibt /data. Das Chart würde per Default nach /var/www/html/data mounten. Die Datenbank speichert Storage-IDs aber als local::/data/; bei geändertem Pfad legt Nextcloud einen zweiten Storage an und der komplette Dateibestand müsste per occ files:scan neu eingelesen werden. Bei 350 Gi ist das keine Option, deshalb nextcloud.datadir: /data.

Volume-Layout. Das Chart mountet nextcloud-data fest mit subPath: data (hardcodiert, nicht abschaltbar). Im Volume liegen die Nutzdaten aktuell in der Wurzel und müssen einmalig nach data/ verschoben werden — ein Rename im selben Dateisystem, kein Kopieren. Die Mounts für SSH und icloudpd in values-services.yaml führen denselben Offset mit.


Secrets
#

Es gibt in diesem Repo kein sealed-secrets/external-secrets. Die folgenden Secrets werden einmalig von Hand im Namespace nextcloud angelegt und sind nicht in Git.

Vorher: Die Credentials in apps/nextcloud/values.yaml, values-private.yaml und values-shared.yaml liegen im Klartext in der Git-Historie — MariaDB-Root, das Apple-Passwort und das SMTP-Passwort. Sie gelten als kompromittiert. Beim Anlegen der neuen Secrets neue Passwörter vergeben, nicht die alten übernehmen. Das Apple-Passwort und das SMTP-Passwort zusätzlich beim jeweiligen Anbieter rotieren. Das Entfernen der Dateien beseitigt die Historie nicht.

 1# Datenbank. db-hostname-or-ip zeigt auf den Service, nicht auf localhost.
 2kubectl create secret generic nextcloud-db -n nextcloud \
 3  --from-literal=db-username=nextcloud \
 4  --from-literal=db-password="$(openssl rand -base64 24)" \
 5  --from-literal=db-name=nextcloud \
 6  --from-literal=db-hostname-or-ip=nextcloud-mariadb \
 7  --from-literal=mariadb-root-password="$(openssl rand -base64 32)"
 8
 9# Admin-Account für die Erstinstallation in Schritt 6.
10kubectl create secret generic nextcloud-admin -n nextcloud \
11  --from-literal=nextcloud-username=admin \
12  --from-literal=nextcloud-password="$(openssl rand -base64 24)"
13
14kubectl create secret generic nextcloud-redis -n nextcloud \
15  --from-literal=redis-password="$(openssl rand -base64 24)"
16
17# Nur nötig, wenn icloudpd aktiviert wird.
18kubectl create secret generic nextcloud-icloudpd -n nextcloud \
19  --from-literal=apple-username='<benutzer>@<domain>' \
20  --from-literal=apple-password='<neues Apple-App-Passwort>' \
21  --from-literal=smtp-username='<benutzer>@<domain>' \
22  --from-literal=smtp-password='<neues SMTP-Passwort>'

Die erzeugten Passwörter danach auslesen und im Passwortmanager ablegen:

1kubectl -n nextcloud get secret nextcloud-db -o jsonpath='{.data}' \
2  | python3 -c 'import json,sys,base64;
3    [print(k, base64.b64decode(v).decode()) for k,v in json.load(sys.stdin).items()]'

Migration
#

Ausgangslage: apps/nextcloud läuft. Ziel: dieselbe Instanz, dieselben Daten, neue Struktur. Die Schritte 1-4 laufen ohne Downtime, ab Schritt 5 ist Die Nextcloud-Oberfläche ist nicht erreichbar.

Schritt 1 — Ist-Zustand gegen storage.yaml abgleichen
#

storage.yaml muss die vorhandenen PVCs exakt beschreiben, sonst scheitert der Sync an immutablen Feldern:

1kubectl -n nextcloud get pvc \
2  -o custom-columns=NAME:.metadata.name,SIZE:.spec.resources.requests.storage,SC:.spec.storageClassName,VOL:.spec.volumeName

Abweichungen in storage.yaml nachziehen, bevor es weitergeht.

Schritt 2 — Snapshots
#

1# Über die Longhorn-UI oder per CRD: Snapshot von nextcloud-data und
2# nextcloud-db anlegen. Das ist die einzige echte Rückfallebene für die
3# Nutzdaten, sobald Schritt 8 gelaufen ist.
4kubectl -n longhorn-system get volumes.longhorn.io nextcloud-data nextcloud-db

Schritt 3 — Secrets anlegen
#

Siehe Abschnitt oben. Ohne diese Secrets startet in Schritt 6 nichts.

Schritt 4 — Identität der Altinstallation sichern
#

Kritisch. secret, passwordsalt und instanceid aus der alten config.php müssen übernommen werden. Ohne secret sind alle verschlüsselten Werte in der Datenbank (App-Passwörter, Zugangsdaten für externen Speicher) verloren; ohne instanceid findet Nextcloud das appdata_<instanceid>-Verzeichnis in den Nutzdaten nicht.

1OLD=$(kubectl -n nextcloud get pod -l app.kubernetes.io/name=nextcloud \
2  -o jsonpath='{.items[0].metadata.name}')
3
4kubectl -n nextcloud exec "$OLD" -c nextcloud -- \
5  cat /config/www/nextcloud/config/config.php > /tmp/config.php.alt
6
7grep -E "instanceid|passwordsalt|'secret'" /tmp/config.php.alt

Ebenso die SSH-Hostkeys, damit sich der Fingerprint für Ansible nicht ändert:

1kubectl -n nextcloud exec "$OLD" -c ssh -- \
2  tar cf - -C /config ssh_host_keys > /tmp/ssh_host_keys.tar

Und die Liste der Drittanbieter-Apps, die das offizielle Image nicht mitbringt:

1kubectl -n nextcloud exec "$OLD" -c nextcloud -- occ app:list > /tmp/apps.alt

Schritt 5 — Downtime beginnt: Wartungsmodus und finaler Dump
#

1kubectl -n nextcloud exec "$OLD" -c nextcloud -- occ maintenance:mode --on
2
3kubectl -n nextcloud exec "$OLD" -c db -- \
4  sh -c 'mariadb-dump --single-transaction --default-character-set=utf8mb4 \
5    -u root -p"$MARIADB_ROOT_PASSWORD" nextcloud' > /tmp/nextcloud.sql
6
7ls -lh /tmp/nextcloud.sql   # Plausibilitätsprüfung: nicht leer, nicht winzig

Schritt 6 — Umschalten
#

In manifests.yaml zeigt der bestehende Eintrag auf das neue Verzeichnis — gleicher Application-Name, gleicher Namespace, nur ein anderer Pfad:

1    - name: nextcloud
2      dir: "apps/nextcloud-new"      # vorher: apps/nextcloud
3      namespace: nextcloud

Danach die alte Deployment löschen. Das ist kein optionaler Schritt: der Label-Selector wechselt von app.kubernetes.io/controller: main auf app.kubernetes.io/component: app, und spec.selector ist immutable. Ohne Löschen bricht der Sync mit field is immutable ab.

1kubectl -n nextcloud delete deployment nextcloud

ArgoCD synct jetzt den neuen Stand. Das Webroot-PVC ist leer und im Datenvolume ist data/ noch nicht vorhanden — der Entrypoint sieht also eine jungfräuliche Installation, legt ein frisches config.php an und initialisiert das leere Schema in der neuen MariaDB. Genau das ist gewollt: die Altdaten liegen weiterhin unberührt in der Wurzel des Volumes.

1kubectl -n nextcloud rollout status deploy/nextcloud --timeout=20m
2kubectl -n nextcloud get pods

Schritt 7 — Identität übertragen
#

1NC="kubectl -n nextcloud exec deploy/nextcloud -c nextcloud -- php /var/www/html/occ"
2
3$NC config:system:set instanceid   --value='<Wert aus Schritt 4>'
4$NC config:system:set passwordsalt --value='<Wert aus Schritt 4>'
5$NC config:system:set secret       --value='<Wert aus Schritt 4>'

Schritt 8 — Datenbank und Nutzdaten übernehmen
#

 1kubectl -n nextcloud scale deploy/nextcloud --replicas=0
 2
 3kubectl -n nextcloud exec -i sts/nextcloud-mariadb -- \
 4  sh -c 'mariadb -u root -p"$MARIADB_ROOT_PASSWORD" \
 5    -e "DROP DATABASE nextcloud; CREATE DATABASE nextcloud
 6        CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"'
 7
 8kubectl -n nextcloud exec -i sts/nextcloud-mariadb -- \
 9  sh -c 'mariadb -u root -p"$MARIADB_ROOT_PASSWORD" nextcloud' < /tmp/nextcloud.sql
10
11# Der Dump bringt keine Grants mit.
12kubectl -n nextcloud exec sts/nextcloud-mariadb -- \
13  sh -c 'mariadb -u root -p"$MARIADB_ROOT_PASSWORD" \
14    -e "GRANT ALL ON nextcloud.* TO '"'"'nextcloud'"'"'@'"'"'%'"'"'; FLUSH PRIVILEGES;"'

Jetzt die Nutzdaten unter data/ bringen und auf www-data (33) umschreiben. Der Helper-Pod braucht podAffinity nicht, weil die Nextcloud-Deployment auf 0 steht und das RWO-Volume damit frei ist:

 1kubectl -n nextcloud run migrate --rm -it --restart=Never \
 2  --image=alpine:3.22 --overrides='
 3{
 4  "spec": {
 5    "securityContext": {"runAsUser": 0},
 6    "containers": [{
 7      "name": "migrate", "image": "alpine:3.22",
 8      "command": ["sh"], "stdin": true, "tty": true,
 9      "volumeMounts": [{"name": "d", "mountPath": "/mnt"}]
10    }],
11    "volumes": [{"name": "d",
12      "persistentVolumeClaim": {"claimName": "nextcloud-data"}}]
13  }
14}' -- sh

Im Pod:

1ls /mnt                      # erwartet: die Altdaten + ein frisches data/
2rm -rf /mnt/data             # Reste der Erstinstallation aus Schritt 6
3mkdir -p /mnt/data
4find /mnt -mindepth 1 -maxdepth 1 ! -name data -exec mv -t /mnt/data {} +
5ls /mnt/data                 # erwartet: appdata_<alte-id>, <benutzerverzeichnis>, .ocdata
6chown -R 33:33 /mnt
7exit

chown -R über 350 Gi läuft je nach Dateizahl lange und darf nicht unterbrochen werden.

Die SSH-Hostkeys aus Schritt 4 auf demselben Weg in das PVC nextcloud-sshd-config entpacken (tar xf - -C /mnt, Ziel ssh_host_keys/).

Schritt 9 — Hochfahren und reparieren
#

 1kubectl -n nextcloud scale deploy/nextcloud --replicas=1
 2kubectl -n nextcloud rollout status deploy/nextcloud --timeout=30m
 3
 4$NC maintenance:mode --on
 5$NC upgrade
 6$NC maintenance:repair --include-expensive
 7$NC db:add-missing-indices
 8$NC db:add-missing-columns
 9$NC db:add-missing-primary-keys
10$NC maintenance:mode --off

Ein vollständiges occ files:scan --all ist nicht nötig, weil datadirectory unverändert /data ist und die Storage-IDs damit passen. Wenn einzelne Ordner fehlen, gezielt nachscannen: $NC files:scan --path="/fabrice/files/…".

Die Drittanbieter-Apps aus /tmp/apps.alt gegen $NC app:list abgleichen und fehlende über die Weboberfläche neu installieren.

Schritt 10 — ClamAV umstellen
#

Der Virenscanner spricht nicht mehr über einen Socket, sondern über TCP:

1$NC config:app:set files_antivirus av_mode --value=daemon
2$NC config:app:set files_antivirus av_host --value=nextcloud-clamav
3$NC config:app:set files_antivirus av_port --value=3310
4$NC config:app:set files_antivirus av_stream_max_length --value=536870912

Der ClamAV-Pod braucht beim Erststart mehrere Minuten, bis freshclam die Signaturen geladen hat. Bis dahin steht er auf Ready: false — das ist die startupProbe, kein Fehler.

Schritt 11 — Abnahme
#

1kubectl -n nextcloud get pods,svc,pvc,cronjob
2$NC status
3$NC check
4$NC config:system:get trusted_domains
5$NC config:system:get datadirectory     # muss /data sein
6$NC config:system:get instanceid        # muss dem alten Wert entsprechen

Über die Weboberfläche: Anmeldung mit einem bestehenden Konto, Dateiliste, Up- und Download, Freigabe-Link, CalDAV/CardDAV, /php hinter Authentik, ein Upload gegen den Virenscanner, und einen Cron-Lauf abwarten (kubectl -n nextcloud get jobs).

SSH gegen den unveränderten Endpunkt:

1ssh -p 4022 <benutzer>@<loadbalancer-ip>

Wenn alles steht, icloudpd aktivieren: in values-services.yaml bei beiden Controllern replicas: 0 auf 1 setzen.

Schritt 12 — Aufräumen
#

Erst nach ein paar Tagen stabilen Betriebs:

  1. networkpolicies.yaml in kustomization.yaml aufnehmen.
  2. Den Altbestand-Block aus storage.yaml entfernen (nextcloud-config, nextcloud-db, nextcloud-redis). Die PVs stehen auf Retain, die Longhorn-Volumes bleiben also erhalten und müssen dort separat gelöscht werden.
  3. git rm -r apps/nextcloud und git mv apps/nextcloud-new apps/nextcloud, dann den Pfad in manifests.yaml zurückstellen. Damit heißt das Verzeichnis wieder wie der Namespace, wie es die Repo-Konvention vorsieht.

Rollback
#

Zeitpunkt Rückweg
vor Schritt 6 nichts zu tun, die Altinstallation läuft
nach Schritt 6, vor Schritt 8 manifests.yaml zurückstellen, kubectl -n nextcloud delete deployment nextcloud, Sync abwarten. Die Altdaten liegen unverändert in der Volume-Wurzel.
nach Schritt 8 nur über den Longhorn-Snapshot aus Schritt 2 — die Nutzdaten sind dann nach data/ verschoben und auf uid 33 umgeschrieben

Das Verschieben in Schritt 8 ist prinzipiell umkehrbar (mv /mnt/data/* /mnt/), das chown auf PUID 1000 ebenfalls. Verlassen sollte man sich darauf nicht — deshalb der Snapshot.


Lokale Validierung
#

1kubectl kustomize --enable-helm apps/nextcloud-new

Das legt apps/nextcloud-new/charts/ an — von .gitignore abgedeckt, aber nach dem Testen aufräumen.

Abhängigkeiten
#

  • k3s-Cluster mit Longhorn (StorageClass longhorn)
  • Traefik mit Entrypoint websecure und den Middlewares localnet und authentik im Namespace kube-system
  • cert-manager mit ClusterIssuer letsencrypt-production
  • MetalLB für den SSH-LoadBalancer (feste, mit anderen Diensten geteilte IP)

Dokumentation
#

Fabrice Kirchner
Autor
Fabrice Kirchner
stolzer Vater, Nerd, Admin