Inhaltsverzeichnis
Letzte Aktualisierung am 01.01.2023, 14:01:18 Uhr
Immer wieder werde ich gefragt, ob es möglich ist AdGuard redundant aufzubauen, so dass bei Wartungsarbeiten und Ausfällen weiterhin die Funktionsfähigkeit für die Endanwender gegeben ist.
Bei meinen Recherchen bin ich über ein Issue auf GitHub des Projekts gestolpert. Das Thema beschäftigt die Nutzer bereits über drei Jahre. Bisher hat die Entwicklung von AdGuard keine Möglichkeit implementiert, um out of the Box High availability (HA) zu realisieren. Genau an diesem Punkt setzt ein Kommentar in dem Issue an, dessen Idee ich aufgegriffen habe.
Design/Aufbau
Nachstehend ein Schaubild meines Testsaufbau.
Die von mir entworfene Lösung ist skalierbar. Das heißt es spielt keine Rolle, ob der „Cluster“ aus zwei oder vier Servern besteht.
Wichtig ist, dass die Server untereinander über SSH (Port 22/tcp) erreichbar sind. Des weiteren verfügen alle Server über öffentliche IPv4 und IPV6 Adressen. Somit ist gewährleistet, dass für die Bereitstellung von SSL-Zertifikaten Let’s Encrypt (LE) verwendet werden kann. Somit entstehen keine weiteren jährlichen Kosten.
Bei der Namensgebung habe ich mich dafür entschieden, dem Cluster einem eindeutigen Namen (FQDN) zu geben. In diesem Beitrag ist es „adguard04.wydler.eu“. Der FQDN ist relevant, sobald
A) die Endgeräte DoH nutzen sollen. Denn damit ist der Einsatz eines Load Balancers sinnvoll, der über einem aussagekräftige DNS-Namen ansprechbar sein. Der Load Balancer wird auf Layer 4 konfiguriert. Sprich die Anfragen werden an die Backend Server weitergeleitet.
B) Ein Load Balancer eingesetzt wird, der sowohl mit TCP als auch UDP umgehen kann (z.B. Microsoft Azure Traffic Manager.
Die vermeidlichen Mitglieder des Clusters „adguard04.wydler.eu“ habe ich das Namensschema weitergeführt. D.h. deren Servernamen beginnt mit „adguard04“. Am Ende hänge ich einfach fortlaufend einen Buchstaben des Alphabets an (siehe Schaubild). Somit kann ein Cluster aus maximal 26 Servern (A bis Z) bestehen. Das sollte für die meisten Umgebungen ausreichen. 😉
Der Server mit dem Buchstaben „a“ am Ende ist zugleich der Master innerhalb des Clusters. Alle dort getätigten Konfigurationen in der Weboberfläche von AdGuard werden auf allen anderen Server repliziert.
Grundinstallation
Für meinen Testaufbau habe ich zwei Server in der Hetzner Cloud gemietet. Diese heißen adguard04a.izbw.de und adguard04b.izbw.de. Das anschließend die notwendigen DNS-Einträge (A, AAAA sowie PTR) konfiguriert werden müssen, sehe ich als selbstverständlich an.
Nachstehend die verschiedenen Konfiguration für meinen Testaufbau. Dazu nenne ich vorweg immer den Servernamen, auf denen die Befehle ausgeführt werden müssen.
Node adguard04a
Betriebssystem und die installierten Pakete auf aktuellen Stand bringen.
apt update && apt upgrade -y
SSH Schlüssel erzeugen. Öffentlicher Schlüssel auf anderen Node übertragen.
ssh-keygen -t ed25519 ssh-copy-id root@adguard04b.wydler.eu ssh root@adguard04b.wydler.eu
Abruf eines SSL-Zertifikat von Let’s Encrypt.
apt install certbot -y certbot certonly --standalone -d adguard04a.wydler.eu -d adguard04.wydler.eu --agree-tos --cert-name adguard04.wydler.eu -m webmaster@wydler.eu --rsa-key-size 4096 --dry-run
Installation von AdGuard.
curl -sSL https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh
Danach die Weboberfläche von AdGuard aufrufen und den Einrichtungsassistent ausführen (http://adguard04a.wydler.eu:3000). Dies ist erforderlich, dass die Konfigurationsdatei angelegt wird.
Konfiguration der Firewall.
ufw allow ssh ufw allow 53/tcp ufw allow 53/udp #ufw allow 67/udp #ufw allow 68/udp ufw allow http ufw allow https ufw allow 853/tcp echo y | ufw enable ufw status
Node adguard04b
apt update && apt upgrade -y
Abruf eines SSL-Zertifikat von Let’s Encrypt.
apt install certbot -y certbot certonly --standalone -d adguard04b.wydler.eu --agree-tos --cert-name adguard04.wydler.eu -m webmaster@wydler.eu --rsa-key-size 4096 --dry-run
Installation von AdGuard.
curl -sSL https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh
Konfiguration der Firewall.
ufw allow ssh ufw allow 53/tcp ufw allow 53/udp #ufw allow 67/udp #ufw allow 68/udp ufw allow http ufw allow https ufw allow 853/tcp echo y | ufw enable ufw status
Einrichtung der Replikation
Alle nachstehenden Befehle werden auf dem Node adguard04a.wydler.eu ausgeführt.
Installation von lsyncd.
apt install lsyncd -y lsyncd --version
Verzeichnisse für Konfiguration und Logfiles anlegen.
mkdir /etc/lsyncd mkdir -p /var/log/lsyncd/
Konfiguration von logrotate für die Logfiles einrichten.
cat << EOF > /etc/logrotate.d/lsyncd /var/log/lsyncd/lsyncd.log /var/log/lsyncd/lsyncd.status { rotate 7 daily compress missingok notifempty postrotate systemctl restart lsyncd.service > /dev/null endscript } EOF
Konfiguration für die Replizierung der Konfigurationsdatei von AdGuard sowie Neustart des Dienstes auf allen Servern.
TAB="$(printf '\t')" cat > /etc/lsyncd/lsyncd.conf.lua << EOF settings { ${TAB}logfile = "/var/log/lsyncd/lsyncd.log", ${TAB}statusFile = "/var/log/lsyncd/lsyncd.status", ${TAB}statusInterval = 20, ${TAB}maxProcesses = 1, ${TAB}maxDelays = 30, ${TAB}insist = false } targetList = { ${TAB}"adguard04b.wydler.eu" } for _, servers in ipairs(targetList) do ${TAB}sync { ${TAB}${TAB}default.rsyncssh, ${TAB}${TAB}source="/opt/AdGuardHome/", ${TAB}${TAB}host=servers, ${TAB}${TAB}targetdir="/opt/AdGuardHome", ${TAB}${TAB}delete='startup', ${TAB}${TAB}delay = 5, ${TAB}${TAB}rsync = { ${TAB}${TAB}${TAB}owner = false, ${TAB}${TAB}${TAB}group = false, ${TAB}${TAB}${TAB}perms = false, ${TAB}${TAB}${TAB}rsh = "/usr/bin/ssh -p 22 -o StrictHostKeyChecking=no", ${TAB}${TAB}${TAB}_extra = { ${TAB}${TAB}${TAB}${TAB}"--include=AdGuardHome.yaml", ${TAB}${TAB}${TAB}${TAB}"--exclude=*", ${TAB}${TAB}${TAB}}, ${TAB}${TAB}}, ${TAB}${TAB}ssh = { ${TAB}${TAB}${TAB}port = 22 ${TAB}${TAB}} ${TAB}} ${TAB}sync { ${TAB}${TAB}default.rsyncssh, ${TAB}${TAB}source = "/opt/AdGuardHome/", ${TAB}${TAB}targetdir = "/opt/AdGuardHome", ${TAB}${TAB}host = servers, ${TAB}${TAB}delay = 10, ${TAB}${TAB}rsync = { ${TAB}${TAB}${TAB}binary = "/opt/AdGuardHome/AdGuardRestart.sh", ${TAB}${TAB}${TAB}_extra = { ${TAB}${TAB}${TAB}${TAB}(""..servers), ${TAB}${TAB}${TAB}} ${TAB}${TAB}} ${TAB}} end EOF
Bei dem Abschnitt targetlist müssen alle weiteren Server mit Komma (,) hinzugefügt werden. Mit dem delay in jedem Abschnitt wird sichergestellt, dass alle Änderungen in der Weboberfläche nicht sofort repliziert werden. Gerade auf Hinblick, dass einige Änderungen sofort in die Konfigurationsdatei geschrieben werden ohne das diese explizit über eine Schaltfläche „Speichern“ erst geschrieben werden. Somit soll einer fehlerhaften Konfiguration auf allen Nodes vorgebeugt werden.
Erstellen des Bash-Skripts für den Neustart des AdGuard Dienstes auf dem Zielserver.
cat << \EOF > /opt/AdGuardHome/AdGuardRestart.sh #!/bin/bash if [[ $2 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then ip=$2 else ip=$4 fi ssh root@$ip "/opt/AdGuardHome/AdGuardHome -s restart" EOF
Das Skript ist unerlässlich. Denn damit die neue Konfiguration auf den anderen Nodes wirksam wird, muss der Dienst von AdGuard neu gestartet werden.
Berechtigungen des Bash-Skripts anpassen.
chmod 755 /opt/AdGuardHome/AdGuardRestart.sh
Dienst aktivieren, starten und Status prüfen.
systemctl enable lsyncd systemctl restart lsyncd systemctl status lsyncd
Logfile von lsyncd fortlaufend ausgeben.
tail -f /var/log/lsyncd/lsyncd.log
Das Ganze ist natürlich skalierbar. D.h. ob es nun 2, 5 oder 10 Server sind, spielt keine Rolle. Das Schema bleibt immer das Selbe.
Die Grundkonfiguration von AdGuard habei ich im Artikel AdGuard Home im Netzwerk implementieren für euch dokumentiert.
Viel Spaß beim Ausprobieren.
Hi,
ich bekommen wenn ich das RestartScript nutze eine Fehlermeldung das der Hostnae nicht erreichbar ist oder nicht gefunden werden kann.
Ich verstehe das Script auch nicht wirklich. Woher zb. bezieht er den die IP Adresse? Von wo werden den die Variablen $2 und $4 gefüllt?
Grüße
Danke sieht interessant aus.
Wer die Server nicht öffentlich verfügbar machen möchte, kann sich mal Lego anschauen. Läuft bei mir wunderbar in der lokalen Domäne 🙂
https://github.com/go-acme/lego
P.S. Tollen Blog hast du da. Bin letzte Woche drauf gestoßen und habe dann gesehen, dass wir uns ja von früher kennen 😉