Nextcloud 22 Installation mit Nginx, MariaDB, PHP7.4, LetsEncrypt, Redis und Fail2Ban
14 min read

Nextcloud 22 Installation mit Nginx, MariaDB, PHP7.4, LetsEncrypt, Redis und Fail2Ban

In diesem Beitrag wird der komplette Installationsablauf für die Inbetriebnahme von Nextcloud v22 auf einem Ubuntu Server 20.04 LTS behandelt.
Nextcloud 22 Installation mit Nginx, MariaDB, PHP7.4, LetsEncrypt, Redis und Fail2Ban

Inhalt:

Vorwort

Als Basis für den gesamten Artikel dient mir eine Virtuelle Maschine mit folgenden Eigenschaften:

  • OS: Ubuntu 20.04 LTS
  • 4 CPU Kerne
  • 8 GB Ram
  • 200 GB SSD Speicherplatz

Desweiteren wird der LEMP Stack zum Einsatz kommen, das heißt ich werde auf:

  • Ubuntu (Linux) als Betriebssystem,
  • Nginx als Webbrowser,
  • MariaDB als Datenbankserver
  • und PHP7.4 setzen.

Die Installation von Nginx, MariaDB und PHP 7.4 wird in folgenden Abschnitten noch ausführlich beschrieben. Der Zeitaufwand für die Installation sollte hierbei 3 Stunden nicht überschreiten, wenn wenig Kenntnisse vorhanden sind.


Vorbereitungen

Bevor wir starten, sollte das System und alle Programme noch auf den aktuellen Stand gebracht werden, dies geschieht mit folgendem Befehl:

apt update && apt upgrade -y && apt autoremove

Nginx

Anschließend füge ich noch die Paketquellen des Mainline Repository von Nginx ein, um aktuellere Versionen des Webservers zu erhalten, als in den Standard Ubuntu Paketquellen freigegeben sind.Zuerst wird der Key hinzugefügt:

wget -O - http://nginx.org/keys/nginx_signing.key | apt-key add -

Anschließend können die Paketquellen hinzugefügt werden:

nano /etc/apt/sources.list.d/nginx.list
# Nginx (Mainline)
deb [arch=amd64] http://nginx.org/packages/mainline/ubuntu/ focal nginx
deb-src [arch=amd64] http://nginx.org/packages/mainline/ubuntu/ focal nginx

Danach kann Nginx wie gewohnt installiert werden:

apt update && apt install nginx

MariaDB

Das gleiche Vorgehen erledigen wir noch für MariaDB um auch hier eine neuere Version - aktuell 10.5 - zu erhalten: Key:

sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'

Und wie bei Nginx, auch hier die neuen Paketquellen hinzufügen:

nano /etc/apt/sources.list.d/MariaDB.list
# MariaDB 10.5 repository list
# http://downloads.mariadb.org/mariadb/repositories/
deb [arch=amd64] http://mirror.netcologne.de/mariadb/repo/10.5/ubuntu focal main
deb-src http://mirror.netcologne.de/mariadb/repo/10.5/ubuntu focal main

Und die gewohnte Installation über den APT Paketmanager:

apt update && apt install mariadb-server

PHP

Bei PHP werde ich die letzte Stable Version in den Ubuntu Paketquellen verwenden. Warum kein PHP8? - Beim Testen gab es mit einigen Submodulen noch Probleme, deshalb bleibt es vorerst bei Version 7.4 .Die benötigten Pakete beziehen wir über folgenden Befehl:

apt-get install php7.4 php-fpm php-gd php-mysql php-curl php-xml php-zip php-intl php-mbstring php-bz2 php-json php-apcu php-imagick php-gmp php-bcmath

Zusätzliche Pakete:

Ab Nextcloud Version 21 wird zusätzlich noch ImageMagick benötigt, dies ist recht simpel zu erledigen, ebenso die Erweiterung um den Support für SVG Dateien:

apt install imagemagick libmagickcore-6.q16-6-extra

ACME.sh - LetsEncrypt Zertifikate beantragen und managen

Zum Beantragen der SSL Zertifikate greife ich später auf dem ACME.sh Client zurück, dieser sollte nicht als root User ausgeführt werden, deshalb legen wir zunächst einen neuen User an, der sich künftig um das Management der Zertifikate kümmern wird:

adduser letsencrypt

Anschließend wird der User der »www-data« Gruppe hinzugefügt, damit er den Webserver verwalten kann:

usermod -a -G www-data letsencrypt

Jetzt müssen noch die Berechtigungen für den letsencrypt User vergeben werden, denn momentan kann dieser noch nicht den Webserver neu starten ohne das root Kennwort einzugeben, da das Management jedoch automatisch ablaufen soll, ändern wir mit

visudo

noch den Inhalt der Datei und fügen am Schluss folgende Zeile ein:

letsencrypt ALL=NOPASSWD: /bin/systemctl reload nginx

Jetzt sollten die Berechtigungen soweit richtig gesetzt sein, wir wechseln in den neu erstellten letsencrypt User und installieren acme.sh:

su - letsencrypt
curl https://get.acme.sh | sh -s [email protected]

Die angegebene Mailadresse wird verwendet um euch über bald ablaufende Zertifikate zu informieren - also potentiellen Handlungsbedarf für den Administrator. Anschließend kann die Session mit exit verlassen werden.


Konfiguration der einzelnen Programme

Einrichtung von Nginx

Die Nginx Konfiguration ist recht schnell über die folgenden Konfigurationsdateien abgebildet. Die Basis dazu war nginxconfig.io und ich habe die Dateien auf meine Bedürfnisse zugeschnitten: Zuerst widmen wir uns der »nginx.conf« Datei, der "Steuereinheit" für den Webserver, diese Datei erhält folgenden Inhalt:

nano /etc/nginx/nginx.conf
user                 www-data;
pid                  /run/nginx.pid;
worker_processes     auto;
worker_rlimit_nofile 65535;

events {
    multi_accept       on;
    worker_connections 65535;
}

http {
    charset              utf-8;
    sendfile             on;
    tcp_nopush           on;
    tcp_nodelay          on;
    server_tokens        off;
    log_not_found        off;
    types_hash_max_size  2048;
    client_max_body_size 16M;

    # MIME
    include              mime.types;
    default_type         application/octet-stream;

    # Logging
    access_log           /var/log/nginx/access.log;
    error_log            /var/log/nginx/error.log warn;

    # SSL
    ssl_session_timeout  1d;
    ssl_session_cache    shared:SSL:10m;
    ssl_session_tickets  off;

    # Mozilla Modern configuration
    ssl_protocols        TLSv1.3;

    # OCSP Stapling
    ssl_stapling         on;
    ssl_stapling_verify  on;
    resolver             1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] valid=60s;
    resolver_timeout     2s;

    # Load configs
    include              /etc/nginx/conf.d/*.conf;
    include              /etc/nginx/sites-enabled/*;
}

Anschließend erstellen wir ein Unterverzeichnis, welches unsere zusätzlichen Konfigurationsdateien beinhalten wird:

mkdir -p /etc/nginx/configs

Anschließend erstellen wir die »general.conf« Datei und betanken diese mit unten stehendem Inhalt:

nano /etc/nginx/configs/general.conf
# favicon.ico
location = /favicon.ico {
    log_not_found off;
    access_log    off;
}

# robots.txt
location = /robots.txt {
    log_not_found off;
    access_log    off;
}

# assets, media
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
    expires    7d;
    access_log off;
}

# svg, fonts
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
    add_header Access-Control-Allow-Origin "*";
    expires    7d;
    access_log off;
}

# gzip
gzip            on;
gzip_vary       on;
gzip_proxied    any;
gzip_comp_level 6;
gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

Und gleich darauf wird noch die »security.conf« Datei erstellt, welche Zusatzinformationen wie Header beinhalten wird:

nano /etc/nginx/configs/security.conf
add_header X-Frame-Options           "SAMEORIGIN" always;
add_header X-XSS-Protection          "1; mode=block" always;
add_header X-Content-Type-Options    "nosniff" always;
add_header Referrer-Policy           "no-referrer" always;
add_header Content-Security-Policy   "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# . files
location ~ /\.(?!well-known|file).* {
        deny all;
}

Anschließend kann Nginx noch gestartet werden, sowie der Befehl abgesetzt werden, dass der Webserver nach einem Neustart automatisch startet:

systemctl start nginx
systemctl enable nginx
systemctl status nginx

Ist nach Absetzen des letzten Befehles abzusehen, dass der Webserver läuft, können wir uns der Einrichtung von MariaDB widmen.

Einrichtung von MariaDB

Da der Datenbankserver erst neu installiert wird, wird die Einrichtung über das Absetzen des Befehls

mysql_secure_installation

gestartet. Hierbei wird das Kennwort für den root User vergeben, alle anderen Fragen der Installationsroutine können mit "Ja" bzw. Y/J beantwortet werden.

Einrichtung von PHP

PHP benötigt einige tiefergehende Änderungen, zuerst widmen wir uns der »www.conf« Datei:

nano /etc/php/7.4/fpm/pool.d/www.conf

Hier sollten folgende Änderungen bzw. Checks durchgeführt werden, die Datei habe ich zur besseren Lesbarkeit entsprechend eingekürzt:

user = www-data
group = www-data

[...]

listen = /run/php/php7.4-fpm.sock

[...]

# Durch entfernen der Semikolons am Zeilenbeginn werden die Umgebungsvariablen aktiviert
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

Jetzt folgen noch zwei weitere Dateien zur Bearbeitung:

nano /etc/php/7.4/fpm/php.ini
cgi.fix_pathinfo = 0

memory_limit = 512M

opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 1
opcache.save_comments = 1

Erklärung:

  • »cgi.fix_pathinfo«: Sorgt für eine sichere Interpretation von Pfadangaben
  • »memory_limit«: Dieser Wert gibt an, wie viel Speicher ein PHP-Skript nutzen darf. Nextcloud benötigt mindestens 512 MB als Memory Limit
  • »OPcache«: PHP OPcache ermöglicht bessere Performance durch das Ablegen vorkompilierten Bytecodes in den Arbeitsspeicher.

Die Einträge liegen auskommentiert vor und müssen durch Entfernen des »;« noch scharf geschalten werden.

Tipp: Unter nano lässt sich durch die Tastenkombination »Strg + W« nach beliebigen Einträgen suchen! Die letzte benötigte Datei beinhaltet die Informationen für die CLI Version von PHP und wird wie folgt abgeändert:

nano /etc/php/7.4/cli/php.ini
cgi.fix_pathinfo = 0

apc.enable_cli = 1

»apc.enable« muss mit Version 21 aktiv gesetzt werden, andernfalls kommt es zu Fehlermeldungen oder der Arbeitsspeicher läuft euch wieder und wieder voll.

service php7.4-fpm restart

Mit obigem Restart lassen wir getätigte Änderungen wirksam werden.

Beantragen der SSL Zertifikate

Hier müssen zunächst einige Verzeichnisse erstellt werden, wo die Zertifikate verwaltet und gespeichert werden:

mkdir -p /etc/letsencrypt/nextcloud.domain.tld/rsa
mkdir -p /etc/letsencrypt/nextcloud.domain.tld/ecc
chown -R www-data:www-data /etc/letsencrypt
chmod -R 775 /etc/letsencrypt

Anschließend können wir unser Bash Script einrichten. Da ich die Authentifizierung via DNS API benutze, müssen vorab noch Informationen von Cloudflare übergeben werden. Die Informationen umfassen eure Account ID sowie einen Token, der euch zum Ändern von DNS Einträgen berechtigt. Beides lässt sich dem Dashboard auf der rechten Seite entnehmen:

Den Token kann man sich unter »Profil« - »API Token« erstellen lassen:

Diese beiden Parameter werden wie folgt übergeben:

export CF_Account_ID="<eure_CF_ID>"
export CF_Token="<Token>"

Anschließend können die Zertifikate beantragt werden, dies geschieht über die beiden Befehle, die ich aus der Doku zusammengebaut habe. Zuerst beantrage ich die ECC Zertifikate, im zweiten Command werden die Zertifikate gleich noch installiert.

acme.sh --issue --dns dns_cf --ecc --accountemail "[email protected]" -d nextcloud.domain.tld --keylength ec-384 --key-file /etc/letsencrypt/nextcloud.domain.tld/ecc/key.pem --ca-file /etc/letsencrypt/nextcloud.domain.tld/ecc/ca.pem --cert-file /etc/letsencrypt/nextcloud.domain.tld/ecc/cert.pem --fullchain-file /etc/letsencrypt/nextcloud.domain.tld/ecc/fullchain.pem --reloadcmd "systemctl reload nginx"

acme.sh --install-cert -d nextcloud.domain.tld --key-file /etc/letsencrypt/nextcloud.domain.tld/ecc/key.pem --fullchain-file /etc/letsencrypt/nextcloud.domain.tld/ecc/fullchain.pem --reloadcmd "service nginx reload" --ecc

Danach das gleiche Spiel noch einmal, diesmal für RSA Zertifikate. Diese werden ebenso im Zweiten Command installiert.

acme.sh --issue --dns dns_cf -d nextcloud.domain.tld --keylength 4096 --key-file /etc/letsencrypt/nextcloud.domain.tld/rsa/key.pem --ca-file /etc/letsencrypt/nextcloud.domain.tld/rsa/ca.pem --cert-file /etc/letsencrypt/nextcloud.domain.tld/rsa/cert.pem --fullchain-file /etc/letsencrypt/nextcloud.domain.tld/rsa/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx"

acme.sh --install-cert -d nextcloud.domain.tld --key-file /etc/letsencrypt/nextcloud.domain.tld/rsa/key.pem --fullchain-file /etc/letsencrypt/nextcloud.domain.tld/rsa/fullchain.pem --reloadcmd "service nginx reload"

Installation

vHost für Nextcloud anlegen

Die Vorarbeit ist getan, jetzt fehlt noch der vHost für Nginx, der später unsere Nextcloud ausliefern wird. Meine Konfiguration basiert auf der ausgeschriebenen Config aus dem Admin Manual und wurde nach meinen Wünschen abgeändert:

sudo nano /etc/nginx/conf.d/nextcloud.domain.tld.conf
upstream php-handler {
   #server 127.0.0.1:9000;
    server unix:/var/run/php/php7.4-fpm.sock;
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name nextcloud.domain.tld;

    # SSL configuration
    # SSL ECC
    ssl_certificate /etc/letsencrypt/nextcloud.domain.tld/ecc/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/nextcloud.domain.tld/ecc/key.pem;

    # SSL RSA
    ssl_certificate /etc/letsencrypt/nextcloud.domain.tld/rsa/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/nextcloud.domain.tld/rsa/key.pem;

    ssl_trusted_certificate /etc/letsencrypt/nextcloud.domain.tld/ecc/ca.pem;

    # Include headers
    include /etc/nginx/configs/security.conf;
    
    #specific Nextcloud Headers until Version 21.0.2
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;

    #
    # Nextcloud configuration
    #

    # Path to the root of your installation
    root /var/www/nextcloud/;

    # set max upload size
    client_max_body_size 10G;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    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 application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject 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;

    # Pagespeed is not supported by Nextcloud, so if your server is built
    # with the 'ngx_pagespeed' module, uncomment this line to disable it.
    #pagespeed off;

    # Specify how to handle directories -- specifying '/index.php$request_uri'
    # here as the fallback means that Nginx always exhibits the desired behaviour
    # when a client requests a path that corresponds to a directory that exists
    # on the server. In particular, if that directory contains an index.php file,
    # that file is correctly served; if it doesn't, then the request is passed to
    # the front-end controller. This consistent behaviour means that we don't need
    # to specify custom rules for certain paths (e.g. images and other assets,
    # '/updater', '/ocm-provider', '/ocs-provider'), and thus
    # 'try_files $uri $uri/ /index.php$request_uri'
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Rule borrowed from '.htaccess' to handle Microsoft DAV clients
    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;
    }

    proxy_cookie_path / "/; HTTPOnly; Secure";

    # logging
    access_log /var/log/nginx/cloud.access.log;
    error_log /var/log/nginx/cloud.error.log warn;

    # Make a regex exception for '/.well-known' so that clients can still
    # access it despite the existence of the regex rule
    # 'location ~ /(\.|autotest|...)' which would otherwise handle requests
    # for '/.well-known'.
    location ^~ /.well-known {
        # The following 6 rules are borrowed from '.htaccess'

        location = /.well-known/carddav     { return 301 /remote.php/dav/; }
        location = /.well-known/caldav      { return 301 /remote.php/dav/; }
        # Anything else is dynamically handled by Nextcloud
        location ^~ /.well-known            { return 301 /index.php$uri; }

        try_files $uri $uri/ =404;
    }

    # Rules borrowed from '.htaccess' to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }

    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends '/index.php'
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        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;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;

        fastcgi_read_timeout 600;
        fastcgi_send_timeout 600;
        fastcgi_connect_timeout 600;

        fastcgi_param PHP_VALUE "upload_max_filesize = 10G
        post_max_size = 10G
        max_execution_time = 3600
        output_buffering = off";
    }

    location ~ \.(?:css|js|svg|gif)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;         # Cache-Control policy borrowed from '.htaccess'
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from '.htaccess'
        access_log off;     # Optional: Don't log access to assets
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}

server {
    listen 80;
    listen [::]:80;
    server_name nextcloud.domain.tld;
    # enforce https
    return 301 https://nextcloud.domain.tld$request_uri;
}

Ob bis zu diesem Punkt alles geklappt hat erfahrt ihr via »nginx -t«, mit »systemctl restart nginx« wird der Webserver im Anschluss noch neu gestartet.

Download der Serverfiles

Die letzte Stable Version von Nextcloud laden wir uns zunächst auf unser System, entpacken es anschließend und verschieben es an den künftigen Speicherort im Webroot:

wget https://download.nextcloud.com/server/releases/latest.tar.bz2
tar -xjf latest.tar.bz2 -C /var/www
rm latest.tar.bz2

Anschließend werden die Berechtigungen für den Nextcloud Ordner angepasst:

chown -R www-data:www-data /var/www/nextcloud

Datenverzeichnis anlegen

Im Admin Manual wird explizit geraten, die Daten die in der Nextcloud gespeichert werden, nicht im Webroot abgelegt werden. Hierfür erstelle ich einen Ordner außerhalb und gebe anschließend die Berechtigungen an den www-data User ab.

mkdir -p /var/nextcloud_data 
chown -R www-data:www-data /var/nextcloud_data

Datenbank und Datenbankverbindung anlegen

CREATE USER [email protected] IDENTIFIED BY 'PasSw0rT';
CREATE DATABASE nextcloud_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES on nextcloud_db.* to [email protected];
FLUSH privileges;
exit;

Nextcloud Setup

Die Vorarbeit ist geschafft. Navigiert jetzt zu eurer Domain (https://nextcloud.domain.tld) und gebt alle benötigten Daten an.

Wenn ihr soweit seid, schließt das Setup mit "Installation abschließen" ab. Nach einem kurzen Moment solltet ihr eingeloggt in der Cloud ankommen.


Warnungen im Admin Bereich / Nacharbeit

Cronjob anlegen

Nextcloud setzt nach Standard Installation AJAX zur Bewältigung von Hintergrundaufgaben ein, das heißt aber auch, dass Datenbankbereinigungen etc. nur dann ausgeführt werden, wenn jemand aktiv in der Cloud ist. Das möchte ich dringend ändern und werde es in einen Cronjob auslagern, der diese Hintergrundaufgaben alle 5min anstößt - auch wenn niemand angemeldet ist. Zuerst öffnet man crontab als »www-data« User, anschließend kommt folgender Cronjob neu hinzu:

sudo -u www-data crontab -e
*/5 * * * * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1

config.php - Nacharbeiten

Die config.php beinhaltet Instruktionen für die Nextcloud Instanz, es fehlen jedoch noch ein paar Nacharbeiten um zum Einen Fehlermeldungen zu verhindern und zum anderen den Betrieb zusätzlich noch etwas abzusichern, diese Änderungen habe ich an meinen Instanzen vorgenommen:

sudo nano /var/www/nextcloud/config/config.php
# Standard Telefonregion
'default_phone_region' => 'DE',
# Memory-Caches für PHP
'memcache.local' => '\OC\Memcache\APCu',
'overwriteprotocol' => 'https',
# Anpassen der Sprache und Zeitzone
'logtimezone' => 'Europe/Berlin',
'force_language' => 'de',
'force_locale' => 'de_DE',

Redis Setup

Zwei weitere Vorteile bietet der Redis Server für die neu erstellte Nextcloud Instanz: Zum einen wird Last vom Datenbankserver genommen, zum anderen kann die Cloud »Transactional File Locking« verwenden. Hierbei werden Sperren auf aktuell zu bearbeitende Dateien gesetzt, sodass bei parallelem Arbeiten keine Fortschritte überschrieben werden können. Ohne diese Sperren würde immer der zuletzt übermittelte Stand durchgesetzt werden.

Installation und Konfiguration des Redis-Server

Zunächst wird Redis und das dazugehörige PHP-Modul installiert:

apt update && apt install redis-server php-redis
nano /etc/redis/redis.conf

Anstatt die Anfragen auf Ports lauschen zu lassen, empfiehlt es sich, Redis so zu konfigurieren, dass Sockets verwendet werden. Hierzu muss die Konfigurationsdatei wie folgt abgeändert werden:

unixsocket /var/run/redis/redis-server.sock 
unixsocketperm 770
port 0 

Die Konfiguration hat folgende Auswirkungen:

  • port: Standardmäßig nutzt Redis den Port 6379, mit der Änderung auf 0 wird stattdessen ein Socket genutzt
  • unixsocket: Der ab jetzt zu verwendende Socket
  • unixsocketperm: Berechtigungen für den Socket, diese müssen angepasst werden, ansonsten wirft Nextcloud im Anschluss Berechtigungsfehler

Im Anschluss muss der Redis-User noch der Webserver Gruppe »www-data« hinzugefügt werden:

usermod -a -G redis www-data

Um die Änderungen zu übernehmen, wird der Redis-Server noch neu gestartet:

systemctl restart redis-server

Einbinden in die Nextcloud

Damit die eigene Cloud nun auch Redis nutzt, muss dieses noch in der Nextcloud-Konfiguration angepasst werden:

Bisher läuft Redis zwar, ist aber momentan noch nicht in die Nextcloud integriert. Hierzu müssen noch Änderungen in der Konfigurationsdatei vorgenommen werden.

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

Am Ende der Datei wird folgende Konfiguration hinzugefügt:

<?php
$CONFIG = array (
[...]
'filelocking.enabled' => 'true',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => array (
     'host' => '/var/run/redis/redis-server.sock',
     'port' => 0,
     'timeout' => 0.0,
      ),
[...]
); // Ende der Config

Hinweis: Bei mir führte die Änderung zu Fehlermeldungen bis zur Nichterreichbarkeit der Cloud. Ursache scheint hierbei folgende Zeile zu sein:

'memcache.local' => '\\OC\\Memcache\\APCu',

Füge ich den Code Block für die Redis Konfiguration über dieser Zeile ein, funktioniert alles problemlos.

Fail2Ban Setup

Da die eingebaute Bruteforce Protection für mich bis zum aktuellen Zeitpunkt nicht optimal aufgebaut ist, wird auf Fail2Ban zurückgegriffen, dieses Tool kann normal über die Paketquellen nachinstalliert werden und wird im Anschluss mit einem eigenen Jail (Gefängnis, in Fail2Ban eine Art Konfigurationsdatei pro überwachtem Dienst) angesprochen.

apt update && apt install fail2ban

Jetzt wird wie oben beschrieben, ein eigenes Jail erstellt:

nano /etc/fail2ban/filter.d/nextcloud.local
[Definition] 
failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$ 
            ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$ 
            ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: <HOST>\).*}$

Damit das Nextcloud Jail aktiviert werden kann, erfolgt jetzt noch das Scharf schalten in der Konfigurationsdatei:

nano /etc/fail2ban/jail.local
[DEFAULT]
maxretry=3
bantime=86400

[nextcloud]
enabled=true
port=80,443
protocol=tcp
filter=nextcloud
logpath=/var/nextcloud_data/nextcloud.log

[nginx-http-auth]
enabled = true

Im [DEFAULT] Tab werden die allgemeinen Regeln festgelegt, hier also die maximalen Versuche (maxretry) bis Fail2Ban einschreitet und die Bandauer (bantime) ausformuliert in Sekunden. Unter [nextcloud] wird das eigentliche Jail definiert und angesprochen:

  • enabled => Aktivierung der Regel
  • port => Zu überwachende Ports, hier HTTP(S) Ports
  • protocol => zu verwendendes Protokoll, hier TCP
  • logpath => Pfad zur Logdatei eurer Instanz, solltet ihr die Logging Einstellungen abgeändert haben, passt diesen Pfad an eure Gegebenheiten an

Im Anschluss wird fail2ban neu gestartet:

service fail2ban restart

Bei Bedarf kann nachgeschaut werden, welche IP Adressen aktuell gesperrt sind, dies geschieht mit folgendem Befehl:

fail2ban-client status nextcloud