Normale Ansicht

Es gibt neue verfügbare Artikel. Klicken Sie, um die Seite zu aktualisieren.
Ältere BeiträgeMy-IT-Brain

Nextcloud im Container – Teil 5: Backup und Restore

21. März 2022 um 06:00

Hallo und herzlich willkommen zu Teil 5 von Nextcloud im Container. In diesem Artikel geht es um Backup und Restore. Die vorhergehenden Teile dieser Serie sind weiter unten verlinkt.

Backup

Mit dem Thema Backup und Restore im Containerland habe ich mich bereits in einem früheren Artikel beschäftigt. Da ich mit dem Ansatz von dort nicht ganz zufrieden bin, gehe ich in diesem Wochenend-Projekt einen anderen Weg.

Für Nextcloud existiert die App Backup, welche im Folgenden zum Einsatz kommt. Diese wird über die App-Verwaltung in den Admin-Einstellungen der Nextcloud aktiviert.

Die englischsprachige Dokumentation (siehe [5]) macht einen soliden und verständlichen Eindruck. Ich habe mich von dieser durch die Konfiguration führen lassen.

Einstellungen der Nextcloud-Sicherung
Standard-Einstellungen der Nextcloud-Sicherungs-App

Ich habe die im obigen Bild dargestellten Einstellungen wie folgt geändert:

  1. Zeitintervall zwischen zwei vollständigen Wiederherstellungspunkten: 7 Tage
  2. Die Verschlüsselung für Wiederherstellungspunkte habe ich deaktiviert
  3. Richtlinie für die lokalen App-Daten: 4

Nun kann man über die entsprechende Schaltfläche einen vollständigen Wiederherstellungspunkt erstellen. Alternativ kann man auch warten, bis das Zeitfenster für den ersten vollständigen Wiederherstellungspunkt erreicht ist.

Ich habe die Sicherung einige Tage mitlaufen lassen. Wie der folgende Screenshot zeigt, wurden ein Full-Backup und zwei darauf folgende differenzielle Backups erzeugt, bevor ein neues Full-Backup erstellt wurde.

Backup-History on Sun 13th Mar
Backup-Historie am 13.03.2022

Hierbei ist zu beachten, dass die Backups in der gleichen Container-Instanz liegen wie die Live- bzw. Produktions-Daten. Damit ist es noch kein richtiges Backup. Denn wenn diese Instanz komplett zerstört wird, ist auch das Backup weg. Die Backups müssen daher unbedingt an einem anderen Ort gespeichert werden. Ich habe mich entschieden, diesem Thema einen eigenen Artikel zu widmen und es in Teil 6 Desaster-Recovery zu behandeln.

Wiederherstellung einer einzelnen Datei

An dieser Stelle möchte ich festhalten, wie eine einzelne Datei wiederhergestellt werden kann. Mit der Wiederherstellung einer kompletten Nextcloud-Instanz beschäftige ich mich in einem folgenden Artikel.

Wiederherstellungspunkte auflisten

Um vorhandene Wiederherstellungspunkte auflisten zu können, wechselt man auf dem Container-Host zuerst in die Container-Instanz mit der laufenden Nextcloud:

$ podman exec -u 33 -it nextcloud bash
www-data@nc_pod:~/html$

Durch ‚-u 33′ betritt man den Container mit der UID des Users www-data, welcher berechtigt ist, die folgenden Kommandos auszuführen. In obigem Beispiel heißt die Container-Instanz schlicht ’nextcloud‘. Für weitere Informationen zum Kommando siehe podman-exec(1). Die Restore-Points können nun wie folgt aufgelistet werden:

www-data@nc_pod:~/html$ ./occ backup:point:list
- retreiving data from local
 > found RestoringPoint 20220305001002-full-3ebDDoh2yinj55C
 > found RestoringPoint 20220307235028-differential-W558tuHGTnCbwgx
 > found RestoringPoint 20220310234002-differential-1NHETYudPSx6Yxc
 > found RestoringPoint 20220312001002-full-i1SY9VxDZRL8n1O
Ausgabe gekürzt.

Einen Wiederherstellungspunkt nach einer Datei durchsuchen

Angenommen, die Bilddatei Frog.jpg ist abhandengekommen. Nun kann ein Wiederherstellungspunkt wie folgt nach dem Dateinamen durchsucht werden:

www-data@nc_pod:~/html$ ./occ backup:file:search --point 20220305001002-full-3ebDDoh2yinj55C Frog.jpg

- searching in 20220305001002-full-3ebDDoh2yinj55C (2022-03-05 00:10:02)
 1/1 [============================] 100%
   > found tronde/files/Photos/Frog.jpg (447.02 KB) in data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e
   > found bob/files/Photos/Frog.jpg (447.02 KB) in data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e
 1/1 [============================] 100%
   > found core/skeleton/Photos/Frog.jpg (447.02 KB) in nextcloud/nextcloud-853e4f81-7f34-4a85-a428-1f569fe7efb5
 1/1 [============================] 100%

In dem angegebenen Wiederherstellungspunkt existiert die Datei Frog.jpg insgesamt dreimal. Es wird jeweils der komplette Pfad angezeigt.

Wiederherstellung von bob/files/Photos/Frog.jpg

Nun soll die Datei Frog.jpg für den Benutzer Bob aus dem oben verwendeten Wiederherstellungspunkt wiederhergestellt werden. Da meine Wiederherstellungspunkte komprimiert gespeichert werden, dient der erste Befehl im folgenden Codeblock jedoch erstmal dazu, einen Wiederherstellungspunkt zu entpacken.

www-data@nc_pod:~/html$ ./occ backup:point:unpack 20220305001002-full-3ebDDoh2yinj55C
Unpacking Restoring Point 20220305001002-full-3ebDDoh2yinj55C
 > lock and set status to unpacking
 > Browsing RestoringData data
   > Unpacking RestoringChunk data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e: proceeding
     * copying parts to temp files
       - 00001-Ur86KyoXRnp8Evt: /tmp/phpkzVs4Y
     * merging parts into single file: /tmp/phpyLjmxZ
     * Extracting /tmp/phpyLjmxZ: /tmp/phpmJG1O1
     - storing chunk in appdata ok
     * removing old chunk parts
 > Browsing RestoringData nextcloud
   > Unpacking RestoringChunk nextcloud-853e4f81-7f34-4a85-a428-1f569fe7efb5: proceeding
     * copying parts to temp files
       - 00001-EUEeVME26dbQyf6: /tmp/phpVfSAt3
     * merging parts into single file: /tmp/phpc3kVw0
     * Extracting /tmp/phpc3kVw0: /tmp/phpF1kt52
     - storing chunk in appdata ok
     * removing old chunk parts
 > Browsing RestoringData apps
   > Unpacking RestoringChunk apps-14864f48-87a9-4c61-82f5-33defc3de2d2: proceeding
     * copying parts to temp files
       - 00001-65lDdATRHTQde5b: /tmp/phpDngG62
     * merging parts into single file: /tmp/php9U5X7Y
     * Extracting /tmp/php9U5X7Y: /tmp/phpXGwXP0
     - storing chunk in appdata ok
     * removing old chunk parts
 > Browsing RestoringData config
   > Unpacking RestoringChunk config-a8809c3e-5259-49b4-b2cb-2dbeb755949f: proceeding
     * copying parts to temp files
       - 00001-HMfvJewXGLEckCH: /tmp/phpPePsK1
     * merging parts into single file: /tmp/phpVlxXA1
     * Extracting /tmp/phpVlxXA1: /tmp/phpBUIDm0
     - storing chunk in appdata ok
     * removing old chunk parts
 > Browsing RestoringData apps-custom_apps-84a585e6
   > Unpacking RestoringChunk apps-custom_apps-84a585e6-c4e2adaa-eb06-4318-8196-62aea73b89c8: proceeding
     * copying parts to temp files
       - 00001-pXttjhVm9cRU6DU: /tmp/phpATT8t2
     * merging parts into single file: /tmp/php8HMcR1
     * Extracting /tmp/php8HMcR1: /tmp/phpmHRKS1
     - storing chunk in appdata ok
     * removing old chunk parts
 > Browsing RestoringData sqldump
   > Unpacking RestoringChunk sqldump-d0ebed1c-81dd-418b-a8ba-cecca8d92c00: proceeding
     * copying parts to temp files
       - 00001-QYOIpn2zOj43TsL: /tmp/phpcEUqQZ
     * merging parts into single file: /tmp/phpOwn0g1
     * Extracting /tmp/phpOwn0g1: /tmp/phpiJxrh3
     - storing chunk in appdata ok
     * removing old chunk parts
 > removing status packed
 > unlocking restoring point

www-data@nc_pod:~/html$ ./occ backup:point:restore 20220305001002-full-3ebDDoh2yinj55C --file bob/files/Photos/Frog.jpg --data data                                           
   > restoring bob/files/Photos/Frog.jpg (447.02 KB) from /data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e (rewind: 8 days, 20 hours, 51 minutes and 20 seconds): ok

Die allgemeine Befehlsform für die Wiederherstellung lautet:

backup:point:restore [--force] [--do-not-ask-data] [--do-not-ask-sql] [--file FILE] [--chunk CHUNK] [--data DATA] [--] <pointId>

Es ist nicht gut dokumentiert, wie man den korrekten Wert für --data herausfindet. Ich habe diesen durch Ausprobieren gefunden. Dann war der Restore jedoch kein Problem mehr. Wie man die korrekten Werte für --data bzw. --chunk sicher identifiziert, muss ich noch herausfinden. Falls hier jemand einen Tipp für mich hat, freue ich mich über euren Kommentar oder eine E-Mail.

Um Speicherplatz zu sparen, komprimiere ich den genutzten Wiederherstellungspunkt wieder und verlasse den Container:

www-data@nc_pod:~/html$ ./occ backup:point:pack 20220305001002-full-3ebDDoh2yinj55C
Packing Restoring Point 20220305001002-full-3ebDDoh2yinj55C
 > lock and set status to processing
 > Browsing RestoringData data
   > Packing RestoringChunk data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e: proceeding
     * copying chunk to temp file /tmp/phpsyGIxw: ok
     * compressing /tmp/phpsyGIxw: /tmp/phpjuZY7z
     * spliting /tmp/phpjuZY7z in parts: 1 part(s) 
     - storing parts in appdata .ok
     * Removing old chunk file data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e.zip
 > Browsing RestoringData nextcloud
   > Packing RestoringChunk nextcloud-853e4f81-7f34-4a85-a428-1f569fe7efb5: proceeding
     * copying chunk to temp file /tmp/php6f6Kfx: ok
     * compressing /tmp/php6f6Kfx: /tmp/phpz3Ndtz
     * spliting /tmp/phpz3Ndtz in parts: 1 part(s) 
     - storing parts in appdata .ok
     * Removing old chunk file nextcloud-853e4f81-7f34-4a85-a428-1f569fe7efb5.zip
 > Browsing RestoringData apps
   > Packing RestoringChunk apps-14864f48-87a9-4c61-82f5-33defc3de2d2: proceeding
     * copying chunk to temp file /tmp/phpf19OHA: ok
     * compressing /tmp/phpf19OHA: /tmp/phpZMcpmw
     * spliting /tmp/phpZMcpmw in parts: 1 part(s) 
     - storing parts in appdata .ok
     * Removing old chunk file apps-14864f48-87a9-4c61-82f5-33defc3de2d2.zip
 > Browsing RestoringData config
   > Packing RestoringChunk config-a8809c3e-5259-49b4-b2cb-2dbeb755949f: proceeding
     * copying chunk to temp file /tmp/phpykt9Rw: ok
     * compressing /tmp/phpykt9Rw: /tmp/phpxik6bx
     * spliting /tmp/phpxik6bx in parts: 1 part(s) 
     - storing parts in appdata .ok
     * Removing old chunk file config-a8809c3e-5259-49b4-b2cb-2dbeb755949f.zip
 > Browsing RestoringData apps-custom_apps-84a585e6
   > Packing RestoringChunk apps-custom_apps-84a585e6-c4e2adaa-eb06-4318-8196-62aea73b89c8: proceeding
     * copying chunk to temp file /tmp/php1oAWAA: ok
     * compressing /tmp/php1oAWAA: /tmp/phpOtyrjA
     * spliting /tmp/phpOtyrjA in parts: 1 part(s) 
     - storing parts in appdata .ok
     * Removing old chunk file apps-custom_apps-84a585e6-c4e2adaa-eb06-4318-8196-62aea73b89c8.zip
 > Browsing RestoringData internal
   > Packing RestoringChunk app.zip: already packed
   > Packing RestoringChunk restore.php: already packed
 > Browsing RestoringData sqldump
   > Packing RestoringChunk sqldump-d0ebed1c-81dd-418b-a8ba-cecca8d92c00: proceeding
     * copying chunk to temp file /tmp/phpFfW2zy: ok
     * compressing /tmp/phpFfW2zy: /tmp/phpvXl8qy
     * spliting /tmp/phpvXl8qy in parts: 1 part(s) 
     - storing parts in appdata .ok
     * Removing old chunk file sqldump-d0ebed1c-81dd-418b-a8ba-cecca8d92c00.zip
 > removing status processing, adding status packed
 > unlocking restoring point
www-data@nc_pod:~/html$ exit
exit

Wiederherstellung eines Ordners inkl. Inhalt

Manchmal ist es erforderlich, statt einzelner Dateien ganze Ordner inkl. Inhalt wiederherzustellen. Wie dies funktioniert, demonstriere ich im Folgenden für den Ordner Documents des Benutzers Bob. Dazu wechsle ich zuerst wieder in den Container, wie in diesem Abschnitt bereits beschrieben wurde.

TL;DR: Die Wiederherstellung eines Ordners inkl. dessen Inhalts ist aktuell nicht möglich (siehe [6]). Wer es eilig hat, kann direkt zum Fazit springen.

Während ich im vorherigen Abschnitt einen ausgewählten Wiederherstellungspunkt nach einer Datei durchsucht habe, liste ich diesmal alle Wiederherstellungspunkte bis zum 15.03.2022 auf, welche den gesuchten Pfad enthalten:

www-data@nc_pod:~/html$ ./occ backup:file:search bob/files/Documents --until 2022-03-15

- searching in 20220305001002-full-3ebDDoh2yinj55C (2022-03-05 00:10:02)
 1/1 [============================] 100%
   > found bob/files/Documents/Example.md (1.07 KB) in data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e
   > found bob/files/Documents/Nextcloud flyer.pdf (365.24 KB) in data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e
   > found bob/files/Documents/Readme.md (136 B) in data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e
   > found bob/files/Documents/Welcome to Nextcloud Hub.docx (24.56 KB) in data/data-baa61d4a-85a8-4cc7-b43b-5a6270b7143e
 1/1 [============================] 100%

- searching in 20220307235028-differential-W558tuHGTnCbwgx (2022-03-07 23:50:28)
 1/1 [============================] 100%   no result

- searching in 20220310234002-differential-1NHETYudPSx6Yxc (2022-03-10 23:40:02)
 1/1 [============================] 100%   no result

- searching in 20220312001002-full-i1SY9VxDZRL8n1O (2022-03-12 00:10:02)
 1/1 [============================] 100%
   > found bob/files/Documents/Example.md (1.07 KB) in data/data-f55df957-3368-4b84-b957-4dc3e819c0ce
   > found bob/files/Documents/Nextcloud flyer.pdf (365.24 KB) in data/data-f55df957-3368-4b84-b957-4dc3e819c0ce
   > found bob/files/Documents/Readme.md (136 B) in data/data-f55df957-3368-4b84-b957-4dc3e819c0ce
   > found bob/files/Documents/Welcome to Nextcloud Hub.docx (24.56 KB) in data/data-f55df957-3368-4b84-b957-4dc3e819c0ce
 1/1 [============================] 100%

- searching in 20220314234502-differential-suwLdJJegRlO4XI (2022-03-14 23:45:02)
 1/1 [============================] 100%   no result

Es muss der vollständige Pfad zum gesuchten Verzeichnis angegeben werden. Wildcards wie z.B. */Documents oder "*/Documents" funktionieren genauso wenig wie reguläre Ausdrücke. Dies kann die Suche nach einem Ordner schonmal schwierig gestalten. Denn welcher Anwender kennt schon den vollständigen Pfad zu dem Ordner, der vermisst wird?

Im obigen Codeblock ist zu sehen, dass der Pfad zum Ordner lediglich als Bestandteil der Pfade zu den darin enthaltenen Dateien angezeigt wird. Dies und die Erkenntnis, keine Suchmuster verwenden zu können, lassen bei mir erste Zweifel aufkommen, ob das Verzeichnis inkl. Inhalt wiederhergestellt werden kann, oder ob ich jede enthaltene Datei einzeln wiederherstellen muss.

Doch bevor ich mich an der Wiederherstellung versuchen kann, muss ich zuerst den ausgewählten Wiederherstellungspunkt entpacken. Wie dies aussieht, kann dem Abschnitt über die Dateiwiederherstellung entnommen werden.

Der folgende Codeblock zeigt dann auch, dass der Ordner nicht wiederhergestellt werden kann:

www-data@nc_pod:~/html$ ./occ backup:point:restore 20220312001002-full-i1SY9VxDZRL8n1O --file bob/files/Documents --data data
 
In ChunkService.php line 925:
                                                        
  [OCA\Backup\Exceptions\ArchiveFileNotFoundException]  
                                                        

backup:point:restore [--force] [--do-not-ask-data] [--do-not-ask-sql] [--file FILE] [--chunk CHUNK] [--data DATA] [--] <pointId>

Eine Wiederherstellung ist offenbar nur auf Dateiebene möglich (siehe [6]). Das ist sehr schade, da dies die Wiederherstellung deutlich verkompliziert. Vor allem da Wildcards ebenfalls nicht funktionieren.

Fazit

In diesem Artikel habe ich das Thema Backup und Recovery aufgegriffen. Ich habe kurz beschrieben, wie eine Sicherung mit der Nextcloud-Backup-App konfiguriert werden kann. Nachdem einige Wiederherstellungspunkte erstellt wurden, habe ich exemplarisch eine Datei wiederhergestellt.

Da die Wiederherstellungspunkte komprimiert gespeichert werden, musste der ausgewählte Wiederherstellungspunkt vor dem Restore erst dekomprimiert werden, was einige Zeit gedauert hat. Hier muss jeder für sich selbst entscheiden, ob man sich die kürzere Zeit zur Wiederherstellung mit einem erhöhten Speicherbedarf durch unkomprimierte Wiederherstellungspunkte erkaufen möchte oder nicht.

Die zu Beginn des Artikels noch gelobte Dokumentation offenbarte schnell Lücken und ich muss mein Urteil revidieren. Sie ist im besten Fall ausreichend.

Der Versuch, einen Ordner inkl. Inhalt wiederherzustellen, endete hingegen in einer Enttäuschung. Dies ist aktuell offenbar nicht möglich, da nur der Datei-Restore oder die Wiederherstellung der gesamten Nextcloud-Instanz unterstützt wird. Diese Erfahrung lässt mich ein wenig enttäuscht und unzufrieden zurück.

Wie sichert ihr eure Nextcloud? Welche Restore-Fälle habt ihr damit bereits durchgespielt? Ich freue mich auf eure Kommentare und darauf euch zu Teil 6: Desaster-Recovery Updates wieder begrüßen zu dürfen.

Update 27.03.2022

Der obige Text wurde dahingehend angepasst, dass nun deutlich wird, dass die Wiederherstellung ganzer Verzeichnisse inkl. deren Inhalt aktuell nicht unterstützt wird (siehe [6]). Nicht mehr zutreffende Textstellen habe ich gestrichen.

Entgegen meiner ursprünglichen Planung wird es keinen Artikel zum Thema Desaster-Recovery geben, da es mir aktuell nicht möglich ist, die Restore-Points auf externem Speicher abzulegen (siehe [7] und [8]).

Damit ist die Backup-App in ihrem aktuellen Zustand (Version 1.0.6; Stand 27.03.2022) in meinen Augen unbrauchbar. Das ist schade, da mir die Idee, die Backup&Recovery-Funktion als App direkt zu integrieren, vom Grundsatz her gut gefällt.

Bis auf Weiteres verfahre ich daher so, wie analog im Artikel Backup und Restore im Kanboard-Container-Land beschrieben. Das dort beschriebene Verfahren lässt sich auch hier anwenden und genügt meinen Anforderungen.

Quellen und weiterführende Links

  1. Nextcloud im Container – Teil 1: Der Plan
  2. Nextcloud im Container – Teil 2: Die Ansible-Rolle
  3. Nextcloud im Container – Teil 3: Mit Reverse-Proxy
  4. Nextcloud im Container – Teil 4: Hier und da klemmt es
  5. Nextcloud im Container – Teil 6: Updates
  6. Nextcloud Backup App auf GitHub
  7. How to restore a folder with all files in it? #211
  8. S3 upload still failes with OOM for 1.0.6 #237
  9. Nothing being uploaded to external storage (WebDAV) #238

Nextcloud im Container — Teil 4: Hier und da klemmt es

07. März 2022 um 06:00

Herzlich Willkommen zu Teil 4 meines Wochenend-Projekts „Nextcloud im Container“. Diesem gingen die folgenden Teile voraus:

  1. Der Plan
  2. Die Ansible-Rolle
  3. NGINX als Reverse-Proxy

Nach Teil 3 habe ich die Zwei-Faktor-Authentisierung über TOTP für meine Nutzerkonten aktiviert, die Bookmark-, Calendar- und Contact-App installiert bzw. aktiviert, ein paar Kalendertermine erstellt und ein paar Dateien hochgeladen. Nichts Wichtiges. Lediglich ein paar Daten, die ich nach einem Backup zerstören kann, um anschließend den Restore-Prozess zu testen. Zuvor möchte ich aber noch ein paar Dinge festhalten, die mir bisher aufgefallen sind.

Background jobs: Cron does not run

In den Grundeinstellungen der Nextcloud werden Hintergrund-Aufgaben konfiguriert. Diese sind laut des dortigen Hinweises wichtig, um die optimale Geschwindigkeit zu erreichen:

Um die optimale Geschwindigkeit zu erreichen ist es wichtig, dass die Hintergrund-Aktivitäten richtig konfiguriert sind. Für größere Installationen ist ‚Cron‘ die empfohlene Einstellung. Weitere Informationen findest Du in der Dokumentation.

Grundeinstellungen in den Nextcloud-Einstellungen

Die Überschrift ist der Titel des GitHub-Issues #1695. Dieser beschäftigt sich damit, dass Cron in der Container-Instanz nicht läuft. Halt genau so, wie Cron dies bei mir auch nicht tut.

Der Benutzer beryl03, welcher den Issue eröffnet hat, beschreibt, dass Cron in der Container-Instanz nicht verfügbar ist und er in der Dokumentation keinen Hinweis darauf gefunden hat. Um das Problem zu mitigieren hat beryl03 einen Cronjob auf seinem Container-Host konfiguriert, welcher sich mit der Container-Instanz verbindet und darin die Datei cron.php ausführt. Welch elender Workaround. Aber immerhin gibt es einen. Denn die Hintergrund-Aufgaben mit AJAX auszuführen, scheitert leider ebenfalls. Schade, so habe ich mir das tatsächlich nicht vorgestellt.

Im Verlauf von Issue #1695 wird darauf hingewiesen, dass zur Verwendung von Cron ein weiterer Container benötigt wird (siehe [3]). Dies wird in den Beispielen zu den Compose-Dateien beschrieben (siehe [4]). Da ich Podman und Ansible statt Docker-Compose verwende, habe ich mir diese Beispiele natürlich nicht angesehen. Das ist dem Projekt nicht anzulasten, da ich mich ja bewusst für einen anderen Weg entschieden habe. Doch denke ich, dass man das Thema Hintergrund-Aufgaben innerhalb der Projekt-Dokumentation als auch in der Nextcloud-Dokumentation etwas ausführlicher behandeln könnte und sollte. Doch wie gehe ich nun mit dem Problem um, dass meine Hintergrund-Aufgaben nicht ausgeführt werden?

Docker-Compose mit Podman nutzen

Tatsächlich habe ich einen Artikel gefunden, welcher beschreibt, wie man Docker-Compose ab Podman 3.0 nutzen kann. Allerdings bietet dieser nur eine Lösung für den Fall, dass man Podman als User root bzw. mit Root-Rechten ausführt. Da Podman bei mir rootless läuft, kommt die Lösung für mich nicht in Frage.

Nach etwas weiterer Recherche habe ich einen RFE gefunden, welcher diese Funktionalität auch für rootless-Podman fordert. Die gute Nachricht lautet, dass diese Funktion mit Podman 3.2 veröffentlicht wurde. Pech für mich, dass unter Debian stable lediglich Podman 3.0.1 in den Quellen verfügbar ist.

Ein Workaround ist besser als gar keine Lösung

Tatsächlich erscheint mir aktuell der Workaround von beryl03 (siehe [1]) der beste Weg zu sein, um die Hintergrund-Aufgaben ausführen zu lassen. Dazu führe ich auf meinem Container-Host folgenden Befehl aus:

$ podman exec -u 33 -t nextcloud php -f /var/www/html/cron.php

Damit wird das Skript cron.php innerhalb der Container-Instanz mit der Nextcloud ausgeführt. Mit -u 33 wird die UID von www-data innerhalb der Container-Instanz angegeben. Für eine genaue Erklärung des Befehls und seiner Optionen siehe podman-exec(1).

Hintergrund-Aufgaben wurden erfolgreich ausgeführt.
Die Hintergrund-Aufgaben wurden nun erfolgreich ausgeführt

Da ich nicht gern lange Befehle in die Crontab schreibe, erstelle ich ein kurzes Skript namens nextcloud_cron.sh, welches obigen Befehl aufnimmt und welches ich alle 5 Minuten von Cron ausführen lasse. Damit werde ich sich noch sehr lange arbeiten, denn nicht umsonst sagen manche: „Nichts hält so lange, wie ein gutes Improvisorium.“

Fazit von Teil 4

Ich hoffe, die Artikelserie hat euch bis hierhin ein wenig unterhalten. Wer nach einer einfachen Lösung gesucht hat, bei der man ein bis zwei Container-Images aus dem Regal nimmt, ein paar Variablen mit Werten füllt, sie auf einen Container-Host provisioniert, ausführt und fertig ist, wird sicher gemerkt haben, dass er diese Lösung in dieser Artikelreihe nicht findet.

Auch ich habe mir zu Beginn nicht vorgestellt, dass es so hakelig werden würde. Schließlich soll mit Containern doch alles einfacher werden, nicht wahr? Warum mache ich also weiter und lasse das ganze Wochenend-Projekt nicht einfach fallen? Neugier, Sturheit, eine nutzbare Nextcloud-Instanz und auch ein bisschen Spaß bilden die Antwort auf vorstehende Frage. Und deshalb mache ich auch weiter. In Teil 5 wird es um Backup und Restore gehen.

Wie betreibt ihr eure Nextcloud? Mit Container oder ohne? Unter Docker, K3s, K8s, Podman, OpenShift oder einer noch ganz anderen Lösung? Lasst es mich gern in den Kommentaren wissen. Habt ihr über eure Erfahrungen in eurem eigenen Blog geschrieben, lasst mir gern einen Link hier. Macht es gut, bis nächste Woche.

Quellen und weiterführende Links

  1. Background jobs: Cron does not run #1695
  2. AJAX Background Jobs Fail After a Period of Inactivity #1442
  3. https://github.com/nextcloud/docker/issues/1695#issuecomment-1042602441
  4. https://github.com/nextcloud/docker/blob/master/.examples/docker-compose/insecure/mariadb/apache/docker-compose.yml
  5. Using Podman and Docker Compose. Podman 3.0 now supports Docker Compose to orchestrate containers. Enable Sysadmin. 2021-01-07.
  6. [RFE]Make docker-compose work with rootless podman #9169

Nextcloud im Container – Teil 2: Die Ansible-Rolle

21. Februar 2022 um 06:00

In Teil 1 dieser Artikelserie habe ich mein Ansinnen ausführlich beschrieben. Dieser Teil widmet sich der Entwicklung einer Ansible-Rolle zum Deployment des Nextcloud-Apache-Container-Images.

In den folgenden Abschnitten beschreibe ich die Einrichtung eines Python Virtual Environments, die Installation von Ansible in dem zuvor erstellten Environment und die Installation der Ansible-Collection containers.podman, bevor ich mich abschließend der eigentlichen Ansible-Rolle widme.

Python Virtual Environments für Ansible

Zur Einrichtung habe ich mich an den englischsprachigen Artikel „How to set up and use Python virtual environments for Ansible“ von Gineesh Madapparambath gehalten. Die notwendigen Schritte werden hier kurz und bündig dokumentiert.

[t14s ~]$ python3 --version
Python 3.9.7

[t14s ~]$ mkdir python-venv
[t14s ~]$ cd !$
cd python-venv

[t14s python-venv]$ python3 -m venv ansible-core2.x
[t14s python-venv]$ source ansible-core2.x/bin/activate
(ansible-core2.x) [jkastning@t14s python-venv]$ python3 -m pip install --upgrade pip
Requirement already satisfied: pip in ./ansible-core2.x/lib/python3.9/site-packages (21.0.1)
Collecting pip
  Downloading pip-21.3.1-py3-none-any.whl (1.7 MB)
     |████████████████████████████████| 1.7 MB 2.3 MB/s 
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 21.0.1
    Uninstalling pip-21.0.1:
      Successfully uninstalled pip-21.0.1
Successfully installed pip-21.3.1

(ansible-core2.x) [t14s python-venv]$ python3 -m pip install ansible-core
Collecting ansible-core
[...]

(ansible-core2.x) [t14s python-venv]$ ansible --version
ansible [core 2.11.6] 
  config file = None
  configured module search path = ['/home/tronde/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/tronde/python-venv/ansible-core2.x/lib64/python3.9/site-packages/ansible
  ansible collection location = /home/tronde/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/tronde/python-venv/ansible-core2.x/bin/ansible
  python version = 3.9.7 (default, Aug 30 2021, 00:00:00) [GCC 11.2.1 20210728 (Red Hat 11.2.1-1)]
  jinja version = 3.0.2
  libyaml = True

Damit ist die Installation von ansible-core abgeschlossen. Im folgenden Code-Block wird geprüft, ob Ansible sich grundsätzlich mit dem Zielsystem verbinden und dort einen Python-Interpreter identifizieren kann.

(ansible-core2.x) [t14s python-venv]$ ansible -i hosts --private-key ~/.ssh/ansible_id_rsa -m ping example.com
example.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

Installation der Ansible-Collection containers.podman

Um Podman auf dem Zielsystem konfigurieren zu können, wird die genannte Ansible-Collection benötigt, welche mit folgendem Befehl installiert werden kann. Der Code-Block zeigt zusätzlich die Ausgabe während der Installation.

(ansible-core2.x) [t14s ansible-core2.x]$ ansible-galaxy collection install containers.podman
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/download/containers-podman-1.8.2.tar.gz to /home/tronde/.ansible/tmp/ansible-local-8729oh0om8w3/tmp7tv2yrae/containers-podman-1.8.2-9rw3fd1y
Installing 'containers.podman:1.8.2' to '/home/tronde/.ansible/collections/ansible_collections/containers/podman'
containers.podman:1.8.2 was installed successfully

Ansible-Rolle: Deployment von Nextcloud und MariaDB als Pod

Nextcloud benötigt für den Betrieb eine Datenbank. Hierfür könnte man eine integrierte SQLite nutzen. Dies wird jedoch nur für kleine Umgebungen empfohlen. Während der Entstehung dieses Artikels wird MariaDB als Datenbank-Backend vom Nextlcoud-Projekt empfohlen. Daher habe ich mich entschieden, das Nextcloud-Image zusammen mit einem MariaDB-Container zu deployen. Dazu greife ich auf die beiden folgenden Container-Repositorien zurück:

Das Grundgerüst bzw. die Verzeichnisstruktur für die Ansible-Rolle wurde erstellt mit:

$ ansible-galaxy role init --offline ansible_role_deploy_nextcloud_with_mariadb_pod

Die aktuelle Version der Ansible-Rolle ist auf GitHub zu finden. Ich werde ihre Bestandteile hier im Einzelnen vorstellen.

Die Variablen in defaults/main.yml

In der Datei defaults/main.yml habe ich Standardwerte für Variablen definiert, die geeignet sind, eine funktionsfähige Nextcloud-Instanz zu initialisieren. Die Bezeichner der Variablen sind dabei der Dokumentation der verwendeten Container-Repositorien entnommen.

In Zeile 4-7 und 10 werden die Namen für Podman-Volumes definiert, welche die persistent zu speichernden Daten aufnehmen werden.

     1	---
     2	# defaults file for ansible_role_deploy_nextcloud_with_mariadb_pod
     3	# Podman volumes for Nextcloud
     4	NC_HTML: nc_html
     5	NC_APPS: nc_apps
     6	NC_CONFIG: nc_config
     7	NC_DATA: nc_data
     8	
     9	# Podman volume for MariaDB
    10	MYSQL_DATA: mysql_data

Die Zeilen 13-17 definieren Variablen für die MariaDB-Instanz, wie z.B. Namen der Datenbank, Benutzername und Passwörter für diese Datenbank und den DB-Host. Diese werden neben dem MariaDB-Container auch von dem Nextcloud-Container benötigt, um eine Verbindung zur Datenbank herstellen zu können.

    12	# MySQL/MariaDB vars
    13	MYSQL_DATABASE: nc_db
    14	MYSQL_USER: nextcloud
    15	MYSQL_PASSWORD: ToPSeCrEt2021!
    16	MYSQL_ROOT_PASSWORD: ToPSeCrEt2021!
    17	MYSQL_HOST: 127.0.0.1
    18	
    19	# Vars for MariaDB container
    20	MARIADB_CONMON_PIDFILE: /tmp/mariadb_conmon.pid
    21	MARIADB_IMAGE: docker.io/library/mariadb:10.5.7
    22	MARIADB_NAME: nc_mariadb

Zeile 20-22 definiert Variablen, die für den MariaDB-Container benötigt werden. Hier wird z.B. die Version des Container-Images (MARIADB_IMAGE) und ein Name für die Container-Instanz (MARIADB_NAME) festgelegt.

Die folgenden Zeilen widmen sich den Variablen für den Nextcloud-Container. Dort werden in den Zeilen 25 u. 26 Benutzername und Passwort für den Nextcloud-Admin definiert, gefolgt von einigen Variablen, welche bei Nutzung eines Reverse-Proxy benötigt werden und SMTP-Variablen, welche der Nextcloud den Mailversand ermöglichen.

    24	# Nextcloud vars
    25	NEXTCLOUD_ADMIN_USER: nc_admin
    26	NEXTCLOUD_ADMIN_PASSWORD: VSnfD2021!
    27	NEXTCLOUD_OVERWRITEPROTOCOL: ""
    28	NEXTCLOUD_OVERWRITECLIURL: ""
    29	NEXTCLOUD_TRUSTED_DOMAINS: ""
    30	
    31	# SMTP vars
    32	SMTP_HOST: smtp.example.com
    33	SMTP_SECURE: tls # ssl to use SSL, or tls zu use STARTTLS
    34	SMTP_PORT: 587 # (25, 465 for SSL, 587 for STARTTLS)
    35	SMTP_AUTHTYPE: LOGIN
    36	SMTP_NAME: bob@example.com
    37	SMTP_PASSWORD: MailSecret1!
    38	MAIL_FROM_ADDRESS: no-reply@example.com
    39	MAIL_DOMAIN: "@example.com"

Bei den SMTP-Variablen handelt es sich um Beispiel-Werte. Diese müssen an die konkrete Umgebung angepasst werden.

Es folgen nun noch ein paar Variablen, welche dem Pod und dem Nextcloud-Container einen Namen geben, sowie die Version des zu verwendenden Nextcloud-Container-Images festlegen.

    41	# Vars for podman-pod(1)
    42	POD_NAME: nc_pod
    43	POD_PORT: 127.0.0.1:40231:80
    44	POD_INFRA_CONMON_PIDFILE: /tmp/nc_pod_infra.pid
    45	
    46	# Vars for Nextcloud container
    47	NC_CONMON_PIDFILE: /tmp/nc_conmon.pid
    48	NC_IMAGE: docker.io/library/nextcloud:23-apache
    49	NC_NAME: nextcloud

Durch POD_PORT: 127.0.0.1:40231:80 wird definiert, dass der Port 40231 an das Loopback-Interface gebunden und mit Port 80 des Pods verknüpft wird. Mit dieser Einstellung ist die Nextcloud-Instanz nur von dem Host aus erreichbar, auf dem sie ausgebracht wurde. Möchte man sie auch von anderen Hosts aus erreichbar machen, kann man entweder den Teil mit 127.0.0.1: weglassen oder einen Reverse-Proxy wie z.B. NGINX verwenden. Ich empfehle an dieser Stelle letzteres.

Hinweis: In defauts/main.yml stehen Passwörter im Klartext. Diese sind mit der Veröffentlichung der Ansible-Rolle allgemein bekannt und sollten gegen solche ersetzt werden, die geheimgehalten werden. Dies kann z.B. geschehen, in dem man die entsprechenden Variablen in vars/main.yml oder host_vars/hostname neu definiert. Es bietet sich an, diese zusätzlich mit Ansible-Vault zu verschlüsseln.

Die Tasks in tasks/main.yml

Im vorstehenden Abschnitt wurden die Variablen definiert, welche für die nun folgenden Tasks benötigt werden. Diese sind in tasks/main.yml definiert und werden im folgenden wieder abschnittsweise erläutert.

     1	---
     2	# tasks file for ansible_role_deploy_nextcloud_with_mariadb_pod
     3	- name: Main folder, needed for updating
     4	  containers.podman.podman_volume:
     5	    state: present
     6	    name: "{{ NC_HTML }}"
     7	    recreate: no
     8	    debug: no
     9	
    10	- name: Volume for installed/modified apps
    11	  containers.podman.podman_volume:
    12	    state: present
    13	    name: "{{ NC_APPS }}"
    14	    recreate: no
    15	    debug: no
    16	
    17	- name: Volume for local configuration
    18	  containers.podman.podman_volume:
    19	    state: present
    20	    name: "{{ NC_CONFIG }}"
    21	    recreate: no
    22	    debug: no
    23	
    24	- name: Volume for the actual data of Nextcloud
    25	  containers.podman.podman_volume:
    26	    state: present
    27	    name: "{{ NC_DATA }}"
    28	    recreate: no
    29	    debug: no
    30	
    31	- name: Volume for the MySQL data files
    32	  containers.podman.podman_volume:
    33	    state: present
    34	    name: "{{ MYSQL_DATA }}"
    35	    recreate: no
    36	    debug: no

Die ersten Zeilen enthalten Tasks, durch welche die Podman-Volumes zur persistenten Datenspeicherung auf dem Zielsystem erstellt werden. Diese Tasks sind, wie für Ansible üblich, deklarativ und idempotent. Existiert ein Volume bereits, liefert der entsprechende Task ein ‚OK‘ zurück, da keine Aktionen erforderlich sind.

Die folgenden Zeilen erstellen den Podman-Pod und fügen ihm einen Nextcloud- sowie einen MariaDB-Container hinzu. Die Dokumentation der verwendeten Module findet sich in Punkt 5 und 6 im Abschnitt Quellen und weiterführende Links.

    38	- name: Create the podman-pod(1)
    39	  containers.podman.podman_pod:
    40	    debug: no
    41	    infra: yes
    42	    infra_conmon_pidfile: "{{ POD_INFRA_CONMON_PIDFILE }}"
    43	    publish: "{{ POD_PORT }}"
    44	    name: "{{ POD_NAME }}"
    45	    state: started
    46	
    47	- name: Create MariaDB container
    48	  containers.podman.podman_container:
    49	    debug: yes
    50	    conmon_pidfile: "{{ MARIADB_CONMON_PIDFILE }}"
    51	    image: "{{ MARIADB_IMAGE }}"
    52	    image_strict: yes
    53	    pod: "{{ POD_NAME }}"
    54	    recreate: yes
    55	    state: started
    56	    name: "{{ MARIADB_NAME }}"
    57	    env:
    58	      MYSQL_USER: "{{ MYSQL_USER }}"
    59	      MYSQL_PASSWORD: "{{ MYSQL_PASSWORD }}"
    60	      MYSQL_ROOT_PASSWORD: "{{ MYSQL_ROOT_PASSWORD }}"
    61	      MYSQL_DATABASE: "{{ MYSQL_DATABASE }}"
    62	    volume: "{{ MYSQL_DATA }}:/var/lib/mysql:Z"
    63	
    64	- name: Wait for DB to initilize
    65	  wait_for:
    66	    timeout: 20
    67	
    68	- name: Create Nextcloud container
    69	  containers.podman.podman_container:
    70	    debug: no 
    71	    conmon_pidfile: "{{ NC_CONMON_PIDFILE }}"
    72	    image: "{{ NC_IMAGE }}"
    73	    image_strict: yes
    74	    pod: "{{ POD_NAME }}"
    75	    recreate: yes
    76	    state: started
    77	    name: "{{ NC_NAME }}"
    78	    env:
    79	      MYSQL_DATABASE: "{{ MYSQL_DATABASE }}"
    80	      MYSQL_USER: "{{ MYSQL_USER }}"
    81	      MYSQL_PASSWORD: "{{ MYSQL_PASSWORD }}"
    82	      MYSQL_HOST: "{{ MYSQL_HOST }}"
    83	      NEXTCLOUD_ADMIN_USER: "{{ NEXTCLOUD_ADMIN_USER }}"
    84	      NEXTCLOUD_ADMIN_PASSWORD: "{{ NEXTCLOUD_ADMIN_PASSWORD }}"
    85	      NEXTCLOUD_TRUSTED_DOMAINS: "{{ NEXTCLOUD_TRUSTED_DOMAINS }}"
    86	      SMTP_HOST: "{{ SMTP_HOST }}"
    87	      SMTP_SECURE: "{{ SMTP_SECURE }}"
    88	      SMTP_PORT: "{{ SMTP_PORT }}"
    89	      SMTP_AUTHTYPE: "{{ SMTP_AUTHTYPE }}"
    90	      SMTP_NAME: "{{ SMTP_NAME }}"
    91	      SMTP_PASSWORD: "{{ SMTP_PASSWORD }}"
    92	      MAIL_FROM_ADDRESS: "{{ MAIL_FROM_ADDRESS }}"
    93	      MAIL_DOMAIN: "{{ MAIL_DOMAIN }}"
    94	      OVERWRITEPROTOCOL: "{{ NEXTCLOUD_OVERWRITEPROTOCOL }}"
    95	      OVERWRITECLIURL: "{{ NEXTCLOUD_OVERWRITECLIURL }}"
    96	    volume:
    97	      - "{{ NC_HTML }}:/var/www/html:Z"
    98	      - "{{ NC_APPS }}:/var/www/html/custom_apps:Z"
    99	      - "{{ NC_CONFIG }}:/var/www/html/config:Z"
   100	      - "{{ NC_DATA }}:/var/www/html/data:Z"

In Zeile 64-66 habe ich einen Task definiert, der einfach nur 20 Sekunden wartet. Dies wurde erforderlich, da ich Laufzeitprobleme feststellen konnte, wenn der Nextcloud-Container startet, bevor die Datenbank im MariaDB-Container initialisiert war. Dieses Konstrukt ist nicht schön und ich bin für Verbesserungsvorschläge offen.

Zwischenfazit

Die Erstellung der Ansible-Rolle hat länger gedauert, als angenommen. Dies liegt nur zum Teil in meiner spärlichen Freizeit begründet. Einen größeren Einfluss darauf hatte die Dokumentation zum Nextcloud-Repository. Diese geht davon aus, dass man ein Dockerfile bzw. Docker-Compose verwendet. So war noch etwas Internet-Recherche erforderlich, um den Pod letztendlich ans Laufen zu bringen.

Dieser Artikel beschäftigte sich mit den Tag-1-Aufgaben, an deren Ende eine Nextcloud-Instanz ausgebracht wurde, welche an einen Reverse-Proxy angebunden werden kann.

Im nächsten Artikel gehe ich auf die Konfiguration des NGINX-Reverse-Proxy ein. Hierbei habe ich einige Überraschungen erlebt, welche mich an der Reife des Projekts [2] zweifeln lassen.

Quellen und weiterführende Links

  1. Nextcloud System Requirements — https://docs.nextcloud.com/server/latest/admin_manual/installation/system_requirements.html
  2. Nextcloud (Official Image) — https://hub.docker.com/_/nextcloud
  3. MariaDB (Official Image) — https://hub.docker.com/_/mariadb
  4. GitHub Tronde/ansible_role_deploy_nextcloud_with_mariadb_pod
  5. podman_pod – Manage Podman pods
  6. podman_container – Manage podman containers

Nextcloud im Container – Teil 1: Der Plan

14. Februar 2022 um 06:00

Dies ist der Beginn meines zweiten Container-Projekts. Nach Kanboard im Container möchte ich diesmal eine Nextcloud-Instanz als Container, zusammen mit einem Datenbank-Container, in einem Podman-Pod betreiben.

Da ein einzelner Artikel vermutlich zu lang wird, teile ich das Projekt in mehrere Artikel auf. Wie viele es genau werden, kann ich jetzt noch nicht sagen. Am Ende der Reihe werde ich hier eine Übersicht einführen und die einzelnen Teilen entsprechend miteinander verbinden.

In diesem ersten Teil geht es um meine Motivation, das eigentliche Ziel und den groben Plan.

Was Leser dieser Reihe erwartet

Ihr könnt mich durch diese Reihe begleiten und euch von meinen Erlebnissen und Erkenntnissen unterhalten lassen. Dabei dürft ihr nicht annehmen, dass es sich bei dem von mir beschriebenen Vorgehen um eine gute Praxis handelt. Hier gilt eher: Der Weg ist das Ziel.

Ihr seid herzlich eingeladen, die Artikel zu kommentieren und über das Vorgehen und Alternativen dazu zu diskutieren. Gern in der Kommentarsektion unter den jeweiligen Beiträgen oder als Artikel in euren eigenen Blogs.

Ich plane die Artikel im Wochenrhythmus, wenigstens monatlich, zu veröffentlichen. Bitte verzeiht, wenn es etwas unregelmäßig wird. Dies ist ein Hobby, dem nur begrenzt Zeit zur Verfügung steht.

Motivation

Bei Linux-Containern handelt es sich um eine Technologie, die gekommen ist, um zu bleiben. Sie hat bereits in vielen Branchen Fuß gefasst und immer mehr Projekte bieten ihre Anwendungen zusätzlich oder ausschließlich in Form von Containern an.

Als Sysadmin mittleren Alters werden mich Linux-Container sicher noch viele Jahre begleiten. Um praktische Erfahrungen mit dem Betrieb zu sammeln, möchte ich einige private Projekte in Containern betreiben.

Beruflich arbeite ich überwiegend mit RHEL. Red Hat engagiert sich stark in den Projekten Ansible und Podman, welche ich auch unter anderen Distributionen, wie z.B. Debian, einsetze. Ich möchte das Projekt als Chance nutzen, mein Wissen auch in diesen Werkzeugen zu festigen und auszubauen.

Ich spiele schon seit einiger Zeit mit dem Gedanken, wieder eine eigene Nextcloud-Instanz zu betreiben. Da auf dem zur Verfügung stehenden Server bereits eine Nextcloud-Instanz läuft und ich meine Anwendung von der bestehenden Instanz getrennt und möglichst losgelöst vom Betriebssystem betreiben möchte, habe ich mich entschieden, Nextcloud im Container zu betreiben.

Ziele

Ziel dieses Projekts sind das Deployment und der Betrieb einer Nextcloud-Instanz als Podman-Pod. Im Einzelnen sollen folgende Ziele erreicht werden:

  1. Entwicklung eines wiederverwendbaren Verfahrens zum Deployment einer Nextcloud im Container
  2. Persistente Speicherung von Konfigurations- und inhaltlichen Daten im Dateisystem des Hosts
  3. Konfiguration eines Reverse-Proxies (NGINX) für den Zugriff auf die Nextcloud-Instanz
  4. Konfiguration von Backup und Restore für Konfiguration und Inhalte der Nextcloud-Instanz
  5. Konfiguration und Test automatischer durch Ansible gesteuerter Updates

Umgebung

Für die Umsetzung des Projekts steht mir ein Virtual Private Server (VPS) mit genügend Ressourcen zur Verfügung. Dieser wird in einem Rechenzentrum in Deutschland betrieben. Auf diesem sind Debian Bullseye, NGINX, ein OpenSSH-Server, Podman 3.0.1 (rootless) und Python 3.9.2 installiert. Damit erfüllt dieses System die Voraussetzungen, um mit Ansible konfiguriert zu werden und Container ausführen zu können.

Ansible selbst läuft in meiner privaten Arbeitsumgebung auf meinem Debian-PC und einem Fedora-35-Notebook.

Methodik und verwendete Werkzeuge

Zu Beginn habe ich mich etwas in der Nextcloud-Dokumentation und den verfügbaren Nextcloud-Images belesen. Besagte Dokumentation sowie die der verwendeten Werkzeuge sind im folgenden Abschnitt verlinkt.

Um die oben formulierten Ziele zu erreichen, werde ich in einem Python Virtual Environment eine Ansible-Version installieren, mit der ich die Collection containers.podman nutzen kann. Hiermit werde ich eine Ansible-Rolle entwickeln, die ich wiederverwenden kann, um Nextcloud-Instanzen in einer rootless-Podman-Umgebung zu deployen. Die Ansible-Rolle wird anschließend auf meinem GitHub-Account veröffentlicht.

Die Konfiguration von NGINX und acme.sh für die TLS-Zertifikate erfolgt manuell.

Quellen und weiterführende Links

In diesem Abschnitt liste ich Links zu Artikeln und Dokumentationen auf, welche ich im Vorfeld gelesen habe und deren Kenntnis ich für die Umsetzung als nützlich erachte. Zur besseren Übersicht gliedere ich diese in die Unterabschnitte Hintergrundwissen, Dokumentation und Eigene Artikel.

Die weiteren Artikel dieser Reihe

Hintergrundwissen

Dokumentation

Eigene Artikel

❌
❌