
Um die Last auf mehrere Nextcloud Instanzen zu verteilen schalten wir einen Loadbalancer (HAProxy) vor die Nextcloud Webserver. Zudem verschlüsseln wir die Kommunikation mit SSL sowohl nach extern, als auch nach intern.
In diesem Beispiel nutzen wir folgende Ubuntu 20 Server:
- haproxy – 192.168.2.205
- nc1 – 192.168.2.206
- nc2 – 192.168.2.207
Zuerst passen wir die hosts-Datei auf allen Servern an:
sudo -s
nano /etc/hosts
# Server: haproxy 127.0.0.1 localhost 127.0.1.1 haproxy ... 192.168.2.205 haproxy 192.168.2.206 nc1 192.168.2.207 nc2

# Server: nc1 127.0.0.1 localhost 127.0.1.1 nc1 ... 192.168.2.205 haproxy 192.168.2.206 nc1 192.168.2.207 nc2

# Server: nc2 127.0.0.1 localhost 127.0.1.1 nc2 ... 192.168.2.205 haproxy 192.168.2.206 nc1 192.168.2.207 nc2

Nun aktualisieren wir den haproxy-Server und installieren den HAProxy-Loadbalancer:
apt update && apt upgrade -y
apt-get install --no-install-recommends software-properties-common add-apt-repository ppa:vbernat/haproxy-2.2 apt install haproxy=2.3.\*
Am Beispiel von self signed SSL-Zertifikaten verschlüsseln wir sowohl die Kommunikation zum Loadbalancer, als auch die Kommunikation zwischen dem Loadbalancer und den Nextcloud-Instanzen. Um das realisieren zu können installieren wir
apt install ssl-cert
und generieren uns neue self-signed SSL_Zertifikate
make-ssl-cert generate-default-snakeoil -y
Um diese Zertifikate im HAProxy nutzen zu können, fügen wir das Zertifikat und den PrivatKey in eine Datei zusammen:
cat /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem > /etc/haproxy/server.pem

Zudem generieren wir uns ein dhparam.pem-File, um auch den Schlüsselaustausch selbst abzusichern:
openssl dhparam -out /etc/haproxy/dhparam.pem 4096
Die Vorbereitungen sind nun abgeschlossen, so dass wir den HAProxy konfigurieren können. Beginnen wir mit einer Sicherungskopie der Standardkonfiguration.
cd /etc/haproxy
cp haproxy.cfg haproxy.cfg.bak
Öffnen Sie dann die Konfigurationsdatei und ersetzen den kompletten Inhalt mit dem nachfolgenden Block:
global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s user haproxy group haproxy daemon # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ssl-dh-param-file /etc/ssl/certs/dhparam.pem defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http listen stats bind :8443 ssl crt /etc/haproxy/server.pem alpn h2,http/1.1 ssl-min-ver TLSv1.2 mode http stats enable stats show-legends stats hide-version stats refresh 30s stats show-node stats uri / frontend c-rieger.de mode http bind :80 bind :443 ssl crt /etc/haproxy/server.pem alpn h2,http/1.1 ssl-min-ver TLSv1.2 acl url_discovery path /.well-known/caldav /.well-known/carddav http-request redirect location /remote.php/dav/ code 301 if url_discovery redirect scheme https code 301 if !{ ssl_fc } http-response set-header Strict-Transport-Security max-age=63072000 acl is_certbot path_beg /.well-known/acme-challenge/ use_backend LetsEncrypt if is_certbot default_backend NextcloudServer backend NextcloudServer balance leastconn cookie SERVERID insert indirect nocache server server1 192.168.2.206:443 check maxconn 20 ssl verify none ca-file /etc/haproxy/server.pem cookie nc1 server server2 192.168.2.207:443 check maxconn 20 ssl verify none ca-file /etc/haproxy/server.pem cookie nc2 backend LetsEncrypt mode http server certbot 127.0.0.1:9080
Nach dem Speichern der Konfigurationsdatei, gefolgt von einem Neustart des HAProxys
service haproxy restart
können Sie die Status-Seite des Loadbalancers bereits aufrufen (https://192.168.2.205:8443):
Vorausgesetzt, Sie haben die Nextcloud-Instanzen (Backends) bereits aufgesetzt (Lesen Sie mehr in diesem Artikel), so können Sie diese „lastverteilt“/“gebalanced“ über https://192.168.2.205 erreichen.
Überprüfen Sie sowohl in der Nextcloud, als auch in der Browserkonsole das Balancingverhalten. Dazu sehen Sie sich zum Einen die System-Einstellungen der Nextcloud an und vollziehen dort visuell nach, auf welchem Node (Knoten/Server) Sie sich befinden. Zum Anderen sehen Sie sich das Pendant, also den vom HAProxy gesetzten Cookie, in der Browserkonsole an. Beide spiegeln im Beispiel den Server nc1 wider.

Möchten Sie Let’s Encrypt Zertifikate nutzen, so installieren Sie die Let’s Encrypt Software certbot:
add-apt-repository -y ppa:certbot/certbot
apt update && apt install -y certbot
Mittels des Kommandozeilentools certbot requestieren wir die SSL Zertifikate
certbot certonly --standalone --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 -d ihre.domain.de --email ihre@domain.de --agree-tos --non-interactive
und nutzen dann ein Skript um alle Zertifikate zu konsolidieren:
nano /etc/haproxy/le-certificates.sh
#!/bin/bash for CERTIFICATE in `find /etc/letsencrypt/live/* -type d`; do CERTIFICATE=`basename $CERTIFICATE` cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/haproxy/server.pem done exit 0
Nun machen wir das Skript noch ausführbar
chmod +x /etc/haproxy/le-certificates.sh
und führen es aus.
/etc/haproxy/le-certificates.sh
Nach einem Neustart des HAProxy-Services
services haproxy restart
werden die neuen Let’s Encypt SSL-Zertifikate schon verwendet.
Um die Zertifikate automatisch zu erneuern benötigen wir ein weiteres Skript:
nano /etc/haproxy/le-renewal.sh
#!/bin/bash certbot renew --standalone --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 --post-hook "/etc/haproxy/le-certificates.sh && systemctl reload haproxy.service" --quiet exit 0
Auch dieses Skript muss wieder ausführbar gemacht werden
chmod +x /etc/haproxy/le-renewal.sh
Nun legen wir noch den wöchentlichen Cronjob an
crontab -e
@weekly /etc/haproxy/le-renewal.sh > /dev/null
wodurch die Zertifikate wöchentlich auf Aktualisierungen geprüft werden und bei einer Aktualisierung auch der haproxy-Service neu gestartet wird.
Die Installation und Einrichtung des HAProxy-Loadbalancers wurde somit erfolgreich abgeschlossen. Über eine Spende würden sich meine Frau, meine Zwillinge und ich sehr freuen. Vielen Dank!

© Carsten Rieger IT-Services