Nextcloud Installationsanleitung für Ubuntu 26.04 LTS

Diese Nextcloud Installationsanleitung für Ubuntu 26.04 LTS (x86_64) mit nginx, MariaDB 11.8, PHP8.5, LetsEncrypt, Redis, crowdsec, ufw u.v.m. beschreibt die Installation, Konfiguration und Härtung sowie einige Erweiterungsmöglichkeiten von Nextcloud auf ihren Servern.


Aktualisierungen

» 2 0 2 6 «

28. April 2026:
» Neue Nextcloud Installationsanleitung für Ubuntu 26.04 LTS (Nextcloud Installationsanleitung)

27. April 2026:
» Neues Nextcloud Installationsskript für Ubuntu 26 (Nextcloud Installationsskript)

25. Februar 2026:
» Anpassung für Nextcloud HUB 26 Winter (php 8.4 und Mariadb 11.8)

11. Januar 2026:
» Anpassung für PHP 8.3 unter Debian 13

04. Januar 2026:
» Anpassung für PHP 8.3 und Redis unter Debian 13

» 2 0 2 5 «

23. November 2025:
» Anpassung bzgl. Netdata

13. November 2025:
» Anpassungen bzgl. Debian 13 und „software-properties-common

09. November 2025:
» Changes bzgl. MariaDB-Repos für Ubuntu undDebian, http/3 entfernt, da nach Angaben der Nextcloud GmbH die Software derzeit nicht http/3 kompatibel ist.

05. November 2025:
» Die Update-Skripte wurden aktualisiert

26. Oktober 2025:
» minimum./maximum.supported.desktop.version ergänzt.

26. September 2025:
» Anpassungen bzgl. CrowdsEC:
» Nextcloud Installationsanleitung
» Nextcloud Installationsskript
» Fail2ban » Crowdsec

27. August 2025:
» Enabled http/3 « optional
(aufgrund von bekannten und anerkannten Problemen der Nextcloud-Software mit http/3 raten wir in produktiven Umgebungen davon ab!)

10. August 2025:
» Anpassung des Nextcloud Installationsskriptes für Debian 13

08. August 2025:
» Anpassung der PostgreSQL 16 Parameter (/var/lib/postgresql/16/main/postgresql.auto.conf)

02. JuLi 2025:
» Anpassung der php-GC-Werte und Nextcloud-SessionWerte
– PHP: php.ini
– Nextcloud: config.php

30. Juni 2025:
» Anpassung der my.cnf (slave_connections_needed_for_purge = 0)

03. Juni 2025:
» SSL Stapling wurde entfernt (Let’s Encrypt)

25. Mai 2025:
» Lock data and shares of disabled users

16. Mai 2025:
» SSL Stapling wurde auskommentiert (Let’s Encrypt)

03. Mai 2025:
» Wechsel zu Redis v.8.0 (OpenSource)

20. April 2025:
» Nextcloud Installationsanleitung für Debian 12 (MariaDB 11.4) angepasst

01. März 2025:
» Nextcloud Installationsanleitung für Hub 10 freigegeben

25. Februar 2025:
» Nextcloud Installationsanleitung angepasst: md5 check

05. Februar 2025:
» Nextcloud Installationsanleitung angepasst: Crowdsec und Session-/Anmeldeverhalten

09. Januar 2025:
» ACME – Autoupgrade

Systemvoraussetzungen

Nextcloud Systemrequirements:
» https://docs.nextcloud.com/server/latest/admin_manual/installation/system_requirements.html#server

Nextcloud Remote access:
» https://docs.nextcloud.com/server/latest/admin_manual/installation/harden_server.html#connections-to-remote-servers


Die Installation basiert auf nginx (http/2), Let’s Encrypt TLS 1.3, MariaDB 11.8, PHP 8.5 (php-fpm), Redis, crowdsec, fail2ban, ufw und erhält abschließend sowohl von Nextcloud, als auch von Qualys SSL Labs eine A+ Sicherheitsbewertung. Die anzupassenden Parameter sind im Artikel rot markiert und müssen durch Ihre spezifischen Systemwerte (bspw. ihre.domain.de, 192.168.2.x, /var/nc_data, Redispassword) ersetzt werden.

Möchten Sie hingegen lieber alles mit nur einem einzigen Skript installieren? Dann nutzen Sie unser Nextcloud-Installationsskript zero26.sh, welches Ihnen hier zur Verfügung steht.

Inhaltsverzeichnis

  1. Systemvorbereitungen und Installation des nginx Webservers
  2. Installation und Konfiguration von PHP 8.5
  3. Installation und Konfiguration des Datenbankservers MariaDB 11.8
  4. Installation des Redis-Server („in-memory-Datenbank“)
  5. Installation und Optimierung der Nextcloud (inkl. SSL)
  6. Systemhärtung (crowdsec IPS, fail2ban und ufw)
  7. Optimieren und aktualisieren der Nextcloud per Skript
  8. optional: Nextcloud (HPB) High Performance Backend für Dateien
  9. optional: bash_alias für php occ, empfohlene Settings (config.php), logrotating
  10. optional: Verbesserung der Sicherheit und Performance des TCP-Stacks

Weiterführende Herstellerinformationen finden Sie hier.


1. Vorbereitungen und Installation des nginx Webserver

Aktuelle Installationsmedien für den zugrundeliegenden Linux-Server erhalten Sie hier:

Ubuntu 26.04.x LTS: Download-Installationsmedium

Starten Sie mit der Installation und verbinden sich anschließend per SSH mit Ihrem Server – bspw.:

ssh <benutzer>@<IP-Adresse>

Wechseln Sie in den privilegierten Benutzermodus

sudo -s

und aktualisieren zuerst das System.

apt update && apt upgrade -y

Bereiten Sie den Server vor, indem Sie die notwendigen Basissoftwarepakete installieren:

apt update && apt upgrade -y
apt install -y \
apt-transport-https bash-completion bzip2 ca-certificates cron curl dialog dirmngr \
ffmpeg ghostscript git gpg gnupg gnupg2 htop jq libfile-fcntllock-perl libfontconfig1 \
libfuse2 locate lsb-release nano nodejs net-tools npm rsyslog screen smbclient socat \
ssl-cert tree unzip vim wget zip software-properties-common ubuntu-keyring
mkdir -p /etc/apt/keyrings

Tragen Sie den zukünftigen Servernamen sowohl in die hosts-Datei, als auch in die hostname-Datei ein:

nano /etc/hosts

Passen Sie die roten Werte an Ihre Umgebung an, im Beispiel gehen wir davon aus, dass die Domäne „ihre.domain.de“ heißt:

127.0.0.1 localhost
127.0.1.1 ihre ihre.domain.de
::1 ihre ihre.domain.de ip6-localhost ip6-loopback
[...]

Geben Sie den vollständigen Servername in der hostname-Datei an und ersetzen den roten Wert durch Ihren:

nano /etc/hostname

Der Servername muss als FQDN, also vollqualifiziert angegeben werden:

ihre.domain.de

Sorgen Sie nun dafür, dass der Server nicht in einen „Energiesparmodus“ wechseln kann:

systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

Starten Sie abschließend den Server neu

reboot now

und melden sich dann erneut mit priviligierten Benutzerrechten am Server an:

sudo -s

Fügen Sie dem System das nginx-Software-Repositoriey (Softwarequelle) hinzu, um die aktuellen Releases des jeweiligen Pakets installieren zu können

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
    http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
    | sudo tee /etc/apt/preferences.d/99nginx

Um das hinzugefügte Repository einzulesen und das System damit zu präparieren aktualisieren wir das System abermals und generieren temporäre „self-signed“-Zertifikate, die im späteren Verlauf durch vollwertige ECC-Zertifikate von Let’s Encrypt ersetzt werden.

apt update && make-ssl-cert generate-default-snakeoil -y

Nun sind die Vorbereitungen bereits abgeschlossen und wir können mit der Installation des Webservers nginx beginnen.

apt install -y nginx

Den automatischen Start des Dienstes setzen wir wie folgt:

systemctl enable nginx.service

Mit Blick auf die späteren Anpassungen wird die Standardkonfiguration gesichert und eine neue Konfigurationsdatei erstellt:

mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
touch /etc/nginx/nginx.conf && nano /etc/nginx/nginx.conf

Kopieren Sie den gesamten nachfolgenden Inhalt in die Datei:

user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
multi_accept on;
use epoll;
}
http {
ssl_early_data on;
server_names_hash_bucket_size 64;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
send_timeout 3600;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=500 inactive=10m;
open_file_cache_errors on;
keepalive_timeout 65;
reset_timedout_connection on;
server_tokens off;
resolver 127.0.0.53 176.9.93.198 176.9.1.117 valid=30s;
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
}

Betreiben Sie Ihre Nextcloud hinter einem Reverse Proxy, so ersetzen Sie die IP des Parameteres „set_real_ip_from 127.0.0.1“ mit der IP des Reverse Proxys („set_real_ip_from w.x.y.z„).

Speichern Sie die Datei und schließen Sie diese, um im Anschluß den Webserver neu zu starten:

systemctl restart nginx.service

Vorbereitend für die SSL Zertifikate und die Webverzeichnisse legen wir vier Ordner an und setzen die korrekten Berechtigungen:

mkdir -p /var/log/nextcloud /var/nc_data /var/www/letsencrypt/.well-known/acme-challenge /etc/letsencrypt/rsa-certs /etc/letsencrypt/ecc-certs
chown -R www-data:www-data /var/nc_data /var/www /var/log/nextcloud

Die Installation des Webservers ist somit bereits abgeschlossen und wir fahren mit der Installation und den Anpassungen von PHP fort.


2. Installation und Konfiguration von PHP 8.5 (fpm)

Wir verwenden das seitens Ubuntu 26 bereitgestellte PHP 8.5 und können direkt mit der Installation beginnen.

apt update
apt install -y php-common \
php8.5-{fpm,gd,curl,xml,zip,intl,mbstring,bz2,ldap,apcu,bcmath,gmp,imagick,igbinary,mysql,redis,smbclient,sqlite3,cli,common,readline} imagemagick libmagickcore-7.q16-10-extra --allow-change-held-packages
apt install -y ldap-utils nfs-common cifs-utils --allow-change-held-packages

Optional (bei einem geplanten Einsatz von Samba- und/oder cifs-Shares oder einer LDAP(s)-Anbindung):

apt install -y ldap-utils nfs-common cifs-utils

Setzen Sie das richtige Datumsformat, um auch ein korrektes Logging zu ermöglichen:

timedatectl set-timezone Europe/Berlin

Bevor wir mit den Optimierungen von PHP beginnen sichern wir die Konfigurationsdateien,

cp /etc/php/8.5/fpm/pool.d/www.conf /etc/php/8.5/fpm/pool.d/www.conf.bak
cp /etc/php/8.5/fpm/php-fpm.conf /etc/php/8.5/fpm/php-fpm.conf.bak
cp /etc/php/8.5/cli/php.ini /etc/php/8.5/cli/php.ini.bak
cp /etc/php/8.5/fpm/php.ini /etc/php/8.5/fpm/php.ini.bak
cp /etc/php/8.5/mods-available/apcu.ini /etc/php/8.5/mods-available/apcu.ini.bak
cp /etc/ImageMagick-7/policy.xml /etc/ImageMagick-7/policy.xml.bak

optimieren dann PHP für den Betrieb Ihrer Nextcloud

sed -i "s/;env\[HOSTNAME\] = /env[HOSTNAME] = /" /etc/php/8.5/fpm/pool.d/www.conf
sed -i "s/;env\[TMP\] = /env[TMP] = /" /etc/php/8.5/fpm/pool.d/www.conf
sed -i "s/;env\[TMPDIR\] = /env[TMPDIR] = /" /etc/php/8.5/fpm/pool.d/www.conf
sed -i "s/;env\[TEMP\] = /env[TEMP] = /" /etc/php/8.5/fpm/pool.d/www.conf
sed -i "s/;env\[PATH\] = /env[PATH] = /" /etc/php/8.5/fpm/pool.d/www.conf
sed -i 's/pm = dynamic/pm = ondemand/' /etc/php/8.5/fpm/pool.d/www.conf
sed -i 's/pm.max_children =.*/pm.max_children = 200/' /etc/php/8.5/fpm/pool.d/www.conf
sed -i 's/pm.start_servers =.*/pm.start_servers = 100/' /etc/php/8.5/fpm/pool.d/www.conf
sed -i 's/pm.min_spare_servers =.*/pm.min_spare_servers = 60/' /etc/php/8.5/fpm/pool.d/www.conf
sed -i 's/pm.max_spare_servers =.*/pm.max_spare_servers = 140/' /etc/php/8.5/fpm/pool.d/www.conf
sed -i "s/;pm.max_requests =.*/pm.max_requests = 1000/" /etc/php/8.5/fpm/pool.d/www.conf
sed -i "s/allow_url_fopen =.*/allow_url_fopen = 1/" /etc/php/8.5/fpm/php.ini
sed -i "s/output_buffering =.*/output_buffering = Off/" /etc/php/8.5/cli/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 3600/" /etc/php/8.5/cli/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/8.5/cli/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/8.5/cli/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/8.5/cli/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/8.5/cli/php.ini
sed -i "s/;cgi.fix_pathinfo.*/cgi.fix_pathinfo=0/" /etc/php/8.5/cli/php.ini

sed -i "s/memory_limit = 128M/memory_limit = 1G/" /etc/php/8.5/fpm/php.ini
sed -i "s/output_buffering =.*/output_buffering = Off/" /etc/php/8.5/fpm/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 3600/" /etc/php/8.5/fpm/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/8.5/fpm/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10G/" /etc/php/8.5/fpm/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10G/" /etc/php/8.5/fpm/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/8.5/fpm/php.ini
sed -i "s/;cgi.fix_pathinfo.*/cgi.fix_pathinfo=0/" /etc/php/8.5/fpm/php.ini
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.enable=.*/opcache.enable=1/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.validate_timestamps=.*/opcache.validate_timestamps=1/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=256/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=64/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=100000/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=0/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" /etc/php/8.5/fpm/php.ini
sed -i "s/;opcache.huge_code_pages=.*/opcache.huge_code_pages=0/" /etc/php/8.5/fpm/php.ini
sed -i "s/session.gc_maxlifetime =.*/session.gc_maxlifetime = 36000/" /etc/php/8.5/fpm/php.ini

sed -i "s|;emergency_restart_threshold.*|emergency_restart_threshold = 10|g" /etc/php/8.5/fpm/php-fpm.conf
sed -i "s|;emergency_restart_interval.*|emergency_restart_interval = 1m|g" /etc/php/8.5/fpm/php-fpm.conf
sed -i "s|;process_control_timeout.*|process_control_timeout = 10|g" /etc/php/8.5/fpm/php-fpm.conf

sed -i '$aapc.enable_cli=1' /etc/php/8.5/mods-available/apcu.ini

# sed -i 's/opcache.jit=off/opcache.jit=on/' /etc/php/8.5/mods-available/opcache.ini
# sed -i '$aopcache.jit=1255' /etc/php/8.5/mods-available/opcache.ini
# sed -i '$aopcache.jit_buffer_size=256M' /etc/php/8.5/mods-available/opcache.ini

sed -i "s/rights=\"none\" pattern=\"PS\"/rights=\"read|write\" pattern=\"PS\"/" /etc/ImageMagick-7/policy.xml
sed -i "s/rights=\"none\" pattern=\"EPS\"/rights=\"read|write\" pattern=\"EPS\"/" /etc/ImageMagick-7/policy.xml
sed -i "s/rights=\"none\" pattern=\"PDF\"/rights=\"read|write\" pattern=\"PDF\"/" /etc/ImageMagick-7/policy.xml
sed -i "s/rights=\"none\" pattern=\"XPS\"/rights=\"read|write\" pattern=\"XPS\"/" /etc/ImageMagick-7/policy.xml


sed -i '$a[mysql]' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.allow_local_infile=On' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.allow_persistent=On' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.cache_size=2000' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.max_persistent=-1' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.max_links=-1' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.default_port=3306' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.connect_timeout=60' /etc/php/8.5/mods-available/mysqli.ini
sed -i '$amysql.trace_mode=Off' /etc/php/8.5/mods-available/mysqli.ini

und starten PHP sowie den Webserver nginx neu:

systemctl restart php8.5-fpm.service nginx.service

Auch PHP ist nun bereits installiert und für den Betrieb der Nextcloud optimiert. Starten wir nun mit der Installation und konfiguration des Datenbankserver MariaDB.


3. Installation und Konfiguration von MariaDB 11.8

Die Installation von MariaDB erfolgt mit diesem Befehl:

apt update && apt install -y mariadb-server

Härten wir nun den Datenbankserver mittels des mitgelieferten Tools „mysql_secure_installation“. Bei einer Erstinstallation besteht kein Rootpasswort, so dass Sie die Abfrage mit ENTER bestätigen könne. Es wird empfohlen, ein Passwort direkt zu setzen, der entsprechende Dialog erscheint automatisch:

mariadb-secure-installation
Enter current password for root (enter for none): <ENTER> or type the password
Switch to unix_socket authentication [Y/n] Y
Change the root password? [Y/n] Y
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

Stoppen Sie nun den Datenbankserver, sichern dann die Standardkonfiguration, um unmittelbar danach Anpassungen vornehmen zu können:

systemctl stop mariadb-server
cp /etc/mysql/my.cnf /etc/mysql/my.cnf.bak
cat <<EOF >/etc/mysql/my.cnf
[client]
default-character-set = utf8mb4
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld_safe]
log_error=/var/log/mysql/mysql_error.log
nice = 0
socket = /var/run/mysqld/mysqld.sock
[mysqld]
# performance_schema=ON
basedir = /usr
bind-address = 127.0.0.1
binlog_format = ROW
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
datadir = /var/lib/mariadb
default_storage_engine = InnoDB
expire_logs_days = 2
slave_connections_needed_for_purge = 0
general_log_file = /var/log/mysql/mysql.log
innodb_buffer_pool_size = 1G
innodb_log_buffer_size = 32M
innodb_log_file_size = 512M
innodb_read_only_compressed=OFF
join_buffer_size = 2M
key_buffer_size = 512M
lc_messages_dir = /usr/share/mysql
lc_messages = en_US
log_bin = /var/log/mysql/mariadb-bin
log_bin_index = /var/log/mysql/mariadb-bin.index
log_bin_trust_function_creators = true
log_error = /var/log/mysql/mysql_error.log
log_slow_verbosity = query_plan
log_warnings = 2
long_query_time = 1
max_connections = 100
max_heap_table_size = 64M
max_allowed_packet = 512M
max-binlog-size = 512M
max_binlog_total_size = 2G
myisam_sort_buffer_size = 512M
port = 3306
pid-file = /var/run/mysqld/mysqld.pid
query_cache_limit = 0
query_cache_size = 0 
read_buffer_size = 2M
read_rnd_buffer_size = 2M
skip-name-resolve
socket = /var/run/mysqld/mysqld.sock
sort_buffer_size = 2M
table_open_cache = 400
table_definition_cache = 800
tmp_table_size = 32M
tmpdir = /tmp
transaction_isolation = READ-COMMITTED
user = mysql
wait_timeout = 600
[mariadb-dump]
max_allowed_packet = 512M
quick
quote-names
[isamchk]
key_buffer = 16M
EOF
mkdir -p /var/log/mysql
chown -R mysql:mysql /var/log/mysql
systemctl restart mariadb.service

Erstellen Sie nun die Nextcloud-Datenbank, den Nextcloud-Benutzer und sein Passwort:

mariadb -uroot -p -e "CREATE DATABASE nextclouddb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER nextclouddbuser@localhost identified by 'nextclouddbpassword'; GRANT ALL PRIVILEGES on nextclouddb.* to nextclouddbuser@localhost; FLUSH privileges;"

Erläuterung (bitte frei nach Ihren Wünschen anpassen):
Datenbankname: nextclouddb
Datenbankbenutzer: nextclouddbuser
Datenbankbenutzerpaßwort: nextclouddbpassword

Überprüfen Sie die neue Datenbank:

mariadb -e "SELECT @@TX_ISOLATION; SELECT SCHEMA_NAME 'database', default_character_set_name 'charset', DEFAULT_COLLATION_NAME 'collation' FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='nextclouddb'"

Erscheint in der Ausgabe (resultset) „READ-COMMITTED“ und „utf8mb4_general_ci“ so wurde alles korrekt eingerichtet und wir können mit der Installation von Redis fortfahren.


4. Installation und Konfiguration von Redis v. 8

Wir installieren und optimieren den Redis-Server um die Nextcloudperformance zu steigern, da durch Redis die Last auf der MariaDB-Nextclouddatenbank signifikant reduziert wird:

apt update && apt install -y redis-server redis-tools --allow-change-held-packages
cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sed -i 's/port 6379/port 0/' /etc/redis/redis.conf
sed -i 's/\# unixsocket\ .*$/unixsocket \/var\/run\/redis\/redis-server.sock/' /etc/redis/redis.conf
sed -i 's/\#\ unixsocketperm\ .*$/unixsocketperm 770/g' /etc/redis/redis.conf
sed -i 's/# maxclients\ .*$/maxclients 10240/' /etc/redis/redis.conf
sed -i "s/\# requirepass foobared/requirepass REDISPASSWORD/" /etc/redis/redis.conf
usermod -aG redis www-data
touch /etc/sysctl.d/99-redis.conf
cat <<EOF >/etc/sysctl.d/99-redis.conf
vm.overcommit_memory = 1
EOF

Stellen wir nun abschließend sicher, dass alle zuvor installierten Dienste auch bei einem Serverneustart automatisch gestartet werden:

systemctl enable mariadb.service redis-server.service php8.5-fpm.service nginx.service && systemctl restart mariadb.service redis-server.service php8.5-fpm.service nginx.service 

Gratulation, der Server ist bereits vollständig mit nginx, PHP8.5, MariaDB und Redis installiert, eingerichtet und optimiert! Wir können nun mit der Einrichtung der Nextcloud beginnen.


5. Installation und Optimierung der Nextcloud (inkl. SSL)

Wir richten nun verschiedene vHosts, also Webserverkonfigurationsdateien, ein und modifizieren die Standard vHost-Datei (default.conf) so, dass diese auch durch spätere Systemupdates nicht automatisch verändert werden kann. Sichern Sie die Standard vhost-Datei namens default.conf und legen zuerst leere vHost-Dateien zum Konfigurieren an.

mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
touch /etc/nginx/conf.d/default.conf
touch /etc/nginx/conf.d/http.conf
touch /etc/nginx/conf.d/nextcloud.conf
cat <<EOF >/etc/nginx/conf.d/http.conf
upstream php-handler {
  server unix:/run/php/php8.5-fpm.sock;
  }
map \$arg_v \$asset_immutable {
    "" "";
    default "immutable";
}
  server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name 192.168.30.198 ihre.domain.de;
    root /var/www;
    location ^~ /.well-known/acme-challenge {
      default_type text/plain;
      root /var/www/letsencrypt;
      }
    location / {
      return 301 https://\$host\$request_uri;
      }
   }
EOF
cat <<EOF >/etc/nginx/conf.d/nextcloud.conf
limit_req_zone \$binary_remote_addr zone=NextcloudRateLimit:10m rate=2r/s;
server {
  listen 443 ssl;
  listen [::]:443 ssl;
  http2 on;
  server_name 192.168.30.198 ihre.domain.de;
  ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
  ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
  ssl_trusted_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
  #ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
  #ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
  #ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:50m;
  ssl_session_tickets off;
  ssl_protocols TLSv1.3 TLSv1.2;
  ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
  ssl_ecdh_curve X448:secp521r1:secp384r1;
  ssl_prefer_server_ciphers on;
  client_max_body_size 10G;
  client_body_timeout 3600s;
  client_body_buffer_size 512k;
  fastcgi_buffers 64 4K;
  gzip on;
  gzip_vary on;
  gzip_comp_level 4;
  gzip_min_length 256;
  gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
  gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
  add_header Strict-Transport-Security            "max-age=15768000; includeSubDomains; preload;" always;
  add_header Permissions-Policy                   "interest-cohort=()";
  add_header Referrer-Policy                      "no-referrer"   always;
  add_header X-Content-Type-Options               "nosniff"       always;
  add_header X-Download-Options                   "noopen"        always;
  add_header X-Frame-Options                      "SAMEORIGIN"    always;
  add_header X-Permitted-Cross-Domain-Policies    "none"          always;
  add_header X-Robots-Tag                         "noindex, nofollow" always;
  add_header X-XSS-Protection                     "1; mode=block" always;
  fastcgi_hide_header X-Powered-By;
  include mime.types;
  types {
  text/javascript mjs;
	  }
  root /var/www/nextcloud;
  index index.php index.html /index.php\$request_uri;
  location = / {
    if ( \$http_user_agent ~ ^DavClnt ) {
      return 302 /remote.php/webdav/\$is_args\$args;
      }
  }
  location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
    }
  location ^~ /.well-known {
    location = /.well-known/carddav { return 301 /remote.php/dav/; }
    location = /.well-known/caldav  { return 301 /remote.php/dav/; }
    location /.well-known/acme-challenge { try_files \$uri \$uri/ =404; }
    location /.well-known/pki-validation { try_files \$uri \$uri/ =404; }
    return 301 /index.php\$request_uri;
    }
  location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:\$|/)  { return 404; }
  location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)  { return 404; }
  location ~ \.php(?:\$|/) {
    rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy) /index.php\$request_uri;
    fastcgi_split_path_info ^(.+?\.php)(/.*)\$;
    set \$path_info \$fastcgi_path_info;
    try_files \$fastcgi_script_name =404;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
    fastcgi_param PATH_INFO \$path_info;
    fastcgi_param HTTPS on;
    fastcgi_param modHeadersAvailable true;
    fastcgi_param front_controller_active true;
    fastcgi_pass php-handler;
    fastcgi_intercept_errors on;
    fastcgi_request_buffering on;
    fastcgi_read_timeout 3600;
    fastcgi_send_timeout 3600;
    fastcgi_connect_timeout 3600;
    fastcgi_max_temp_file_size 0;
    }
    location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
    try_files \$uri /index.php\$request_uri;
    add_header Cache-Control                        "public, max-age=15778463, \$asset_immutable";
    add_header Permissions-Policy                   "interest-cohort=()";
    add_header Referrer-Policy                      "no-referrer"   always;
    add_header X-Content-Type-Options               "nosniff"       always;
    add_header X-Download-Options                   "noopen"        always;
    add_header X-Frame-Options                      "SAMEORIGIN"    always;
    add_header X-Permitted-Cross-Domain-Policies    "none"          always;
    add_header X-Robots-Tag                         "noindex, nofollow" always;
    add_header X-XSS-Protection                     "1; mode=block" always;
    expires 6M;
    access_log off;
    location ~ \.wasm\$ {
      default_type application/wasm;
      }
    }
  location ~ \.(otf|woff2?)$ {
    try_files \$uri /index.php\$request_uri;
    expires 7d;
    access_log off;
    }
  location /remote {
    return 301 /remote.php\$request_uri;
    }
  location /login {
    limit_req zone=NextcloudRateLimit burst=5 nodelay;
    limit_req_status 429;
    try_files \$uri \$uri/ /index.php\$request_uri;
    }    
  location / {
    try_files \$uri \$uri/ /index.php\$request_uri;
    }
}
EOF

HINWEIS: Nur für Cyberduck- bzw. Mountain Duck – Nutzer

Bitte diese Anpassungen vornehmen

nano /etc/nginx/conf.d/nextcloud.conf
[...]
# fastcgi_max_temp_file_size 0;
fastcgi_max_temp_file_size 10240M;
[...]

Quelle: https://docs.cyberduck.io/mountainduck/issues/fastcgi/#nginx

HINWEIS – ENDE

Erweitern Sie die Server- und Systemsicherheit durch die Möglichkeit des sicheren Schlüsselaustauschs mittels eines Diffie-Hellman Schlüssels:

openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Bitte haben Sie nun Geduld! Das Generieren kann – in Abhängigkeit von der Systemleistung – einige Minuten dauern. Erst wenn das Generieren abgeschlossen ist, starten wir den Webserver erneut durch.

systemctl restart nginx.service

Wir beginnen nun die ‚eigentliche‘ Installation der Nextcloud Software und richten dafür die SSL Zertifikate von Let’s Encrypt mittels acme ein. Wechseln Sie dafür in das Arbeitsverzeichnis

cd /usr/local/src

und laden das aktuellste Nextcloud-Release

wget  https://download.nextcloud.com/server/releases/latest.tar.bz2
wget https://download.nextcloud.com/server/releases/latest.tar.bz2.md5

Überpüfen Sie die Dateien:

md5sum --ignore-missing -c latest.tar.bz2.md5 < latest.tar.bz2

Nur wenn Ihnen der Test mit

latest.tar.bz2: OK

bestätigt wird, fahren wir fort. Entpacken Sie dann die Nextcloud Software in das Webverzeichnis (/var/www), setzen dann die notwendigen Berechtigung und Löschen die heruntergeladenen Dateien:

tar -xjf latest.tar.bz2 -C /var/www && chown -R www-data:www-data /var/www/ && rm -f latest.tar.bz2 latest.tar.bz2.md5

Bitte stellen Sie sicher, dass Ihr Server sowohl über Port 80/TCP als auch über Port 443/TCP von außen erreichbar ist. Das Erstellen und Aktualisieren von Let’s Encryptzertifikaten erfolgt im Zuge dieser Anleitung zwingend über http und Port 80. Andere Möglichkeiten werden von uns im Artikel (Let’s Encrypt Zertifikate (RSA 4096 oder EC 384) ohne offene TCP-Ports 80 und 443 beantragen und erstellen beschrieben. Für das Zertifikatshandling erstellen wir nun einen dedizierten Benutzer und fügen diesen der www-data Gruppe hinzu:

adduser acmeuser --gecos "" --disabled-password
usermod -aG www-data acmeuser

Diesem technischen Benutzer erteilen wir noch die notwendigen Berechtigungen, um bei einer Zertifikatserneuerung den notwendigen Webserverstart initiieren zu können.

touch /etc/sudoers.d/acmeuser
cat <<EOF >/etc/sudoers.d/acmeuser
acmeuser ALL=NOPASSWD: /bin/systemctl reload nginx.service
EOF

Installieren Sie nun für den Benutzer acmeuser das acme.sh-Tool und aktivieren zudem das automatische Upgrade:

su - acmeuser -c "/usr/bin/curl https://get.acme.sh | sh"
su - acmeuser -c ".acme.sh/acme.sh --set-default-ca --server letsencrypt"
su - acmeuser -c ".acme.sh/acme.sh --upgrade --auto-upgrade"

Passen Sie die entsprechenden Datei- und Verzeichnisberechtigungen an, um die neuen Zertifikate darin speichern zu können:

chmod -R 775 /var/www/letsencrypt && chmod -R 770 /etc/letsencrypt && chown -R www-data:www-data /var/www/ /etc/letsencrypt

Wechseln Sie in die Shell des neuen acme-Benutzers

su - acmeuser

und beantragen dann die SSL-Zertifikate von Let’s Encrypt. Ersetzen Sie dafür bitte ihre.domain.de mit Ihrer „echten“ Domain:

acme.sh --issue -d ihre.domain.de --server letsencrypt --keylength ec-384 -w /var/www/letsencrypt --key-file /etc/letsencrypt/ecc-certs/privkey.pem --ca-file /etc/letsencrypt/ecc-certs/chain.pem --cert-file /etc/letsencrypt/ecc-certs/cert.pem --fullchain-file /etc/letsencrypt/ecc-certs/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx.service"

Verlassen Sie die Shell des acme-Benutzers

exit

und legen sich dann ein Skript an, das zukünftig die Berechtigungen überprüft und korrigiert (permissions.sh):

nano /root/permissions.sh

Kopieren Sie alle Zeilen in die Datei:

#!/bin/bash
find /var/www/ -type f -print0 | xargs -0 chmod 0640
find /var/www/ -type d -print0 | xargs -0 chmod 0750
if [ -d "/var/www/nextcloud/apps/notify_push" ]; then
chmod ug+x /var/www/nextcloud/apps/notify_push/bin/x86_64/notify_push
fi
chmod -R 775 /var/www/letsencrypt
chmod -R 770 /etc/letsencrypt 
chown -R www-data:www-data /var/www /etc/letsencrypt
chown -R www-data:www-data /var/nc_data
chmod 0644 /var/www/nextcloud/.htaccess
chmod 0644 /var/www/nextcloud/.user.ini
exit 0

Markieren Sie das Skript als ausführbar und führen es dann direkt aus:

chmod +x /root/permissions.sh
/root/permissions.sh

Entfernen Sie Ihre bisher verwendeten Self-Signed-Zertifikate aus nginx und aktivieren Sie die neuen, vollwertigen und bereits gültigen SSL Zertifikate von Let’s Encrypt. Starten Sie dann den Webserver neu:

sed -i '/ssl-cert-snakeoil/d' /etc/nginx/conf.d/nextcloud.conf
sed -i s/#\ssl/\ssl/g /etc/nginx/conf.d/nextcloud.conf
systemctl restart nginx.service

Um sowohl die SSL-Zertifikate automatisch zu erneuern, als auch den notwendigen Webserverneustart zu initiieren, wurde automatisch ein Cronjob angelegt, den Sie nachfolgend einsehen können:

crontab -l -u acmeuser

Wir können nun mit der Einrichtung der Nextcloud selbst fortfahren. Dazu verwenden Sie den nachfolgenden „silent“ Installationsbefehl:

sudo -u www-data php /var/www/nextcloud/occ maintenance:install --database "mysql" --database-name "nextclouddb" --database-user "nextclouddbuser" --database-pass "nextclouddbpassword" --admin-user "YourNextcloudAdmin" --admin-pass "YourNextcloudAdminPasssword" --data-dir "/var/nc_data"

Erläuterungen:

database-name „nextclouddb“ : Datenbankname aus Kapitel 3

database-user “nextclouddbuser” : Datenbankbenutzer aus Kapitel 3

database-pass “nextclouddbpassword” : Datenbankbenutzerpasswort aus Kapitel 3

admin-user “YourNextcloudAdmin” : frei wählbar von Ihnen

admin-pass “YourNextcloudAdminPasssword” : frei wählbar von Ihnen

Warten Sie bis die Installation der Nextcloud abgeschlossen wurde und passen dann die zentrale Konfigurationsdatei der Nextcloud „config.php“ als Webuser www-data an:

1. Fügen Sie Ihre Domain und die IP des Servers als „trusted domain“ hinzu, ergänzen Sie dabei ihre.domain.de und y.x.y.z mit Ihrer dedizierten Domain:

sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 0 --value=w.x.y.z
sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 --value=ihre.domain.de

2. Setzen Sie Ihre Domain als overwrite.cli.url und overwritehost, ergänzen Sie dabei ihre.domain.de mit Ihrer dedizierten Domain:

sudo -u www-data php /var/www/nextcloud/occ config:system:set overwrite.cli.url --value=https://ihre.domain.de
sudo -u www-data php /var/www/nextcloud/occ config:system:set overwritehost --value=ihre.domain.de

Nun erweitern wir abschließend die Nextcloud Konfiguration. Sichern Sie dazu zuerst die bestehende config.php

sudo -u www-data cp /var/www/nextcloud/config/config.php /var/www/nextcloud/config/config.php.bak 

und führen dann die nachfolgenden Zeilen in einem Block aus:

sed -i '/);/d' /var/www/nextcloud/config/config.php
cat <<EOF >>/var/www/nextcloud/config/config.php
  'activity_expire_days' => 14,
  'allow_local_remote_servers' => true,
  'auth.bruteforce.protection.enabled' => true,
  'forbidden_filenames' =>
  array (
    0 => '.htaccess',
    1 => 'Thumbs.db',
    2 => 'thumbs.db',
    ),
    'cron_log' => true,
    'default_phone_region' => 'DE',
    'enable_previews' => true,
    'enabledPreviewProviders' =>
        array (
      0 => 'OC\\Preview\\PNG',
      1 => 'OC\\Preview\\JPEG',
      2 => 'OC\\Preview\\GIF',
      3 => 'OC\\Preview\\BMP',
      4 => 'OC\\Preview\\XBitmap',
      5 => 'OC\\Preview\\Movie',
      6 => 'OC\\Preview\\PDF',
      7 => 'OC\\Preview\\MP3',
      8 => 'OC\\Preview\\TXT',
      9 => 'OC\\Preview\\MarkDown',
      10 => 'OC\\Preview\\HEIC',
      11 => 'OC\\Preview\\Movie',
      12 => 'OC\\Preview\\MKV',
      13 => 'OC\\Preview\\MP4',
      14 => 'OC\\Preview\\AVI',
      ),
      'filesystem_check_changes' => 0,
      'filelocking.enabled' => 'true',
      'htaccess.RewriteBase' => '/',
      'integrity.check.disabled' => false,
      'knowledgebaseenabled' => false,
      'log_rotate_size' => '104857600',
      'logfile' => '/var/log/nextcloud/nextcloud.log',
      'loglevel' => 2,
      'logtimezone' => 'Europe/Berlin',
      'remember_login_cookie_lifetime' => 36000,
      'session_lifetime' => 36000,
      'session_keepalive' => true,
      'auto_logout' => true,
      'memcache.local' => '\\\\OC\\\\Memcache\\\\APCu',
      'memcache.locking' => '\\\\OC\\\\Memcache\\\\Redis',
      'minimum.supported.desktop.version' => '33.0.2',
      'overwriteprotocol' => 'https',
      'preview_max_x' => 1024,
      'preview_max_y' => 768,
      'preview_max_scale_factor' => 1,
      'profile.enabled' => false,
      'redis' =>
      array (
        'host' => '/var/run/redis/redis-server.sock',
        'port' => 0,
        'password' => 'REDISPASSWORD',
        'timeout' => 0.5,
        'dbindex' => 1,
        ),
      'quota_include_external_storage' => false,
      'share_folder' => '/Freigaben',
      'skeletondirectory' => '',
      'trashbin_retention_obligation' => 'auto, 7',
      'maintenance_window_start' => 1,
      'serverid' => '1',
      );
EOF
sed -i 's/^[ ]*//' /var/www/nextcloud/config/config.php

Modifizieren Sie die „.user.ini“

sudo -u www-data sed -i "s/output_buffering=.*/output_buffering=0/" /var/www/nextcloud/.user.ini

und passen die Nextcloud sowie die Nextcloud-Apps als user www-data an

sudo -u www-data php /var/www/nextcloud/occ maintenance:repair --include-expensive
sudo -u www-data php /var/www/nextcloud/occ app:disable survey_client
sudo -u www-data php /var/www/nextcloud/occ app:disable firstrunwizard
sudo -u www-data php /var/www/nextcloud/occ app:disable app_api
sudo -u www-data php /var/www/nextcloud/occ app:disable logreader
sudo -u www-data php /var/www/nextcloud/occ config:app:set files_sharing hide_disabled_user_shares --value yes

Nextcloud ist ab sofort voll einsatzfähig, optimiert und abgesichert. Starten Sie alle relevanten Services neu:

systemctl restart mariadb.service redis-server.service php8.5-fpm.service nginx.service

Richten Sie einen Cronjob für Nextcloud als „www-data“ – Benutzer ein:

crontab -u www-data -e

Fügen Sie diese Zeile am Ende ein

*/5 * * * * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1

Speichern und schließen Sie dann die Datei und konfigurieren Sie den Nextcloud-Job von „Ajax“ zu „Cron“ mittels der Nextclouds CLI um:

sudo -u www-data php /var/www/nextcloud/occ background:cron

Bitte nehmen Sie sich etwas Zeit und überprüfen den Sicherheitsstatus Ihres Servers. Das Ziel sollte sein, mindestens die nachfolgend dargestellten „A+“-Ergebnisse in den Tests zu erzielen:

https://www.ssllabs.com/ssltest/index.html

und https://observatory.mozilla.org/

Um Schwierigkeiten zu vermeiden, die aus Aktualisierungen der verwendeten Komponenten resultieren können, lassen sich die relevanten Pakete mittels „apt-mark hold“ vom turnusmäßigen Aktualisieren ausschließen:

apt-mark hold nginx* nginx-*
apt-mark hold redis-*
apt-mark hold mariadb-* mariadb* mysql-* mysql* galera-*
apt-mark hold php-* php8.5-*

Um diese Pakete im Rahmen von Aktualisierungen wieder zu berücksichtigen muss nur das „hold“ aufgehoben werden:

apt-mark unhold nginx* nginx-*
apt-mark unhold redis-*
apt-mark unhold mariadb-* mariadb* mysql-* mysql* galera-*
apt-mark unhold php-* php8.5-*

Nach der Aktualisierung empfehlen wir ein erneutes setzen auf ‚hold‘.


6. Systemhärtung (crowdsec IPS, fail2ban und ufw)

Zuerst installieren wir crowdsec um den Server gegen Brute-force-Attacken und fehlerhafte Loginversuche zu schützen. Richten Sie dafür das Repository ein:

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash

Da für Ubuntu 26 zum Zeitpunkt der Erstellung des Artikels noch kein Repository zur Verfügung steht, passen wir das source-File an:

sed -i 's/resolute/noble/' /etc/apt/sources.list.d/crowdsec_crowdsec.list

DIese Anpassung kann nach Bereitstellung des Repositorys umgehend rückgängig gemacht werden. Führen wir nun die Installation aus

apt update && install -y crowdsec crowdsec-firewall-bouncer

und stellen anschließend den „Autostart“ der CrowdSec-Software sicher:

systemctl enable --now crowdsec.service crowdsec-firewall-bouncer.service

Überprüfen wir nun, ob CrowdSec gestartet und auf Autostart („enabled“) steht:

systemctl status crowdsec.service crowdsec-firewall-bouncer.service

Um Ihren Cloudserver hinsichtlich NGINX- und Nextcloud-Attacken abzusichern fügen wir sowohl eine NGINX-, als auch Nextcloud- und SSH-Collections hinzu:

cscli collections install crowdsecurity/nginx
cscli parsers install crowdsecurity/nginx-logs
cscli scenarios install crowdsecurity/nginx-req-limit-exceeded
cscli collections install crowdsecurity/nextcloud
cscli collections install crowdsecurity/nextcloud
cscli scenarios install crowdsecurity/nextcloud-bf
cscli parsers install crowdsecurity/nextcloud-logs
cscli parsers install crowdsecurity/nextcloud-whitelist
cscli collections install crowdsecurity/sshd
cscli scenarios install crowdsecurity/ssh-bf
cscli scenarios install crowdsecurity/ssh-slow-bf
cscli parsers install crowdsecurity/sshd-success-logs
cscli parsers install crowdsecurity/sshd-logs

Passen Sie nun den Pfad des Nextcloud-Logfiles für crowdsec an:

touch /etc/crowdsec/acquis.d/setup.nextcloud.yaml
cat <<EOF >>/etc/crowdsec/acquis.d/setup.nextcloud.yaml
#Nextcloud by c-rieger.de
filenames:
- /var/log/nextcloud/nextcloud.log
labels:
type: Nextcloud
---
EOF

Um diese Erweiterungen wirksam werden zu lassen, führen wir noch diesen Befehl zum aktualisieren der Dienste aus:

systemctl daemon-reload && systemctl restart crowdsec.service crowdsec-firewall-bouncer.service

Lassen Sie sich nun die Collections anzeigen und prüfen, ob Nextcloud (Name: nextcloud), NGINX (Name: nginx) und SSH (Name: sshd) mit dem Status „enabled“ dargestellt werden. Ein Blick auf die Szenarien und Parser zeigt uns u.a. die neuen Erweiterungen an:

cscli collections list && cscli scenarios list && cscli parser list

Ab sofort ist Ihr System auf Angriffe wie bspw. Bruteforce-, DDOS- und ähnliche Szenarien vorbereitet und sperrt „kritisch aufgefallene“ IP’s automatisch für bspw. 4 Stunden für ihren Server. Dabei werden u.a. Angriffe auf Nextcloud (logins, Bruteforce u.v.m.), SSH und NGINX analysiert und interpretiert!

Ergänzend zu CrowdSec installieren wir fail2ban.

apt install -y fail2ban --allow-change-held-packages
touch /etc/fail2ban/filter.d/nextcloud.conf
touch /etc/fail2ban/jail.d/nextcloud.local
cat <<EOF >/etc/fail2ban/filter.d/nextcloud.conf
[Definition]
_groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
            ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Two-factor challenge failed:
            ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"
EOF
cat <<EOF >/etc/fail2ban/jail.d/nextcloud.local
[DEFAULT]
maxretry=3
bantime=1800
findtime = 1800
[nextcloud]
backend = auto
enabled = true
port = 80,443
protocol = tcp
filter = nextcloud
maxretry = 5
logpath = /var/log/nextcloud/nextcloud.log
[nginx-http-auth]
enabled = true
EOF
touch /var/log/nextcloud/nextcloud.log
chown -R www-data:www-data /var/log/nextcloud/$NEXTCLOUDDNS.log
systemctl enable --now fail2ban && systemctl restart fail2ban.service

Mittels der Befehle

fail2ban-client status

bzw. konkret

fail2ban-client status sshd && fail2ban-client status nextcloud

lassen sich die Zustände der fail2ban-Jails betrachten.

Installieren wir im Anschluß die serverseitige Firewall namens uncomplicated firewall (ufw). Sofern Sie zuvor den SSH-Port von 22 auf einen anderen Port geändert haben, so müssen Sie die 22 zwingend entsprechend ersetzen!

apt install -y ufw
ufw allow 80/tcp comment "LetsEncrypt (http)"
ufw allow 443/tcp comment "LetsEncrypt (https)"
ufw allow 22/tcp comment "SSH"

Möchten Sie SSH nicht nach außen freigeben (empfohlen!) und nur aus dem internen Netz nutzen, so ersetzen Sie den letzten ufw-Befehl (ufw allow 22/tcp) durch diesen und ersetzen das exemplarische Subnetz durch ihr Subnetz :

ufw allow proto tcp from w.x.y.0/24 to any port 22 comment "SSH nur aus dem LAN"

Setzen Sie das Firewall-Logging auf „medium“ und verhindern nicht definierte eingehende Verbindungen.

ufw logging medium
ufw default deny incoming

Aktivieren Sie die Firewall und starten diese neu:

ufw enable
systemctl restart ufw.service
ufw status verbose

Nextcloud kommuniziert mit verschiedenen Remote-Servern, um gewisse Information verarbeiten, austauschen und bereitstellen zu können:

  • www.nextcloud.com, www.startpage.com, www.eff.org, www.edri.org for checking the internet connection
  • apps.nextcloud.com for the available apps
  • updates.nextcloud.com for Nextcloud updates
  • lookup.nextcloud.com For updating and lookup in the federated sharing addressbook
  • push-notifications.nextcloud.com for sending push notifications to mobile clients
  • surveyserver.nextcloud.com if the admin has agreed to share anonymized data
  • Any remote Nextcloud server that is connected with federated sharing

Quelle: Nextcloud


7. Optimieren & aktualisieren der Nextcloud per Skript

Erstellen Sie ein Skript um den Server, die Nextcloud sowie die aktivierten Apps zu aktualisieren und zu optimieren:

cd /root
wget -O update.sh -q https://codeberg.org/criegerde/nextcloud/raw/branch/master/skripte/update.sh

Alternativ steht Ihnen auch ein Updateskript inklusive der Nextcloud-Office-Docker-Aktualisierung zur Verfügung.

wget -O update.sh -q https://codeberg.org/criegerde/nextcloud/raw/branch/master/skripte/update-nc-office.sh

Markieren Sie das Skript als ausführbar und führen Sie es als privilegierter Benutzer regelmäßig aus.

chmod +x /root/update.sh

Sofern Sie bei der Installation abweichende Pfade oder Softwareversionen verwendet haben, so passen Sie das Skript bitte noch an:

/root/update.sh

Weiterführende Herstellerinformationen:


8. (optional) Nextcloud High Performance Backend für Dateien

Wir beginnen mit der Einrichtung des High Performance Backends für Dateien und wechseln dafür in den Nextcloud App Store. In der Kategorie Werkzeuge findet man die App Client Push.

Alternativ können Sie die App auch über die Kommandozeile installieren:

sudo -u www-data php /var/www/nextcloud/occ app:enable notify_push

Nach der Installation und Aktivierung über den App Store sind die Tätigkeiten in der Nextcloud-Oberfläche bereits abgeschlossen. Weiter geht es hier auf der Kommandozeile des Servers.Als erstes braucht der virtuelle Host für Nextcloud eine kleine Erweiterung

nano /etc/nginx/conf.d/nextcloud.conf

Am Ende der Datei fügen wir die roten Zeilen hinzu:

[...]
location / {
try_files $uri $uri/ /index.php$request_uri;
add_header Alt-Svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400' always;
}
location ^~ /push/ {
proxy_pass http://127.0.0.1:7867/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

}

Starten Sie den Webserver neu:

systemctl restart nginx.service

Das Setup des High Performance Backends für Dateien wird dann über OCC aufgerufen:

cd /var/www/nextcloud
sudo -u www-data php occ notify_push:setup

Sofern die die Konfiguration valide ist, werden weitere Anweisungen angezeigt, um eine systemd Unit für das Nextcloud High Performance Backend für Dateien anzulegen. Dazu öffnen wir eine weitere, zusätzliche SSH-Session und erstellen den Service:

nano /etc/systemd/system/notify_push.service
[Unit]
Description = Push daemon for Nextcloud clients
After=nginx.service php8.3-fpm.service mariadb.service redis-server.service

[Service]
Environment=PORT=7867
Environment=NEXTCLOUD_URL=https://ihre.domain.de
ExecStart=/var/www/nextcloud/apps/notify_push/bin/x86_64/notify_push /var/www/nextcloud/config/config.php
User=www-data
[Install]
WantedBy = multi-user.target

Der Service wird anschließend aktiviert und gestartet:

systemctl daemon-reload
systemctl enable --now notify_push

Sofern der Dienst korrekt gestartet wurde wechseln wir in die erste SSH Session zurück und bestätigen den Dialog mit ENTER. Sollten app-Updates kommen, so wird ein Serviceneustart benötigt.

systemctl restart notify_push.service

Die Konfiguration können Sie wie folgt verifizieren:

sudo -u www-data php occ notify_push:setup https://ihre.domain.de/push

Um die Funktionalität des Nextcloud HPB für Dateien zu überprüfen, laden Sie sich den Nextcloud-„test_client“ herunter

wget -O test_client -q https://github.com/nextcloud/notify_push/releases/download/v0.6.11/test_client-x86_64-unknown-linux-musl

und starten diesen gefolgt von Ihrer Domain, dem Benutzer und dem dazugehörigen Passwort. Ist bereits 2FA aktiv, so nutzen Sie ein App-Passwort.

chmod +x test_client
./test_client https://<ihre.domain.de> <Nextcloud-Benutzername> <(App-)Passwort>

und laden bspw. eine Datei in Ihre Cloud hoch. Sehen Sie dann im Nextcloud test_client-Tool Aktivitäten, so funktioniert das Nextcloud HPB für Dateien. Löschen Sie im Anschluß an Ihre Tests den Client, um spätere Probleme beim Aktualisieren der Nextcloud zu vermeiden.

rm -f test_client

Die Einrichtung des High Performance Backends für Dateien ist somit erfolgreich abgeschlossen.


9. (optional) bash_aliases und empfohlene Settings (config.php)

Passen Sie die Datei /root/bash_aliases an, um das Nextcloud Toolset occ direkt mittels nocc starten zu können

if [ ! -f /root/.bash_aliases ]; then touch /root/.bash_aliases; fi
cat <<EOF >> /root/.bash_aliases
alias nocc="sudo -u www-data php /var/www/nextcloud/occ"
EOF
source /root/.bash_aliases

Ab sofort können Sie als priviligierter Benutzer (sudo -s) die Nextcloud occ-Tools direkt per „nocc … “ ausführen, bspw:

nocc app:list

um sich bspw. alle aktivierten und deaktivierten Apps Ihrer Nexctloud anzeigen zu lassen. Wir empfehlen folgende Settings zu setzen:

nocc config:system:set remember_login_cookie_lifetime --value="3600"
nocc config:system:set log_rotate_size --value="104857600"
nocc config:system:set trashbin_retention_obligation --value="auto, 7"
nocc config:system:set versions_retention_obligation --value="auto, 365"
nocc config:system:set simpleSignUpLink.shown --type=bool --value=false
nocc config:system:set upgrade.disable-web --type=bool --value=true
nocc config:app:set text workspace_available --value=0
nocc config:system:set loglevel --value="2"
nocc config:app:set settings profile_enabled_by_default --value="0"
#nocc app:enable admin_audit
#nocc config:app:set admin_audit logfile --value="/var/log/nextcloud/audit.log"
#nocc config:system:set log.condition apps 0 --value admin_audit

Chunk-Größe setzen oder mit ‚0‘ deaktivieren

nocc config:app:set files max_chunk_size --value="104857600"
oder
nocc config:app:set files max_chunk_size --value 0

Um das Session-/Anmeldeverhalten zu verändern, können Sie diese Einstellungen in der config.php und php.ini wie exemplarisch gezeigt anpassen. Die Berechnung erfolgt bspw. so: 60s*60m*2h = 7200

nano /var/www/nextcloud/config/config.php

[...]
'remember_login_cookie_lifetime' => 7200,
'session_lifetime' => 7200,
'session_keepalive' => true,
'auto_logout' => true,
[...]
nano /etc/php/8.5/fpm/php.ini
[...]
session.gc_maxlifetime = 7200
[...]

Starten Sie die Dienste neu, um das Logoutverhalten zu aktivieren

systemctl restart php8.5-fpm.service nginx.service

Eine weiterführende Übersicht an Nextcloud-Einstellungen finden Sie hier.

Um die manuelle Logrotation einzurichten, bspw. für die nextcloud.log und audit.log Dateien, gehen Sie wie folgt vor:

sed -i '/log_rotate_size/d' /var/www/nextcloud/config/config.php
nocc config:system:set log_rotate_size --value="0"
nano /etc/logrotate.d/nextcloud-audit

Fügen Sie alles Nachfolgende hinzu, speichern und verlassen dann diese Datei:

/var/log/nextcloud/*.log {
su root adm
size 100M
missingok
rotate 30
compress
delaycompress
notifempty
sharedscripts
}

Um das Logrotating zu testen bzw. initial zu starten und auszuführen können Sie folgende Befehle nutzen:

logrotate -d /etc/logrotate.d/nextcloud-audit
logrotate --force /etc/logrotate.d/nextcloud-audit

Das Logrotating wurde somit systemseitig eingestellt und Nextcloud-seitig deaktiviert.


10. (optional): Verbesserung der Sicherheit und Performance des TCP-Stacks

Die empfohlene Anpassungen sind nachfolgend aufgelistet. Wie sie diese Werte auf einmal setzen, das wird im Anschluß beschrieben:

# Schutz gegen IP-Spoofing (IPv4 und IPv6)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Schutz gegen TCP-SYN-Flooding (IPv4)
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_synack_retries = 2
net.core.somaxconn = 1024

# ICMP Echo Ignore Broadcasts (IPv4)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# ICMP Redirects deaktivieren (IPv4 und IPv6)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Sourcen-Routing deaktivieren (IPv4 und IPv6)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# TCP-Timestamps deaktivieren (IPv4)
net.ipv4.tcp_timestamps = 0

# Loggen von Martian-Paketen (IPv4 und IPv6)
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv6.conf.all.log_martians = 1
net.ipv6.conf.default.log_martians = 1

# Maximale Anzahl von halb offenen Verbindungen (IPv4)
net.ipv4.tcp_max_syn_backlog = 4096

# Netzwerkspeichergrößen erhöhen (IPv4 und IPv6)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.optmem_max = 40960

# Maximale Anzahl von Verbindungstrackings erhöhen (IPv4 und IPv6)
net.netfilter.nf_conntrack_max = 262144
net.netfilter.nf_conntrack_tcp_timeout_established = 1800

# Maximaler Backlog für Netzwerkgeräte erhöhen (IPv4 und IPv6)
net.core.netdev_max_backlog = 5000

# TCP-Verbindungseinstellungen optimieren (IPv4)
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15

# Datei-Deskriptor-Limits erhöhen
fs.file-max = 2097152

# TCP-Warteschlangen (Read/Write Queues) erhöhen (IPv4)
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# TCP-Window-Scaling aktivieren (IPv4)
net.ipv4.tcp_window_scaling = 1

# TCP-Memory-Management optimieren (IPv4)
net.ipv4.tcp_mem = 50576 64768 98152

# Reverse Path Filtering aktivieren (IPv4 und IPv6)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv6.conf.all.rp_filter = 1
net.ipv6.conf.default.rp_filter = 1

# TCP Fast Open aktivieren (optional, IPv4)
net.ipv4.tcp_fastopen = 3

# ARP-Caching verbessern (IPv4)
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096

Um die zuvor beschriebenen Einstellungen zur Härtung und Optimierung des TCP-Stacks umzusetzen können führen Sie folgenden Befehl aus:

wget -O /etc/sysctl.d/100-nextcloud.conf -q https://codeberg.org/criegerde/nextcloud/raw/branch/master/etc/sysctl.d/100-nextcloud.conf

Nachdem die Datei heruntergeladen wurde starten Sie den Server einmalig neu.

reboot now

Sie können nach dem Neustart alle Werte wie folgt überprüfen:

sudo -s
sysctl -A

Möchten Sie diese Einstellungen rückgängig machen, so benennen Sie die Datei bspw. in disabled um

mv /etc/sysctl.d/100-nextcloud.conf /etc/sysctl.d/100-nextcloud.conf.disabled

und starten anschleßend den Server neu.

Über Ihre Unterstützung würden wir uns sehr freuen – vorab vielen und herzlichen Dank dafür.

Unterstützung mit WERO