---
title: Nextcloud Serverinstallation auf Almalinux 9.x und Debian 12
description: 
published: true
date: 2024-02-10T22:46:37.724Z
tags: 
editor: markdown
dateCreated: 2024-02-09T19:02:13.024Z
---

# Nextcloud Serverinstallation auf Almalinux 9.x und Debian 12 mit Docker Compose, Nginx als Reverse Proxy und Monitoring von Docker erstellen

**Version: 1.2 *2024-01-04 15:00 Simon Rieger***

1. [Almalinux herunterladen und installieren](#almalinux-herunterladen-und-installieren)
   1.1 [Almalinux herunterladen](#almalinux-herunterladen)
   1.2 [Debian herunterladen](#debian-herunterladen)
   1.3 [Hardwareanforderungen beachten](#hardwareanforderungen-beachten)
   1.4 [Zeitzone einstellen](#zeitzone-einstellen)
   1.5 [Root-Benutzer deaktivieren und nli-server Benutzer anlegen](#root-benutzer-deaktivieren-und-nli-server-benutzer-anlegen)
   1.6 [Netzwerkeinstellungen](#netzwerkeinstellungen)
   1.7 [Minimalinstallation durchführen](#minimalinstallation-durchfuehren)

2. [Distribution starten und Docker Compose einrichten](#distribution-starten-und-docker-compose-einrichten)
   2.1 [Installation unter Almalinux](#installation-unter-almalinux)
   2.2 [Installation unter Vsphere](#installation-unter-vsphere)
   2.3 [Installation unter Debian](#installation-unter-debian)
   2.4 [Docker-Daemon Service setzen](#docker-daemon-service-setzen)
   2.5 [Chrony einrichten](#chrony-einrichten)
   2.6 [Einrichten von mehreren Festplatten](#einrichten-von-mehreren-festplatten)

3. [Installieren von Nextcloud](#installieren-von-der-nextcloud)
   3.1 [Ordnerstrukturen anlegen](#ordnerstrukturen-anlegen)
   3.2 [Docker-Datei erstellen](#docker-datei-erstellen)
   3.3 [Nextcloud Server starten](#nextcloud-server-starten)
   3.4 [Verbindung zur Nextcloud per Port Forwarding herstellen](#verbindung-zur-nextcloud-per-port-forwarding-herstellen)
   3.5 [Reverse Proxy mit Nginx einrichten](#reverse-proxy-mit-nginx-einrichten)
   3.6 [Admin Benutzer für die Nextcloud anlegen](#admin-benutzer-fuer-die-nextcloud-anlegen)
   3.7 [Optimierungen](#optimierungen)

4. [Nextcloud Cron einrichten](#nextcloud-cron-einrichten)

5. [Nextcloud Container updaten](#nextcloud-container-updaten)
   5.1 [Neue Nextcloud Hauptversion verwendet](#neue-nextcloud-hauptversion-verwendet)
   5.2 [Docker Container updaten](#docker-container-updaten)

6. [Datenbank und Dateien von einer bereits vorhandenen Instanz migrieren](#datenbank-und-dateien-von-einer-bereits-vorhandenen-instanz-migrieren)
	6.1 [Weitere Optimierungen an der Datenbank nach der Migration](#weitere-optimierungen-an-der-datenbank-nach-der-migration) 

7. [Volltextsuche und OCR mit migrieren und installieren](#volltextsuche-und-ocr-mit-migrieren-und-installieren)
	7.1. [Anpassungen für ImageMagick](#anpassungen-für-imagemagick) 
	7.2. [Anpassung für Nextcloud](#anpassung-für-nextcloud)
	7.3. [Anpassungen für ElasticSearch](#anpassungen-für-elasticsearch)

8. [Quellen](#quellen)

- Hinweis: bei der nachfolgenden Anleitung ist der Domainname durch den Namen "webseite" auszutauschen.

## Almalinux herunterladen und installieren <a name="almalinux-herunterladen-und-installieren"></a>

Almalinux kann über folgenden Direktlink herunterladen werden:

[Link zum herunterladen von Almalinux](http://almalinux.mirrors.itworxx.de/9/isos/x86_64/AlmaLinux-9-latest-x86_64-minimal.iso)

oder Debian unter diesem Link:

[Link zum herunterladen von Debian](https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.1.0-amd64-netinst.iso)

Bitte darauf achten das man eine Festplatte mit mindesten 64 GB als Datenträger, 2 vCPUs und 4 GB RAM einbindet.

Anschließend muss die Zeitzone auf Europe/Berlin eingestellt werden.

Den Root-Benutzer kann man deaktivieren und als Benutzer "nli-server" mit Administratorrechten anlegen.

Falls das Netzwerk noch statisch eingerichtet werden muss, kann dies unter dem Reiter Netwerk eingerichtet werden, dabei kann auch noch der Hostname gesetzt werden, anschließend muss der Schriit noch extra bestätigt werden.

Bitte noch darauf achten das man eine Minimalinstallation ausgewählt hat und nicht eine normale mit der Standardsoftware von Almalinux, weil sonst der Gnome Desktop mit installiert wird und den brauchen wir nicht für einen Server.

## Distrubtion starten und docker compose einrichten <a name="distrubtion-starten-und-docker-compose-einrichten"></a>

Anschließend kann man die VM neustarten und sich per SSH auf dem eben bereits erstellen Benutzer verbinden.

### Installation unter Almalinux <a name="installation-unter-almalinux"></a>

Für die Installation von Docker Compose können wir die Offiziele Dokumentation von CentOS verwenden, da Almalinux mehr oder weniger ein Fork davon ist.

[Link für die Installation von Docker](https://docs.docker.com/engine/install/centos/)

Um die Packete des Systems upzudaten führen wir folgenden Kommando aus:

~~~
sudo dnf update
~~~

Wir integrieren das Repository nun erstmal in die yum Konfiguration.

~~~
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
~~~

Danach installieren wir Docker Compose mittels diesen Befehls hier.

~~~
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
~~~

### Installation unter Vsphere <a name="installation-unter-vsphere"></a>

Für die Installation unter Vsphere werden noch die Open-VM-tools benötigt.

Diese kann man mit folgendem Befehl installieren.

~~~
dnf install open-vm-tools
~~~

Nun muss der Befehl noch als Autostart eingerichtet werden mit folgendem Befehl:

~~~
systemctl enable --now vmtoolsd
~~~

und man kann dies nun überprüfen mit

~~~
systemctl status vmtoolsd
~~~

### Installation unter Debian <a name="installation-unter-debian"></a>

Für die Installation von Docker Compose können wir die Offiziele Dokumentation von Debian verwenden,

[Link für die Installation von Docker](https://docs.docker.com/engine/install/debian/)

Um die Packete des Systems upzudaten führen wir folgenden Kommando aus:

~~~
sudo apt update && sudo apt upgrade
~~~


~~~
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
~~~

### Docker-Daemon Service setzen <a name="docker-daemon-service-setzen"></a>

Und richten Docker als Systemd-Service ein und starten den auch gleichzeitig.

~~~
sudo systemctl enable --now docker
~~~

Anschließend testen wir mit folgendem Befehl, ob Docker ordnungsgemäß funktioniert.

~~~
sudo docker run hello-world
~~~

## Chrony einrichten <a name="chrony-einrichten"></a>

Um den Zeitserver einzurichten bitte noch folgende Befehle als ROOT ausführen:

~~~
dnf install chrony
~~~

Crony als Systemweiten Service einrichten

~~~
systemctl enable --now chronyd
~~~

die Firewall noch ergänzen

~~~
firewall-cmd --permanent --add-service=ntp
firewall-cmd --reload
~~~

und danach nochmal neustarten

~~~
systemctl restart chronyd
~~~

## Einrichten von mehreren Festplatten <a name="einrichten-von-mehreren-festplatten"></a>

Wenn man die Daten getrennt von dem Betriebssytem haben möchte, formatiert man erstmal die neue Festplatte mit fdisk. Mit folgendem Befehl sehen wir uns die verfügbaren Festplatten genauer an.

~~~
fdisk -l

Disk /dev/sda: 1 TiB, 1099511627776 bytes, 2147483648 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes


Disk /dev/sdb: 64 GiB, 68719476736 bytes, 134217728 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 8A25CA1F-8A16-471D-B928-C0EF5BD7B174

Device       Start       End   Sectors  Size Type
/dev/sdb1     2048   1230847   1228800  600M EFI System
/dev/sdb2  1230848   3327999   2097152    1G Linux filesystem
/dev/sdb3  3328000 134215679 130887680 62.4G Linux LVM


Disk /dev/mapper/almalinux-root: 37.63 GiB, 40407924736 bytes, 78921728 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes


Disk /dev/mapper/almalinux-swap: 6.4 GiB, 6874464256 bytes, 13426688 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes


Disk /dev/mapper/almalinux-home: 18.38 GiB, 19730006016 bytes, 38535168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
~~~

Um **/dev/sdb** handelt es sich die Systempartition, deswegen wählen wir nun mit fdisk die Festplatte **/dev/sda** aus.

~~~
[root@SST-S-440 ~]# fdisk /dev/sda

Welcome to fdisk (util-linux 2.37.4).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xbbcd0e1c.

Command (m for help): p
Disk /dev/sda: 1 TiB, 1099511627776 bytes, 2147483648 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xbbcd0e1c

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (1-4, default 1):
First sector (2048-2147483647, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-2147483647, default 2147483647):

Created a new partition 1 of type 'Linux' and of size 1024 GiB.

Command (m for help):


Command (m for help): p

Disk /dev/sda: 1 TiB, 1099511627776 bytes, 2147483648 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xbbcd0e1c

Device     Boot Start        End    Sectors  Size Id Type
/dev/sda1        2048 2147483647 2147481600 1024G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
~~~

Und formatiert sie anschließend mit ext4.

~~~
[root@SST-S-440 ~]# mkfs.ext4 /dev/sda1
mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: done
Creating filesystem with 268435200 4k blocks and 67108864 inodes
Filesystem UUID: 4a3937fd-26b9-4dd2-9937-d441569a5c5e
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000, 214990848

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
~~~

Damit sie beim nächsten Start automatisch gemounted wird, trägt man die Festplatte noch in die Fstab ein. Davor müssen wir ersteinmal die UUID der Festplatte herausfinden.

~~~
blkid
~~~

und danach denn Ordner erstellen und die /etc/fstab bearbeiten.

~~~
mkdir -p /opt/data
nano /etc/fstab
~~~

mit folgendem Inhalt ergänzen:

~~~
UUID="4a3937fd-26b9-4dd2-9937-d441569a5c5e" /opt/data ext4 defaults 0 0
~~~

und anschließend mit STRG + X und dann Y abspeicher und den automatischen Mount ausführen.

~~~
mount -a
~~~

## Installieren von der Nextcloud <a name="installieren-von-der-nextcloud"></a>

Zuerst legen wir uns passende Ordner-Strukturen an.

~~~
mkdir -p /opt/containers/nextcloud/{db,app,daten}
~~~

und Optional falls man die Daten von Nextcloud wo anders gespeichert haben möchte.

~~~
mkdir -p /opt/data/nextcloud/daten
~~~

Um den Texteditor Nano und Vim zu installieren, benutzt ihr folgenden Befehl.

~~~
sudo dnf install nano vim bash-completion
~~~

oder für Debian:

~~~
sudo apt install nano vim bash-completion
~~~

Nun legen wir die eigentliche Docker Datei an. Hierfür habe ich mir die offizielle Nextcloud Compose genommen und etwas modifiziert. Die Datei könnt ihr mit dem Editor eurer Wahl bearbeiten.

[Offizielle Nextcloud Compose Anleitung](https://hub.docker.com/_/nextcloud/)

~~~
nano /opt/containers/nextcloud/docker-compose.yml
~~~

docker-compose.yml

~~~
version: '3.3'

services:
  nextcloud-db:
    image: mariadb:10.6
    container_name: nextcloud-db
    restart: always
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=rootpass
      - MYSQL_PASSWORD=userpass
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_INITDB_SKIP_TZINFO=1
      - MARIADB_AUTO_UPGRADE=1
    networks:
      - default
    ports:
      - 127.0.0.1:3306:3306

  nextcloud-redis:
    image: redis:alpine
    container_name: nextcloud-redis
    hostname: nextcloud-redis
    restart: always
    command: redis-server --requirepass redispass
    networks:
      - default

  nextcloud-app:
    image: nextcloud:27
    container_name: nextcloud-app
    restart: always
    ports:
      - 8080:80
    depends_on:
      - nextcloud-db
      - nextcloud-redis
    volumes:
      - ./app:/var/www/html
      - /opt/data/nextcloud/daten:/var/www/html/data
    environment:
      - MYSQL_PASSWORD=userpass
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=nextcloud-db
      - TRUSTED_PROXIES=10.161.24.10/24
      #- OVERWRITEPROTOCOL=https
      #- OVERWRITECLIURL=https://cloud.webseite.com
      #- OVERWRITEHOST=cloud.webseite.com
      - REDIS_HOST=nextcloud-redis
      - REDIS_HOST_PASSWORD=redispass
      - PHP_MEMORY_LIMIT=2G
      - PHP_UPLOAD_LIMIT=2G
      - NEXTCLOUD_TRUSTED_DOMAINS=10.161.24.1
    networks:
      - default
~~~

Die Umgebgungsvariablen OVERWRITEPROTOCOL, OVERWRITECLIURL und OVERWRITEHOST sollten erst gesetzt worden sein, wenn der Reverse Proxy mit SSL-Zertifikat bereits eingerichtet wurde.

Falls eventuell das automatische anlegen der Datenbank, oder die Datenbank nicht von der Nextcloud automatisch übernommen wurde kann mit dem Tool *dos2unix* der Text in das Unix Format konventiert werden.

## Nextcloud Server starten <a name="nextcloud-server-starten"></a>

Den Server startet ihr wie gewohnt mit folgendem Befehl:

~~~
docker compose -f /opt/containers/nextcloud/docker-compose.yml up -d
~~~

Falls Probleme auftreten solltet, wechselt in das Verzeichnis wo die Docker Compose Datei liegt und für einen dieser folgenden Befehlen aus.

~~~
cd /opt/containers/nextcloud/

docker compose logs nextcloud-app
docker compose logs nextcloud-db
docker compose logs nextcloud-redis
~~~

## Verbindung zur Nextcloud per Port Forwarding herstellen <a name="verbindung-zur-nextcloud-per-port-forwarding-herstellen"></a>

Falls ihr noch nicht auf eure Nextcloud zugreifen könnt, weil sie von einer Firewall blockiert wird, oder auf einem anderem Server liegt könnt ihr mittels Port Forwarding drauf zugreifen.

Unter Linux verwendet ihr folgenden Befehl:

~~~
ssh -L 8080:127.0.0.1:8080 server -N
~~~

Unter Putty fügt ihr fügt ihr folgendes im Connection -> SSH -> Tunnels reiter hinzu.

![2023-07-14-150559_464x454_scrot.png](/_ressources_nextcloud-serverinstallation/2023-07-14-150559_464x454_scrot.png)

## Reverse Proxy mit Nginx einrichten <a name="reverse-proxy-mit-nginx-einrichten"></a>

Den Reverse Proxy Nginx installieren wir lokal auf das System ohne Docker zu verwenden.
Für das Zertifikat benutzen wir Let´s Encrypt und automatisieren es mit Certbot.

Installieren können wir die Packete mit:

~~~
sudo dnf install epel-release

sudo dnf install certbot python3-certbot-nginx nginx
~~~

oder für Debian:

~~~
sudo apt install python3-certbot-nginx nginx
~~~

und überprüfen danach ob nun Certbot vorhanden ist.

~~~
certbot --version
~~~

Für Almalinux fügen wir noch ein paar Firewall-Regeln hinzu.

~~~
sudo firewall-cmd --permanent --add-port=80/tcp --zone=public
sudo firewall-cmd --permanent --add-port=443/tcp --zone=public
sudo firewall-cmd --reload

setsebool -P httpd_can_network_connect 1

sudo cat /var/log/audit/audit.log | grep nginx | grep denied

sudo cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M mynginx
sudo semodule -i mynginx.pp

setsebool -P httpd_can_network_relay 1
~~~

Dann erstellen wir die Konfiguration des Reverse Proxys. Das geht am einfachsten mit dem Tool von DigitalOcean.

Ich habe hier bereits eine vorkonfiguriete Konfiguration erstellt, dort müsst ihr einfach nur den Domain-Namen ändern.

*Was noch zu beachten ist, das man noch in der Konfiguration bei Debian den Benutzer und die Gruppe für den zu benötigten User noch anpasst.*

[Vorkonfigurierte Nginx Konfiguration](https://www.digitalocean.com/community/tools/nginx?domains.0.server.domain=cloud.webseite.com&domains.0.server.documentRoot=&domains.0.server.redirectSubdomains=false&domains.0.https.letsEncryptEmail=support%40webseite.com&domains.0.php.php=false&domains.0.reverseProxy.reverseProxy=true&domains.0.reverseProxy.proxyPass=http%3A%2F%2F127.0.0.1%3A8080&domains.0.routing.root=false&domains.0.logging.accessLogPath=%2Fvar%2Flog%2Fnginx%2Fcloud.webseite.com-access.log&domains.0.logging.redirectAccessLog=true&domains.0.logging.errorLogPath=%2Fvar%2Flog%2Fnginx%2Fcloud.webseite.com-error.log&domains.0.logging.redirectErrorLog=true&global.nginx.user=nginx&global.nginx.clientMaxBodySize=0&global.app.lang=de)

Ihr drückt dann einmal auf Als Base64 kopieren und follgt dementsprechend die Anleitung.

![2023-07-14-155745_1350x695_scrot.png](/_ressources_nextcloud-serverinstallation/2023-07-14-155745_1350x695_scrot.png)

Hier nochmal die vollständige Anleitung.

kopiere einen Base64 String der komprimierten Konfiguration, füge ihn auf der Kommandozeile deines Servers ein und führe ihn aus.

Wechsle in das NGINX Konfigurationsverzeichnis deines Servers:
~~~
cd /etc/nginx
~~~

Erstelle ein Backup deiner aktuellen NGINX Konfiguration:
~~~
tar -czvf nginx_$(date +'%F_%H-%M-%S').tar.gz nginx.conf sites-available/ sites-enabled/ nginxconfig.io/
~~~

Entpacke das komprimierte Konfigurationsverzeichnis mittels tar:
~~~
tar -xzvf nginxconfig.io-cloud.webseite.com.tar.gz | xargs chmod 0644
~~~

Erzeuge Diffie-Hellman Schlüssel indem du diesen Befehl auf deinem Server ausführst:
~~~
openssl dhparam -out /etc/nginx/dhparam.pem 2048
~~~

Erstelle ein ACME-Challenge Verzeichnis (für Let's Encrypt):
~~~
mkdir -p /var/www/_letsencrypt
chown nginx /var/www/_letsencrypt
~~~

Kommentiere SSL-relevante Direktiven in deiner Konfiguration aus:
~~~
sed -i -r 's/(listen .*443)/\1; #/g; s/(ssl_(certificate|certificate_key|trusted_certificate) )/#;#\1/g; s/(server \{)/\1\n    ssl off;/g' /etc/nginx/sites-available/cloud.webseite.com.conf
~~~

This command will add a temporary ssl off directive to ensure that SSL directives are not active. This may cause NGINX to emit a warning, which is safe to ignore. The directive will be removed once Certbot is configured.

Führe einen reload deines NGINX Server aus:
~~~
sudo nginx -t && sudo systemctl reload nginx
~~~

Erhalte SSL Zertifikate von Let's Encrypt mittels Certbot:
~~~
certbot certonly --webroot -d cloud.webseite.com --email support@webseite.com -w /var/www/_letsencrypt -n --agree-tos --force-renewal
~~~

Kommentiere SSL-relevante Direktiven in deiner Konfiguration ein:
~~~
sed -i -r -z 's/#?; ?#//g; s/(server \{)\n    ssl off;/\1/g' /etc/nginx/sites-available/cloud.webseite.com.conf
~~~

Führe einen reload deines NGINX Server aus:
~~~
sudo nginx -t && sudo systemctl reload nginx
~~~

Konfiguriere Certbot um NGINX neu zu laden, wenn die Zertifikate erfolgreich erneuert wurden:
~~~
echo -e '#!/bin/bash\nnginx -t && systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh
sudo chmod a+x /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh
~~~

Jetzt gehts los! 🎉

Lade NGINX neu, um deine neue Konfiguration zu verwenden:
~~~
sudo nginx -t && sudo systemctl reload nginx
~~~

Und damit das zukünftige neuerstellen der Zertifikate möglich ist
~~~
systemctl enable --now certbot-renew.timer
~~~

Dann modifizieren wir noch die cloud.webseite.com.conf im nginx Verzeichnis.
~~~
nano /etc/nginx/sites-available/cloud.webseite.com.conf
~~~

cloud.webseite.com.conf

Wir fügen noch diese Einträge dort hinzu:

~~~
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

    location /.well-known/carddav {
        return 301 $scheme://$host/remote.php/dav;
    }

    location /.well-known/caldav {
        return 301 $scheme://$host/remote.php/dav;
    }
~~~

Und dokumentieren schließlich diesen Bereich aus:

~~~
    include                 nginxconfig.io/security.conf;
~~~

So das es schließlich so aussieht:

~~~
server {
    listen                  443 ssl http2;
    listen                  [::]:443 ssl http2;
    server_name             cloud.webseite.com;

    # SSL
    ssl_certificate         /etc/letsencrypt/live/cloud.webseite.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/cloud.webseite.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/cloud.webseite.com/chain.pem;

    # security
    #include                 nginxconfig.io/security.conf;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

    # logging
    access_log              /var/log/nginx/cloud.webseite.com-access.log combined buffer=512k flush=1m;
    error_log               /var/log/nginx/cloud.webseite.com-error.log warn;

    # reverse proxy
    location / {
        proxy_pass            http://127.0.0.1:8080;
        proxy_set_header Host $host;
        #proxy_set_header X-Real-IP $remote_addr;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        #proxy_set_header X-Forwarded-Proto $scheme;
        include               nginxconfig.io/proxy.conf;
    }

    location /.well-known/carddav {
        return 301 $scheme://$host/remote.php/dav;
    }

    location /.well-known/caldav {
        return 301 $scheme://$host/remote.php/dav;
    }

    # additional config
    include nginxconfig.io/general.conf;
}

# HTTP redirect
server {
    listen      80;
    listen      [::]:80;
    server_name cloud.webseite.com;

    # logging
    access_log  /var/log/nginx/cloud.webseite.com-access.log combined buffer=512k flush=1m;
    error_log   /var/log/nginx/cloud.webseite.com-error.log warn;
    include     nginxconfig.io/letsencrypt.conf;

    location / {
        return 301 https://cloud.webseite.com$request_uri;
    }
}
~~~

Und das war es eigentlich schon, wichtig dabei ist das euer Server als A-Record im Domainbestellsystem hinterlegt worden ist.

## Admin Benutzer für die Nextcloud anlegen <a name="admin-benutzer-für-die-nextcloud-anlegen"></a>

Wir öffnen dann die Webseite zur Nextcloud: [Link zur Nextcloud](http://127.0.0.1:8080)

Wichtig dabei zu beachten ist, wenn der Admin Benutzer angelegt ist, ist nur noch ein Zugriff über den Reverse Proxy mit Nginx auf dem *OVERWRITECLIURL* möglich der dann im vorherigen Schritt eingerichtet wurde. Deswegen ist es auch Sinnvoll erst diesen Schritt erst auszuführen wenn der Nginx auch komplett läuft und auf die FQDN zugreifen kann.

## Optimierungen <a name="optimierungen"></a>

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.

<img width="780" height="312" src="/_ressources_nextcloud-serverinstallation/nextcloud23-001_db8de1a1354945f5adbe65104acd5753.png"/>(https://goneuland.de/wp-content/uploads/2022/01/nextcloud23-001.png)

### Standardtelefonregion festlegen <a name="standardtelefonregion-festlegen"></a>

Dazu öffnet ihr folgende Datei:

~~~
nano /opt/containers/nextcloud/app/config/config.php
~~~

Fügt nun folgende Zeile hinzu:

~~~
 'default_phone_region' => 'DE',
~~~

Dies setzt die Standardregion auf Deutschland. Beispiele dazu findet ihr [hier](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html). Nun könnt ihr die Datei wieder schließen.

Bei mir sieht es dann so aus:

~~~
  'dbuser' => 'nextcloud',
  'dbpassword' => 'test',
  'installed' => true,
  'default_phone_region' => 'DE',
);
~~~


## Container neu starten <a name="container-neu-starten"></a>

Nun starten wir Nextcloud neu um sicherzugehen, dass alle Einstellungen übernommen werden.

~~~
docker compose -f /opt/containers/nextcloud/docker-compose.yml down

docker compose -f /opt/containers/nextcloud/docker-compose.yml up -d
~~~

Nun sollte es so aussehen:

<img width="780" height="169" src="/_ressources_nextcloud-serverinstallation/nextcloud23-004_b4e01d5f29084214b2aefbd27341b989.png"/>(https://goneuland.de/wp-content/uploads/2022/01/nextcloud23-004.png)

## Nextcloud Cron einrichten <a name="nextcloud-cron-einrichten"></a>

Nun fügen wir auf unserem Server noch einen Cron Eintrag hinzu. Dieser bewirkt, dass Nextcloud alle 5 Minuten die Hintergrundjobs abarbeitet. Um Cron zu starten gebt ihr folgendes ein:

~~~
crontab -e
~~~

Beim ersten Start erscheint nun folgende Meldung. Wählt hier “1” aus.

~~~
no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.tiny

Choose 1-2 [1]: 1
~~~

Hier fügt ihr nun folgende Zeile hinzu:

~~~
*/5 * * * * docker exec -u www-data nextcloud-app-1 php cron.php
~~~

Diese Zeile bewirkt, dass euer Server alle 5 Minuten die “cron.php” Datei ausführt in eurem Nextcloud Container.

Nachdem ihr dies eingerichtet habt, könnt ihr dies auch kontrollieren. Geht dazu in eure Nextcloud als Administrator. Wählt dann bei Hintergrundaufgaben noch “Cron (Empfohlen)”. Hier solltet ihr nun folgendes in den Einstellungen sehen. Wichtig ist, dass die “Letzte Aufgabe ausgeführt…” maximal 5 Minuten sein sollte. Wenn dies so ist, dann funktioniert alles.

<img width="780" height="568" src="/_ressources_nextcloud-serverinstallation/nextcloud-cron_3b36c672e578432d900beb8deed5ccf1.png"/>(https://goneuland.de/wp-content/uploads/2022/09/nextcloud-cron.png)

## Nextcloud Container updaten <a name="nextcloud-container-updaten"></a>

Man kann den Nextcloud Container Updaten, indem man in folgendes Verzeichnis wechselt und die docker-compose.yml bearbeitet:

~~~
cd /opt/containers/nextcloud
nano docker-compose.yml
~~~

Falls man bei dieser Hauptversion bleiben möchte, dann bitte den nächsten Schritt überspringen.

## Neue Nextcloud Hauptversion verwendet <a name="neue-nextcloud-hauptversion-verwendet"></a>

Wichtig dabei zu beachten, wenn man noch die Hauptversion updaten will auch den Tag von Version zu Version hochzuzählen.

~~~
nextcloud-app:
    image: nextcloud:27
~~~

In diesem Falle die Version nextcloud:27 zu nextcloud:28, aber nicht von Version 27 zu 29.

Eventuell muss man auch die Version der MariaDB Datenbank hochzählen, falls die neue Version die ältere Datenbank nicht mehr unterstützt wird.

Unter folgendem [Link](https://hub.docker.com/_/nextcloud/tags) kann man sich die Tags zu den Nextcloud Versionen anzeigen lassen.

## Docker Container updaten <a name="docker-container-updaten"></a>

Um nun die neue Version von Nextcloud herunterzuladen machen wir erst einmal ein Backup von den Container, da Backups wichtig und richtig sind.

~~~
cd /opt/containers/
tar -czf nextcloud-backup-$(date "+%F").tar.gz nextcloud/
~~~

nun müssen folgende Befehle ausgeführt werden damit die neuen Images gepulled werden und anschließend ausgeführt werden.

~~~
cd nextcloud
docker compose pull
docker compose up -d
~~~

## Datenbank und Dateien von einer bereits vorhandenen Instanz migrieren <a name="datenbank-und-dateien-von-einer-bereits-vorhandenen-instanz-migrieren"></a>

Hierdurch werden die Nextcloud Datenbank vom alten System gedumpt:

~~~
mysqldump --single-transaction --default-character-set=utf8mb4 -h 127.0.0.1 -u root -p nextcloud > NextCloud-dump-2023-07-24.sql
~~~

und anschließend auf das neue System hinzugefügt:

~~~
mysql -h 127.0.0.1 -u nextcloud -p nextcloud < NextCloud-dump.sql
./occ upgrade
~~~

~~~
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
Setting log level to debug
Updating database schema
Updated database
Updating <files> ...
Updated <files> to 1.22.0
Updating <activity> ...
Updated <activity> to 2.19.0
Updating <circles> ...
Updated <circles> to 27.0.1
Updating <cloud_federation_api> ...
Updated <cloud_federation_api> to 1.10.0
Updating <dav> ...

Fix broken values of calendar objects

 Done
    0/0 [->--------------------------]   0%
Clean up old calendar subscriptions from deleted users that were not cleaned-up
 Done
    0/0 [----->----------------------]   0%
Updated <dav> to 1.27.0
Updating <encryption> ...
Updated <encryption> to 2.15.0
Updating <files_sharing> ...
Updated <files_sharing> to 1.19.0
Updating <files_trashbin> ...
Updated <files_trashbin> to 1.17.0
Updating <files_versions> ...
Updated <files_versions> to 1.20.0
Updating <sharebymail> ...
Updated <sharebymail> to 1.17.0
Updating <workflowengine> ...
Updated <workflowengine> to 2.9.0
Updating <admin_audit> ...
Updated <admin_audit> to 1.17.0
Updating <comments> ...
Updated <comments> to 1.17.0
Updating <notifications> ...
Updated <notifications> to 2.15.0
Updating <systemtags> ...
Updated <systemtags> to 1.17.0
Updating <theming> ...
Migrate old user accessibility config
 Done
  471/471 [============================] 100%
Updated <theming> to 2.2.0
Updating <bruteforcesettings> ...
Updated <bruteforcesettings> to 2.7.0
Updating <contactsinteraction> ...
Updated <contactsinteraction> to 1.8.0
Updating <dashboard> ...
Updated <dashboard> to 7.7.0
Updating <federatedfilesharing> ...
Updated <federatedfilesharing> to 1.17.0
Updating <files_pdfviewer> ...
Updated <files_pdfviewer> to 2.8.0
Updating <files_rightclick> ...
Updated <files_rightclick> to 1.6.0
Updating <logreader> ...
Updated <logreader> to 2.12.0
Updating <photos> ...
Updated <photos> to 2.3.0
Updating <privacy> ...
Updated <privacy> to 1.11.0
Updating <provisioning_api> ...
Updated <provisioning_api> to 1.17.0
Updating <recommendations> ...
Updated <recommendations> to 1.6.0
Updating <serverinfo> ...
Updated <serverinfo> to 1.17.0
Updating <settings> ...
Updated <settings> to 1.9.0
Updating <twofactor_backupcodes> ...
Updated <twofactor_backupcodes> to 1.16.0
Updating <updatenotification> ...
Updated <updatenotification> to 1.17.0
Updating <user_status> ...
Updated <user_status> to 1.7.0
Updating <viewer> ...
Updated <viewer> to 2.1.0
Updating <weather_status> ...
Updated <weather_status> to 1.7.0
Starting code integrity check...
Finished code integrity check
Update successful
Maintenance mode is kept active
Resetting log level
~~~

Und für die Dateien einmal die in den Nextcloud Data-Verzeichnis ableget wurde mit folgendem Befehl die Rechte anlegen:

~~~
cd /opt/data/nextcloud/
cp -Rv /opt/extern-data/nextcloud/data/* .
chown -cRv www-data:www-data .
~~~

und anschließend die Dateien neu einscannen:

~~~
docker compose exec --user www-data -it nextcloud-app /bin/bash
./occ files:scan --all
~~~

## Weitere Optimierungen an der Datenbank nach der Migration <a name="weitere-optimierungen-an-der-datenbank-nach-der-migration"></a>

Falls noch Probleme im Status mit der Datenbank vorhanden sind, sind diese Befehle auszuführen um die Tabellen zu reparieren:

~~~
[root@SST-S-440 nextcloud]# docker compose exec --user www-data -it nextcloud-app /bin/bash
www-data@bbb02abc82f0:~/html$ ./occ db:add-missing-indices
~~~

Das Ergebniss sollte dann so aussehen:

~~~
Check indices of the share table.
Check indices of the filecache table.
Adding additional size index to the filecache table, this can take some time...
Filecache table updated successfully.
Adding additional size index to the filecache table, this can take some time...
Filecache table updated successfully.
Adding additional path index to the filecache table, this can take some time...
Filecache table updated successfully.
Adding additional parent index to the filecache table, this can take some time...
Filecache table updated successfully.
Check indices of the twofactor_providers table.
Check indices of the login_flow_v2 table.
Check indices of the whats_new table.
Check indices of the cards table.
Check indices of the cards_properties table.
Check indices of the calendarobjects_props table.
Check indices of the schedulingobjects table.
Check indices of the oc_properties table.
Adding properties_pathonly_index index to the oc_properties table, this can take some time...
oc_properties table updated successfully.
Check indices of the oc_jobs table.
Adding job_lastcheck_reserved index to the oc_jobs table, this can take some time...
oc_properties table updated successfully.
Check indices of the oc_direct_edit table.
Adding direct_edit_timestamp index to the oc_direct_edit table, this can take some time...
oc_direct_edit table updated successfully.
Check indices of the oc_preferences table.
Adding preferences_app_key index to the oc_preferences table, this can take some time...
oc_properties table updated successfully.
Check indices of the oc_mounts table.
Adding mounts_user_root_path_index index to the oc_mounts table, this can take some time...
oc_mounts table updated successfully.
Check indices of the oc_systemtag_object_mapping table.
Adding systag_by_tagid index to the oc_systemtag_object_mapping table, this can take some time...
oc_systemtag_object_mapping table updated successfully.
Adding additional textstep_session index to the oc_text_steps table, this can take some time...
oc_text_steps table updated successfully.
~~~

Und noch ein weiterer Befehl:

~~~
www-data@bbb02abc82f0:~/html$ ./occ db:add-missing-primary-keys
~~~

Und weitere Anpassungen an der Datenbank mit:

~~~
mysql -h 127.0.0.1 -u nextcloud -p nextcloud
~~~

und folgenden Befehlen:

~~~
use nextcloud

DROP TABLE oc_textprocessing_tasks;
DROP TABLE oc_open_local_editor;
~~~

Dessen Ausgabe so aussehen sollte:

~~~
Check primary keys.
Adding primary key to the federated_reshares table, this can take some time...
federated_reshares table updated successfully.
Adding primary key to the systemtag_object_mapping table, this can take some time...
systemtag_object_mapping table updated successfully.
Adding primary key to the comments_read_markers table, this can take some time...
comments_read_markers table updated successfully.
Adding primary key to the collres_resources table, this can take some time...
collres_resources table updated successfully.
Adding primary key to the collres_accesscache table, this can take some time...
collres_accesscache table updated successfully.
Adding primary key to the filecache_extended table, this can take some time...
filecache_extended table updated successfully.
~~~

Anschließend noch diesen Befehl ausführen und zusätzlich bestätigen:

~~~
www-data@bbb02abc82f0:~/html$ ./occ db:convert-filecache-bigint
Following columns will be updated:

* federated_reshares.share_id
* filecache.mtime
* filecache.storage_mtime
* filecache_extended.fileid
* files_trash.auto_id
* mounts.storage_id
* mounts.root_id
* mounts.mount_id
* share_external.id
* share_external.parent

This can take up to hours, depending on the number of files in your instance!
Continue with the conversion (y/n)? [n] y
~~~

## Volltextsuche und OCR mit migrieren und installieren <a name="volltextsuche-und-ocr-mit-migrieren-und-installieren"></a>

Folgenden Text der Docker Compose Datei hinzufügen:

~~~
  elasticsearch:
    build: ./elasticsearch
    container_name: elasticsearch
    restart: unless-stopped
    environment:
      - discovery.type=single-node
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./elasticsearch/data:/usr/share/elasticsearch/data
    networks:
      - default
~~~

und folgendes beim Nextcloud ändern bzw. ausdokumentieren:

~~~
# image: nextcloud:27
build: ./nextcloud-app
~~~

### Anpassungen für ImageMagick <a name="anpassungen-für-imagemagick"></a>

ImageMagick wird verwendet um aus PDF Seiten Fotos zu erstellen. Diese können später per OCR erkannt werden. Es gibt derzeit wohl ein kleines Hindernis ([Github Quelle](https://github.com/nextcloud/files_fulltextsearch/issues/100)) weshalb wir hier noch eine extra Anpassung vornehmen müssen.

~~~
mkdir /opt/containers/nextcloud/imagemagick/
nano /opt/containers/nextcloud/imagemagick/policy.xml
~~~

Inhalt:

~~~
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policymap [
  <!ELEMENT policymap (policy)+>
  <!ATTLIST policymap xmlns CDATA #FIXED ''>
  <!ELEMENT policy EMPTY>
  <!ATTLIST policy xmlns CDATA #FIXED '' domain NMTOKEN #REQUIRED
    name NMTOKEN #IMPLIED pattern CDATA #IMPLIED rights NMTOKEN #IMPLIED
    stealth NMTOKEN #IMPLIED value CDATA #IMPLIED>
]>

<policymap>
  <!-- <policy domain="system" name="shred" value="2"/> -->
  <!-- <policy domain="system" name="precision" value="6"/> -->
  <!-- <policy domain="system" name="memory-map" value="anonymous"/> -->
  <!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
  <!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
  <policy domain="resource" name="memory" value="256MiB"/>
  <policy domain="resource" name="map" value="512MiB"/>
  <policy domain="resource" name="width" value="16KP"/>
  <policy domain="resource" name="height" value="16KP"/>
  <!-- <policy domain="resource" name="list-length" value="128"/> -->
  <policy domain="resource" name="area" value="128MB"/>
  <policy domain="resource" name="disk" value="1GiB"/>
  <!-- <policy domain="resource" name="file" value="768"/> -->
  <!-- <policy domain="resource" name="thread" value="4"/> -->
  <!-- <policy domain="resource" name="throttle" value="0"/> -->
  <!-- <policy domain="resource" name="time" value="3600"/> -->
  <!-- <policy domain="coder" rights="none" pattern="MVG" /> -->
  <!-- <policy domain="module" rights="none" pattern="{PS,PDF,XPS}" /> -->
  <!-- <policy domain="delegate" rights="none" pattern="HTTPS" /> -->
  <!-- <policy domain="path" rights="none" pattern="@*" /> -->
  <!-- <policy domain="cache" name="memory-map" value="anonymous"/> -->
  <!-- <policy domain="cache" name="synchronize" value="True"/> -->
  <!-- <policy domain="cache" name="shared-secret" value="passphrase" stealth="true"/> -->
  <!-- <policy domain="system" name="pixel-cache-memory" value="anonymous"/> -->
  <!-- <policy domain="system" name="shred" value="2"/> -->
  <!-- <policy domain="system" name="precision" value="6"/> -->
  <!-- not needed due to the need to use explicitly by mvg: -->
  <!-- <policy domain="delegate" rights="none" pattern="MVG" /> -->
  <!-- use curl -->
  <policy domain="delegate" rights="none" pattern="URL" />
  <policy domain="delegate" rights="none" pattern="HTTPS" />
  <policy domain="delegate" rights="none" pattern="HTTP" />
  <!-- in order to avoid to get image with password text -->
  <policy domain="path" rights="none" pattern="@*"/>
  <!-- disable ghostscript format types -->
  <policy domain="coder" rights="none" pattern="PS" />
  <policy domain="coder" rights="none" pattern="PS2" />
  <policy domain="coder" rights="none" pattern="PS3" />
  <policy domain="coder" rights="none" pattern="EPS" />
  <policy domain="coder" rights="read | write" pattern="PDF" />
  <policy domain="coder" rights="none" pattern="XPS" />
</policymap>
~~~

### Anpassung für Nextcloud <a name="anpassung-für-nextcloud"></a>

In der aktuellen Version muss noch GhostScript in den Nextcloud Container hinzugefügt werden. Daher müssen wir uns den Container selbst bauen.

~~~
mkdir /opt/containers/nextcloud/nextcloud-app/
nano /opt/containers/nextcloud/nextcloud-app/Dockerfile
~~~

Inhalt:

~~~
FROM nextcloud
RUN apt-get update
RUN apt-get install -y ghostscript
RUN apt install -y libmagickwand-dev --no-install-recommends
RUN pecl install imagick; exit 0
RUN docker-php-ext-enable imagick
RUN rm -rf /var/lib/apt/lists/*
~~~

### Anpassungen für ElasticSearch <a name="anpassungen-für-elasticsearch"></a>

Um die OCR Erkennung in ElasticSearch zu realisieren benötigen wir noch das Programm [Tesseract](https://tesseract-ocr.github.io/tessdoc/4.0-Docker-Containers.html). Daher müssen wir uns den ElasticSearch Container auch selbst bauen.

~~~
mkdir /opt/containers/nextcloud/elasticsearch/
nano /opt/containers/nextcloud/elasticsearch/Dockerfile
~~~

Inhalt:

~~~
FROM elasticsearch:7.17.10
RUN /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch ingest-attachment
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y tesseract-ocr tesseract-ocr-deu tesseract-ocr-eng
~~~

Hier könnt ihr noch weitere Sprachen installieren zur OCR Erkennung. Eine Übersicht alles Sprachen findet ihr [hier](https://download.opensuse.org/repositories/home:/Alexander_Pozdnyakov/CentOS_8/noarch/).

Folgende Plugins müssen installiert werden:

![d5dbd79976bd4b09aca92ff565795085.png](/_ressources_nextcloud-serverinstallation/d5dbd79976bd4b09aca92ff565795085.png)

Und folgende Einstellungen gesetzt werden:

![81cca748e213ab2eb7c78c4c3b6f9989.png](/_ressources_nextcloud-serverinstallation/81cca748e213ab2eb7c78c4c3b6f9989.png)

Nach der DB-Migration folgende Befehle ausführen.

~~~
docker compose exec --user www-data -it app /bin/bash

./occ fultextsearch:migration:24
./occ fulltextsearch:index
./occ fulltextsearch:live
~~~

Das Ergebniss müsste schließlich so aussehen:

![2023-11-15-114235_grim.png](/_ressources_nextcloud-serverinstallation/2023-11-15-114235_grim.png)

## Quellen <a name="quellen"></a>

https://hub.docker.com/_/nextcloud/

https://teqqy.de/nextcloud-docker-tutorial-step-by-step-zum-erfolg/

https://goneuland.de/nextcloud-server-mit-docker-compose-und-traefik-installieren/

https://goneuland.de/nextcloud-server-mit-elasticsearch-collabora-office-docker-compose-und-traefik-installieren/

https://wiki.ubuntuusers.de/SSH/#SSH-Tunnel

https://idroot.us/install-certbot-almalinux-8/

https://stackoverflow.com/questions/23948527/13-permission-denied-while-connecting-to-upstreamnginx

https://github.com/nextcloud/docker/blob/master/README.md

https://howtodotech.de/nextcloud-dateien-mit-occ-filesscan-neu-einscannen/

https://docs.nextcloud.com/server/latest/admin_manual/maintenance/backup.html

https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html

https://gdevillele.github.io/engine/admin/systemd/

https://linuxconfig.org/how-to-configure-ntp-server-and-client-on-almalinux

https://www.my-it-brain.de/wordpress/nextcloud-im-container-teil-3-mit-reverse-proxy/