HAProxy unter ArchLinux installieren und einrichten
HAProxy ist ein kostenloser, sehr schneller und zuverlässiger Reverse-Proxy, der Hochverfügbarkeit, Loadbalancing und Proxying für TCP- und HTTP-basierte Anwendungen bietet. Er eignet sich besonders für Websites mit sehr hohem Datenverkehr und wird von einem Großteil der weltweit meistbesuchten Websites genutzt. So hat es sich im Laufe der Zeit zum De-facto-Standard für Open-Source-Lastenausgleich entwickelt, wird mittlerweile mit den meisten gängigen Linux-Distributionen ausgeliefert swie sehr oft standardmäßig in Cloud-Plattformen eingesetzt.
In dem nachfolgenden WIKI-Artikel wollen wir uns nun eingehender mit der Installation und Konfiguration unseres HAProxy unter Arch Linux beschäftigen.
Herausforderung / Aufgabenstellung
Für verschiedene Webangebote werden mehrere Apache-Webserver betrieben. So z.B. für Djangos WIKI, der Wetterstation Pliening, der Ebersberger Liedersammlung sowie viele administrative Anwendungen und|oder Netzgeräten, welche über eine WEB-GUI verfügen, betrieben. Einige der Anwendungen werden Höchverfügbar betrieben, so dass ohne erkennbare Ausfälle für einen Besucher, (Anwendungs-)Hosts aktualisiert und dabei in Wartung sprich offline genommen werden.
Mit Hilfe von HAProxy wollen wir nun genau folgende Punkte erledigen:
- Der TLS-gesicherte Weg zu Djangos WIKI soll mit Hilfe unseres HA-Proxy abwechselnd auf einen der beiden Apache-Webserver I und Apache-Webserver II „roundrobin mäßig“ verteilt werden.
- Die Webseite Ebersberger Liedersammlung soll auf dem Node Apache-Webserver I primär laufen und für den Notbetrieb wird der Apache-Webserver I als sog. cold-standby bereit gehalten.
- Die Wetterstation Pliening hingegen läuft aktuell systembedingt nur auf dem Apache-Webserver II.
- Aller anderer Verkehr soll ausnahmslos direkt zu dem Fedora-Node weiter gereicht werden.
- Sofern die Ressource für die Weiterleitung nicht zur Verfügung steht, soll ein Besuchender eine entsprechende Hinweisseite angezeigt bekommen.
Installation und Konfiguration des HAProxy
Dokumentation / Man-Pages
Informationen zu den Release-Zyklen von HAProxy findet man unter Latest versions auf der HAProxy Wenseite sowie eine ausfühliche Anleitung in den HAProxy Konfigurations Tutorials.
Zusätzlich findet man rudimentäre Informationen zum HAProxy unter Arch Linux finden sich unter anderem im Arch Linux WIKI.
- Ferner finden wir nach der Installation von haproxy im Verzeichnis
/usr/share/haproxy/das aktuelle HAProxy Configuration Manual →configuration.txtsowie weitere erklärende Dokumente,
sowie im Unterordner/usr/share/haproxy/examplesviele Beispiele die einem bei der Konfiguration des HAProxy wertvolle Dienste leisten.
haproxy Manpage
Was uns der httpd - Apache Hypertext Transfer Protocol Server bietet und welche Optionen beim Aufruf der Daemon bietet offenbart uns die betreffende Man-Page des Programms.
# man httpd
Paketinstallation
Die Installation und Konfiguration des HAProxy gestaltet sich relativ einfach. Zur Installation des Paketes verwenden wir unter Arch Linux den Paketmanager pacman.
- Als User:
$ sudo pacman -S haproxy
- Als Nutzer mit Root-Rechten entsprechend:
# pacman -S haproxy
Ausgabe des Befehls pacman -S haproxy
Bei der Installation des HAProxy-Paketes erhalten wir einen wichtigen Hinweis:
==> The example config chroots HAProxy, meaning that logging to journald won't work.
Either disable chrooting, use rsyslog, or bind /run/systemd/journal/dev-log into the chroot.
Im Abschnitt ChangeRoot-Umgebung werden wir diesen Vorschlag beherzigen und aufgreifen.
Was uns das Paket haproxy alles in das System unseres Arch Linux Server gebracht hat, können wir wie folgt abfragen:
# pacman -Qil haproxy
Grund-Konfiguration
Firewall/Paketfilter - firewalld
Bevor wir nun unseren haproxy konfigurieren und starten müssen wir natürlich sicherstellen, dass auf dem betreffendem Host auch die Kommunikationsbeziehungen entsprechend erlaubt sind.
Wie auch schon früher bei CentOS ab Release 7 bzw. den nachfolgenden Release-Kandidaten Stream von RHEL nutzen wir auch unter Arch Linux den dynamischen firewalld Service. Ein grosser Vorteil der dynamischen Paketfilterregeln ist unter anderem, dass zur Aktivierung der neuen Firewall-Regel(n) nicht der Daemon durchgestartet werden muss und somit alle aktiven Verbindungen kurz getrennt werden. Sondern unsere Änderungen können on-the-fly aktiviert oder auch wieder deaktiviert werden.
Damit unsere haproxy-Daemon Anfragen aus dem Netz auf den Ports 80/TCP- und 443/TCP-Ports annahmen kann, müssen wir für diese noch Änderungen am Paketfilter firewalld vornehmen.
Zunächst installieren wir uns das betreffende firewalld-Paket.
# pacman -S firewalld
bzw. als Admin-User:
$ sudo pacman -S firewalld
Anschließend starten wir den Firewall-Daemon.
# systemctl start firewalld.service
Damit der Firewall-Daemon beim Neustart des Systems automatisch gestartet wird, enablen wir diesen nun auch noch.
# systemctl enable firewalld.service
Mit Hilfe des Programms firewall-cmd konfigurieren wir nun den Daemon:
- Logging aktivieren:
# firewall-cmd --set-log-denied=all
- Firewall-Zone anlegen:
# firewall-cmd --permanent --new-zone=idmz # firewall-cmd --reload
- Netzwerkinterfaces der Zonen zuordnen:
# firewall-cmd --permanent --zone=idmz --add-interface=net0 # firewall-cmd --reload
- Firewalld Default Zone setzen:
# firewall-cmd --set-default-zone idmz
- SSH, HTTP und HTTPS für die Zone idmz aktivieren:
# firewall-cmd --permanent --zone=idmz --add-service=ssh # firewall-cmd --permanent --zone=idmz --add-service=http # firewall-cmd --permanent --zone=idmz --add-service=https
- Regelwerk persistieren:
# firewall-cmd --reload
- Ergebniskontrolle:
# firewall-cmd --zone=idmz --list-all
idmz (default, active) target: default ingress-priority: 0 egress-priority: 0 icmp-block-inversion: no interfaces: net0 sources: services: http https ssh ports: protocols: forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
HAProxy-Konfigurationsverzeichnis und -Datei(en)
Die Konfiguration des HA-Proxy-Daemon haproxy erfolgt mit Hilfe einer Konfigurationsdatei, die sich im Verzeichnis /etc/haproxy befindet. Somit ist das entsprechende Verzeichnis erst einmal sehr überschaubar, was sich aber im Laufe der nachfolgenden Konfigurationsschritte noch stark ändern wird!
Im Verzeichnis /etc/haproxy findet sich also aktuell „nur“:
/etc/haproxy/ └── haproxy.cfg 1 directory, 1 file
Systemstart
erster manueller Start
# systemctl start haproxy.service
Im Journal wird der Start unseres HTTP-Servers entsprechend vermerkt.
# journalctl -fu haproxy
Ebenso kann man den Status des Webservers mit Hilfe des Befehls systemctl abfragen.
# systemctl status haproxy.service
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; preset: disabled)
Active:active (running) since Wed 2026-03-04 17:02:12 CET; 3min 43s ago
Invocation: 54978bf4061c4988b96ac4cc0ab58897
Main PID: 6745 (haproxy)
Status: "Ready."
Tasks: 5 (limit: 9499)
Memory: 16.8M (peak: 17.5M)
CPU: 287ms
CGroup: /system.slice/haproxy.service
├─6745 /usr/bin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
└─6749 /usr/bin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
Mar 04 17:02:12 vml000080 haproxy[6745]: [NOTICE] (6745) : Initializing new worker (6749)
Mar 04 17:02:12 vml000080 haproxy[6745]: [NOTICE] (6745) : Loading success.
Mar 04 17:02:12 vml000080 systemd[1]: Started HAProxy Load Balancer.
Mar 04 17:02:12 vml000080 haproxy[6749]: [WARNING] (6749) : Server static/static is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 0 active and 0 backup >
Mar 04 17:02:12 vml000080 haproxy[6749]: [ALERT] (6749) : backend 'static' has no server available!
Mar 04 17:02:12 vml000080 haproxy[6749]: [WARNING] (6749) : Server app/app1 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 3 active and 0 backup serve>
Mar 04 17:02:13 vml000080 haproxy[6749]: [WARNING] (6749) : Server app/app2 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 2 active and 0 backup serve>
Mar 04 17:02:13 vml000080 haproxy[6749]: [WARNING] (6749) : Server app/app3 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 1 active and 0 backup serve>
Mar 04 17:02:14 vml000080 haproxy[6749]: [WARNING] (6749) : Server app/app4 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 0 active and 0 backup serve>
Mar 04 17:02:14 vml000080 haproxy[6749]: [ALERT] (6749) : backend 'app' has no server available!
Alternativ dazu können wir auch einen Blick in die Prozess-Liste werfen um uns zu vergewissern ob der Daemon läuft.
# ps auxwf | grep haproxy
root 6783 0.0 0.0 8064 6372 pts/1 S+ 17:09 0:00 | \_ grep --color=auto haproxy root 6745 0.0 0.2 110432 20396 ? Ss 17:02 0:00 \_ /usr/bin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock haproxy 6749 0.0 0.2 264284 24240 ? Sl 17:02 0:00 \_ /usr/bin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
Wir können jetzt auch schon mit Hilfe des Utility ss abfragen ob der httpd nun Ports auf zugehörigen Addressen geöffnet hat.
# ss -tulpn
Start des Daemon einrichten
Damit der haproxy-Daemon automatisch beim Neustart des Servers mit gestartet werden kann, ist dieser Dienst zunächst zu „enablen“.
# systemctl enable haproxy.service
Created symlink '/etc/systemd/system/multi-user.target.wants/haproxy.service' → '/usr/lib/systemd/system/haproxy.service'.
Konfiguration des haproxy
Basis-Konfiguration
Die Konfiguration des Daemon erfolgt über die Datei /etc/haproxy/haproxy.cfg die uns bei der Paketinstallation mitgeliefert wurde. Damit wir Änderungen, die beim Updaten des installierten Paketes ggf. neu hinzukommen oder wegfallen, besser von der Originaldatei unterscheiden können kopieren wir uns als erstes diese Datei.
# cp -av /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig
Damit wir bei einer manuellen Konfiguration des haproxy-Daemon die entsprechenden Konfigurationsoptionen besser im Überblick haben, werden wir diese entsprechend dokumentieren!
Wichtiger Dreh- und Angelpunkt unseres Konfigurationsbeispiels ist das aktuelle Configuration Manual der HAProxy Community Edition. Dort finden wir eine detaillierte Beschreibung aller Parameter und Optionen!
Die im Arch Linux Paket zeigt nur ein Beispiel, wie die Konfigurationsdatei strukturiert und aufgebaut ist. Wir werden in unserem Konfigurationsbeispiel hier unsere eigene Konfigurationsdatei anlegen und diese mit entsprechenden Kommentaren und Verweisen auf das offizielle HAProxy Configuration Manual anreichern, so dass bei einer manuellen Pflege der Konfigurationsdatei der Admin entsprechende Hinweise findet, was hier im Detail konfiguriert wurde.
Die Konfigurationsdatei gliedert sich in mehrere Sektionen, die in der Regel von oben nach unten vererbt werden. So gelten z.B. Optionen die in der Sektion global gesetzt sind, in den nachfolgenden front und backends. Unsere Beispielskonfigurationsdatei wird folhggende Sektionen aufweisen:
- global : Globale Betriebssystemspezifische Konfigurationsparameter, die für alle Prozesse übergreifend gelten.
- default : Definition der Standardeinstellungen, welche bei den nachfolgenden Sektionen frontend, backend und listen die Standardwerte vorgeben. Werden Parameter in nachfolgenden Sektionen wiederholt gesetzt, folgen die Werte beginnend von der defaultsektion abwärts bis zur letztverwendeten Sektion.
- userlist : Kontrolle der Zugriffsbeschränkungen auf die einzelnen Sektionen frontend, backend sowie listen bzw. auf die http-Statistiken. Nur authentifizierte und autorisierte Benutzer werden zugelassen.
- http-errors : Es ist möglich, mehrere Gruppen von HTTP-Fehlern global zu deklarieren, um sie anschließend in einen beliebigen Proxy-Abschnitt zu importieren. Dieselbe Gruppe kann an mehreren Stellen referenziert und vollständig oder teilweise importiert werden.
- cache : Definition eines gemeinsam nutzbaren wartungsarmen Cache-Bereichs im Speicher (RAM), der für die Zwischenspeicherung von kleinen Objekten (favicon.ico, css uvm.) konzipiert wurde.
- frontend : Definition von eine Reihe von Sockets, die Client-Verbindungen annehmen.
- frontend http-in : Definition der Verbindungsparameter und -optionen für den ankommenden HTTP-Traffic.
- frontend https-in : Definition der Verbindungsparameter und -optionen für den ankommenden HTTPS-Traffic.
- backend : Festlegung von eine Reihe von Servern, mit denen sich der HAProxy verbindet um eingehende Verbindungen dorthin weiterzuleiten.
- backend webui : Definition des Statistic Backends, der WEB-GUI für die Administration des HAProxy Daemons.
- backend dokuwiki.nausch.org : Definition des Backends
dokuwiki.nausch.orgbei dem die Last gleichmäßig im Verfahren roundrobin auf die beiden Apache Webserver I und II verteilt werden soll. - backend ebersberger-liedersammlung.de : Definition des Backends
ebersberger-liedersammlung.debei dem die Last primär auf dem Apache-Webserver I ankommen soll. Der zweite Apache-Webserver wird als cold-stand-by vorgehalten und soll nur dann Verkehr abbekommen, wenn ein Admin manuell eingreift und dieses Backend-System aktiviert. - backend wetterstation-pliening.info : Definition des Backends
wetterstation-pliening.infobei dem nur der Apache-Webserver II angesprochen werden soll. Hier gibt es keinen cold-stand-by Webapplikations-Server. - backend fedora : Definition des Default-Backends. Hier soll aller HTTP/HTTPS-Traffic abgeladen werden, für deren URLs keine der ACLs greift, die in der Section
https_inzutrifft.
Genug der Vorrede, machen wir uns nun ans Werk und bauen unsere individuelle Konfigurationsdatei, entsprechend der Überlegungen im Abschnitt Herausforderung / Aufgabenstellung in diesem WIKI-Artikel.
Zunächst einmal legen wir dden informativen und erklärenden Infoblock zu Beginn unserer Konfigurationsdatei fest.
# vim /etc/haproxy/haproxy.cfg
- /etc/haproxy/haproxy.cfg
# ┌─────────────────────────────────────────────────────────────────────────────┐ # │ │ # │ Musterkonfiguration für einen HAProxy Loadbalancers │ # │ für das Konfigurationsbeispiel in Djangos WIKI │ # │ https://https://dokuwiki.nausch.org/doku.php/linux:haproxy │ # │ │ # └─────────────────────────────────────────────────────────────────────────────┘
Sektion global
Als nächstes definieren wir die Sektion global, in der wir die globale Betriebssystemspezifische Konfigurationsparameter festlegen werden, die für alle Prozesse übergreifend gelten sollen.
# vim /etc/haproxy/haproxy.cfg
... # Globale Betriebssystemspezifische Konfigurationsparameter, die für alle # Prozesse übergreifend gelten. global # Festlegung des Default-Konfigurationsverzeichnisses des haproxy-Daemons, # „config“ gibt an, dass alle relativen Dateien aus dem Verzeichnis geladen # werden sollen, das die Konfigurationsdatei enthält. # https://docs.haproxy.org/3.3/configuration.html#3.1-default-path default-path config # Verlagerung des haproxy-Prozesses in den Hintergrund, was dem systemd # Daemon Modue entspricht. # https://docs.haproxy.org/3.3/configuration.html#daemon daemon # Definieren der maximalen gleichzeitigen Verbindungen pro HAProxy-Daemon. # Der HAProxy-Daemon nimmt keine neuen Verbindungen mehr an, sobald dieses # Limit erreicht ist. Der Parameter ulimit-n wird automatisch an diesen Wert # angepasst. # https://docs.haproxy.org/3.3/configuration.html#maxconn maxconn 2048 # Definition des globalen Syslog-Servers. Bei Bedarf können mehrere globale # Syslog-Server definiert werden, welche dann Protokolle für Starts und # Beendigungen sowie alle Protokolle von Proxys, die mit „log global” # konfiguriert sind, empfangen werden. Weitere Informationen finden man # unter der Option „log” für Proxys. # https://docs.haproxy.org/3.3/configuration.html#log log /dev/log local0 info # Festlegung des Users unter dem dser HAProxy Prozess laufen soll. HAProxy # wird beim Start mit SuperUser Rechten gestartet und anschließend zum # definierten user gewechselt. # https://docs.haproxy.org/3.3/configuration.html#user user haproxy # Festlegung der Gruppe mit dem dser HAProxy Prozess laufen soll. HAProxy # wird beim Start mit SuperUser Rechten gestartet und anschließend zum # definierten group gewechselt. # https://docs.haproxy.org/3.3/configuration.html#group group haproxy # Schreibt die PIDs aller Daemons in die Datei <pidfile>, wenn der Daemon- # -Modus aktiv ist, oder schreibt die PID des Master-Prozesses in die Datei # <pidfile>, wenn der Master-Worker-Modus aktiv ist. # Der Benutzer, der den Prozess startet, muss Zugriff auf die Datei haben. # https://docs.haproxy.org/3.3/configuration.html#pidfile pidfile /run/haproxy.pid # Definition der Standard-SSL-Optionen, welche in allen „bind“-Zeilen # erzwungen werden. In diesem Konfigurationsbeispiel wird als Mindestvoraus- # setzung bei der SSL-/TLS-Verschlüsselung Version TLSv1.2 erzwungen. # https://docs.haproxy.org/3.3/configuration.html#ssl-default-bind-options ssl-default-bind-options ssl-min-ver TLSv1.2 # Festlegung der Standardzeichenfolge, die die Liste der Verschlüsselungs- # algorithmen („Cipher Suites“) beschreibt, die während des SSL/TLS-Hand- # shakes bis zu TLSv1.2 für alle „bind“-Zeilen ausgehandelt werden, die # ihre nicht explizit definieren. # https://docs.haproxy.org/3.3/configuration.html#ssl-default-bind-ciphers 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 # Festlegung der Standardalgorithmen, der die Liste der Verschlüsselungs- # algorithmen („Cipher Suites“) beschreibt, die während des TLSv1.3 Hand- # shakes für alle bind-Parameter die nicht explizit ihre eigenen definie- # ren, als Standard gesetzt haben. # https://docs.haproxy.org/3.3/configuration.html#ssl-default-bind-ciphersuites ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 # Bindet einen UNIX-Socket an <Pfad> oder eine TCPv4/v6-Adresse an # <Adresse:Port>. Verbindungen zu diesem Socket geben verschiedene # Statistiken aus und ermöglichen sogar die Ausgabe einiger Befehle, # um bestimmte Laufzeiteinstellungen zu ändern. # Die Datei und Verzeichnisrechte orientieren sich dabei an den jeweiligen # Verwendungszeck/Level. # Level: # - admin : uneingeschränkten Zugriff auf alles mit entsprechender # Berechtigung zum Ändern und Löschen. # - operator : Lesender Zugriff auf alle Parameter und eingeschränkte # Löschberechtigung auf einzelnme Werte, wie z.B. max. # https://docs.haproxy.org/3.3/configuration.html#3.1-stats%20socket stats socket /var/run/haproxy-admin.sock user root mode 600 level admin stats socket /var/run/haproxy-operator.sock user haproxy mode 600 level operator stats socket /var/run/haproxy-user.sock group wheel mode 660 level user # Standardmäßig ist der Statistik-Socket auf 10 gleichzeitige Verbindungen # beschränkt. # https://docs.haproxy.org/3.3/configuration.html#3.1-stats%20maxconn stats maxconn 5 # Die Standard-Zeitüberschreitung für den Statistik-Socket ist auf 10 # Sekunden eingestellt. Dieser Wert kann mit „stats timeout” geändert # werden. Der Wert muss in Millisekunden angegeben oder mit einer # Zeiteinheit aus { us, ms, s, m, h, d } versehen werden. # https://docs.haproxy.org/3.3/configuration.html#3.1-stats%20timeout stats timeout 15s
Sektion defaults
Die Definition der Standardeinstellungen, welche bei den nachfolgenden Sektionen frontend, backend und ggf. listen die Standardwerte vorgeben, werden wir nun als nächstes definieren. Setzen wir hier Parameter in nachfolgenden Sektionen wiederholt aufgegriffen werden, folgen die Werte beginnend von der default-Sektion abwärts bis zur letztverwendeten Sektion.
# vim /etc/haproxy/haproxy.cfg
... # Definition der Standardeinstellungen, welche bei den nachfolgenden # Sektionen frontend, backend und listen die Standardwerte vorgeben. # Werden Parameter in nachfolgenden Sektionen wiederholt gesetzt, # folgen die Werte beginnend von der defaultsektion abwärts bis zur # letztverwendeten Sektion. defaults # Definition des Ausführungsmodus oder das Protokolls der Instanz. # https://docs.haproxy.org/3.3/configuration.html#mode mode http # Festlegung der maximalen Inaktivitätszeit auf Client-Seite. # https://docs.haproxy.org/3.3/configuration.html#4.2-timeout%20client timeout client 10s # Festlegung der maximalen Zeit, die gewartet werden soll, bis ein # Verbindungsversuch zu einem Server zu erfolgen hat. timeout connect 5s # Legte die maximal zulässige Wartezeit für eine vollständige # HTTP-Anfrage fest. timeout http-request 10s # Legte die maximale Inaktivitätszeit auf der Serverseite fest. # https://docs.haproxy.org/3.3/configuration.html#4.2-timeout%20server timeout server 10s # Aktivieren der Protokollierung von Ereignissen und Datenverkehr # pro Instanz. # https://docs.haproxy.org/3.3/configuration.html#4.2-log%20global log global # Ermöglicht das Einfügen des X-Forwarded-For-Headers in Anfragen, # die an Server gesendet werden. # https://docs.haproxy.org/3.3/configuration.html#4.2-option%20forwardfor option forwardfor # Aktivieren oder Deaktivieren der Sitzungsumverteilung im Falle eines # Verbindungsabbruchs. # https://docs.haproxy.org/3.3/configuration.html#4.2-option%20redispatch option redispatch # Änderung der Log-Ebene für nicht vollständig erfolgreiche Verbindungen. # https://docs.haproxy.org/3.3/configuration.html#4.2-option%20log-separate-errors option log-separate-errors # Änderung der Log-Ebene für nicht vollständig erfolgreiche Verbindungen. # https://docs.haproxy.org/3.3/configuration.html#4.2-option%20log-health-checks option log-health-checks # Aktivierung bzw. Deaktivierung der Protokollierung normaler, erfolgreicher # Verbindungen. # https://docs.haproxy.org/3.3/configuration.html#4.2-option%20dontlog-normal option dontlog-normal # Aktivierung bzw. Deaktivierung der Protokollierung von leeren (Null)- # -Verbindungen. # https://docs.haproxy.org/3.3/configuration.html#4.2-option%20dontlognull option dontlognull
Sektion userlist stats-auth
In der Sektion userlist stats-auth legen wir nun fest, dass nur authentifizierte und autorisierte Benutzer zugelassen werden sollen, wenn sie auf einzelne Sektionen wie frontend, backend und listen sowie auf die WEB-GUI des HAProxy zugreifen wollen.
Das verschlüsseltes Passwort für den Nutzer admin erstellen wir uns mit folgendem Befehl:
# openssl passwd -6 -salt $(openssl rand -base64 16)
Password: $6$O4BVsBujJlfNLdWw$xyipkf33hNlCznKGwrojyZK.1/RCk0.5NNKjGoW/Oqr7nBAbjkY5sygkTE0uw5kXp986VL6c8RtevkZ0aUqtt1
Das so generierte verschlüsselte Secret hinterlegen wir nun in unserer Konfigurationsdatei.
# vim /etc/haproxy/haproxy.cfg
... # Kontrolle der Zugriffsbeschränkungen auf die einzelnen Sektionen # frontend, backend sowie listen bzw. auf die http-Statistiken. Nur # authentifizierte und autorisierte Benutzer werden zugelassen. userlist stats-auth group admin users admin user admin password $6$O4BVsBujJlfNLdWw$xyipkf33hNlCznKGwrojyZK.1/RCk0.5NNKjGoW/Oqr7nBAbjkY5sygkTE0uw5kXp986VL6c8RtevkZ0aUqtt1
Sektion http-errors haerrors
Wenn wir eines unserer Backendsystem in downtime setzen, weil z.B. Backup-Arbeiten oder Systemupdates anstehen, wollen wir natürlich, dass unsere Besucher nicht ins Leere laufen, sondern eine vernünftige 503er-Fehlerseite präsentiert bekommen.
Hierzu legen wir uns als erstes ein entsprechendes Unterverzeichnis unter /etc/haproxy an.
# mkdir /etc/haproxy/errors/
Dort hinterlegen wir unsere Fehlerseite.
# vim /etc/haproxy/errors/503.html
- /etc/haproxy/errors/503.html
HTTP/1.0 503 Service Unavailable Cache-Control: no-cache Connection: close Content-Type: text/html <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Wartungsmodus - Service im Moment nicht verfügbar!</title> <style> :root { --primary: #ff6f61; --bg: #f9f9f9; --text: #333; } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: var(--bg); color: var(--text); display: flex; align-items: center; justify-content: center; min-height: 100vh; text-align: center; padding: 1rem; } .container { max-width: 480px; } h1 { font-size: 2.5rem; margin: 0.5rem 0; color: var(--primary); } p { line-height: 1.5; margin: 1rem 0; } a.button { display: inline-block; padding: 0.75rem 1.5rem; margin-top: 1rem; background: var(--primary); color: #fff; text-decoration: none; border-radius: 4px; transition: background 0.2s; } a.button:hover { background: #e65a50; } @media (max-width: 480px) { h1 { font-size: 2rem; } } </style> </head> <body> <div class="container"> <h1>503 – Wartungsmodus Service nicht verfügbar!</h1> <p>Die angeforderte Seite kann im Moment nicht ausgeliefert werden.<br> Der Webserver befindet sich gerade im Wartungs- bzw. Aktualisierungsmodus.<br> Bitte versuchen Sie es später erneut oder kontaktieren Sie den <a href="mailto:webmaster@nausch.org">Administrator.</a></p> <a href="/" class="button">Zur Startseite</a> </div> </body> </html>
Anschließend ergänzen wir unsere HAProxy-Konfigurationsdatei entsprechend.
# vim /etc/haproxy/haproxy.cfg
... # Es ist möglich, mehrere Gruppen von HTTP-Fehlern global zu deklarie- # ren, um sie anschließend in einen beliebigen Proxy-Abschnitt zu im- # portieren. Dieselbe Gruppe kann an mehreren Stellen referenziert und # vollständig oder teilweise importiert werden. # https://docs.haproxy.org/3.3/configuration.html#12.4-http-errors http-errors haerrors errorfile 503 /etc/haproxy/errors/503.html
Sektion cache haproxycache
Als nächstes definieren wir einen gemeinsam nutzbaren wartungsarmen Cache-Bereichs im Speicher (RAM), der für die Zwischenspeicherung von kleinen Objekten (favicon.ico, css uvm.) konzipiert wurde.
# vim /etc/haproxy/haproxy.cfg
... # Definition eines gemeinsam nutzbaren wartungsarmen Cache-Bereichs # im Speicher (RAM), der für die Zwischenspeicherung von kleinen # Objekten (favicon.ico, css uvm.) konzipiert wurde. # Die Angabe der cache-Größe ist dabei obligatorisch. # https://docs.haproxy.org/3.3/configuration.html#6 cache haproxycache # Legt die maximale Ablaufdauer fest. Der Ablauf wird als der nied- # rigste Wert zwischen der Anweisung „s-maxage“ oder „max-age“ (in # dieser Reihenfolge) im Cache-Control-Antwortheader und diesem # Wert festgelegt. Der Standardwert beträgt 60 Sekunden, was be- # deutet, dass Sie ein Objekt standardmäßig nicht länger als 60 # Sekunden zwischenspeichern können. # https://docs.haproxy.org/3.3/configuration.html#6.2.1-max-age max-age 240 # Legt die maximale Größe der Objekte fest, die zwischengespeichert # werden sollen. Darf nicht größer als die Hälfte von # „total-max-size” sein. Wenn nicht festgelegt, entspricht sie # einem 256stel der Cache-Größe. Alle Objekte, deren Größe # „max-object-size” überschreitet, werden nicht zwischengespeichert. # https://docs.haproxy.org/3.3/configuration.html#6.2.1-max-object-size max-object-size 1024000 # Legt die maximale Anzahl gleichzeitiger sekundärer Einträge mit # demselben Primärschlüssel im Cache fest. Dazu muss die Unterstützung # für „vary“ aktiviert sein. Der Standardwert ist 10 und es sollte # eine streng positive Ganzzahl übergeben werden. # https://docs.haproxy.org/3.3/configuration.html#6.2.1-max-secondary-entries max-secondary-entries 10 # Aktiviert oder deaktiviert die Verarbeitung des Vary-Headers. Wenn # diese Option deaktiviert ist, wird eine Antwort, die einen solchen # Header enthält, niemals zwischengespeichert. Wenn diese Option # aktiviert ist, müssen wir einen vorläufigen Hash für eine Teilmenge # der Request-Header aller eingehenden Requests berechnen (was mit # hohen CPU-Kosten verbunden sein kann), der zur Erstellung eines # sekundären Schlüssels für einen bestimmten Request verwendet wird. # Der sekundäre Schlüssel wird derzeit aus den Inhalten der Header # „accept-encoding”, „referer” und „origin” erstellt. Der Standard- # wert ist „off” (deaktiviert). # https://docs.haproxy.org/3.3/configuration.html#6.2.1-process-vary process-vary off # Definition der Cache-Größe im RAM in Megabytes. Diese Grösse wird # jeweils in Blöcke von 1 KB aufgeteilt, die von den Cache-Einträgen # verwendet werden. Der Maximalwert beträgt hier 4095 MB. # https://docs.haproxy.org/3.3/configuration.html#total-max-size total-max-size 512
Ob der Cache-Speicher im RAM wie gewünscht aktiviert wurde, können wir mit nachfolgendem Aufruf überprüfen. Das Programm socat, welches hier benötigt wird, ist aus dem gleichnamigen Arch Linux Extra Paket socat. Dieses installieren wir uns nun noch.
- Als User:
$ sudo pacman -S socat
- Als Nutzer mit Root-Rechten entsprechend:
# pacman -S socat
Nun steht der Überprüfung nichts mehr im Wege.
# echo "show cache" | socat stdio unix-connect:/var/run/haproxy-admin.sock
0x7f57a73ff03a: hacache (shctx:0x7f57a73ff000, available blocks:262144)
Möchten wir in Erfahrung bringen, ob und wie schneller unser HAProxy mit aktiviertem Cache ist, erfahren wir mit folgenden curl-Abfragen.
Zuerst machen wir eine Abfrage ohne aktiviertem Cache:
# curl -s -w '\nResponse time for: %{url_effective}\n\nLookup Time:\t\t%{time_namelookup}\nConnect Time:\t\t%{time_connect}\nAppConnect Time:\t%{time_appconnect}\nRedirect Time:\t\t%{time_redirect}\nPre-transfer Time:\t%{time_pretransfer}\nStart-transfer Time:\t%{time_starttransfer}\n\nTotal Time:\t\t%{time_total}\n' -o /dev/null https://dokuwiki.nausch.org
Response time for: https://dokuwiki.nausch.org/ Lookup Time: 0.003460 Connect Time: 0.003707 AppConnect Time: 0.030645 Redirect Time: 0.000000 Pre-transfer Time: 0.030845 Start-transfer Time: 0.064222 Total Time: 0.064299
Anschließend aktivieren wir den Cache und führen den curl-Aufruf aus unserer Bash-History erneut aus.
curl -s -w '\nResponse time for: %{url_effective}\n\nLookup Time:\t\t%{time_namelookup}\nConnect Time:\t\t%{time_connect}\nAppConnect Time:\t%{time_appconnect}\nRedirect Time:\t\t%{time_redirect}\nPre-transfer Time:\t%{time_pretransfer}\nStart-transfer Time:\t%{time_starttransfer}\n\nTotal Time:\t\t%{time_total}\n' -o /dev/null https://dokuwiki.nausch.org
Response time for: https://dokuwiki.nausch.org/ Lookup Time: 0.003540 Connect Time: 0.003786 AppConnect Time: 0.033557 Redirect Time: 0.000000 Pre-transfer Time: 0.033749 Start-transfer Time: 0.042963 Total Time: 0.043040
Wir sehen also, die Webseiten werden ca. um ein ⅓ schneller bei Nutzung des cache geladen!
Sektion frontend http-in
Nun beschreiben wir die Frontends, die für den ankommenden Verkehr stehen, die der HA-Proxy annimmt. als erstes definieren wir das frontend http-in.
# vim /etc/haproxy/haproxy.cfg
... # Definition der Verbindungsparameter und -optionen für den ankommenden # HTTP-Traffic. frontend http-in # Ermöglicht die Protokollierung von HTTP-Anfragen, Stream-Stati und # Timern. # https://docs.haproxy.org/3.3/configuration.html#4-option%20httplog option httplog # Definiert eine oder mehrere Listening-Adressen und/oder Ports in # einem Frontend. # In dem Konfigurationsbeispiel sollen auf allen Interfaces und # Adressen auf Port 80 Anfragen entgegen genommen werden. Dazu soll # das Application-Layer Protocol Negotiation (ALPN) in der Reihen- # folge das Hypertext Transfer Protocol (HTTP) in Version 2 zuerst # und dann anschliessend in Version 1.1 angewendet werden. # https://docs.haproxy.org/3.3/configuration.html#4-bind bind ipv4@:80,ipv6@:80 alpn h2,http/1.1 # Durchführung einer HTTP-Umleitung, sofern keine HTTPS-Verbindung # besteht. Einem anfragenden Client der HTTP-Statuscode 301 (moved # permanently) präsentiert, bei dem im „Location“-Header-Feld # (redirect) gesetzt wird. Der Client muss erneut eine Anfrage via # HTTPS-Vernindung stellen, in welcher er die URI des „Location“- # -Header verwenden muss. # https://docs.haproxy.org/3.3/configuration.html#4.2-redirect%20scheme redirect scheme https code 301 if !{ ssl_fc }
Sektion frontend https-in
Anschließend definieren wir das frontend http-in für den ankommenden HTTPS-Verkehr stehen, die der HA-Proxy annehmen soll.
# vim /etc/haproxy/haproxy.cfg
... # Definition der Verbindungsparameter und -optionen für den ankommenden # HTTPS-Traffic. frontend https-in # Ermöglicht die Protokollierung von HTTPS-Anfragen, Stream-Stati und # Timern. # https://docs.haproxy.org/3.3/configuration.html#4-option%20httpslog option httpslog # Definiert eine oder mehrere Listening-Adressen und/oder Ports in # einem Frontend. # In dem Konfigurationsbeispiel sollen auf allen Interfaces und # Adressen auf Port 443 Anfragen entgegen genommen werden. Hier muss # HTTPSA als Protokollsuite verwendet werden. Die zughörigen Verbin- # dungsparameter wie Zertifikatsschlüssel-, Server- und Intermediate- # Zertifikatsdateien sind im Verzeichnis /etc/haproxy/certs/ zu finden. # Ferner soll das Application-Layer Protocol Negotiation (ALPN) in der # Reihenfolge das Hypertext Transfer Protocol (HTTP) in Version 2 zu- # erst und dann anschliessend in Version 1.1 angewendet werden. # https://docs.haproxy.org/3.3/configuration.html#4-bind bind ipv4@:443,ipv6@:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1 # Speichert eine HTTP-Antwort im Cache. Die Speicherung der Antwort- # -Header erfolgt in diesem Schritt, was bedeutet, dass man andere # HTTP-Antwortaktionen verwenden kann, um die Header vor oder nach # der Speicherung der Antwort zu ändern. Diese Aktion ist für die # Einrichtung des Cache-Speicherfilters verantwortlich. # https://docs.haproxy.org/3.3/configuration.html#4.4-cache-store http-response cache-store haproxycache # Versucht, ein zwischengespeichertes Objekt aus dem Cache <name> zu # liefern. Diese Anweisung ist auch für die Speicherung des Caches # obligatorisch, da sie den Cache-Hash berechnet. Wenn man eine # Bedingung sowohl für die Speicherung als auch für die Lieferung # verwenden möchten, ist es ratsam, diese nach dieser Anweisung einzu- #fügen. # https://docs.haproxy.org/3.3/configuration.html#4.4-cache-use http-response cache-store haproxycache # Importiert die im Abschnitt <name> http-errors definierten Fehler- # dateien vollständig oder teilweise. # https://docs.haproxy.org/3.3/configuration.html#4-errorfiles errorfiles haerrors # Auswahl des zugehörigen Backends anhand des Host‑Headers # (URL‑Domain) durch Auswahl jeweils einer definierten ACL. # https://docs.haproxy.org/3.3/configuration.html#4-acl acl host_site_00 hdr(host) -i lb-ha.nausch.org acl host_site_01 hdr(host) -i dokuwiki.nausch.org acl host_site_02 hdr(host) -i www.ebersberger-liedersammlung.de ebersberger-liedersammlung.de acl host_site_03 hdr(host) -i www.wetterstation-pliening.info wetterstation-pliening.info # Wechseln zu einem bestimmten Backend, wenn eine der zuvor definierten # ACL-basierten Bedingung erfüllt ist. # https://docs.haproxy.org/3.3/configuration.html#use_backend use_backend webui if host_site_00 use_backend dokuwiki.nausch.org if host_site_01 use_backend ebersberger-liedersammlung.de if host_site_02 use_backend wetterstation-pliening.info if host_site_03 # Definiert das Default-Backend, welches verwendet werden soll, wenn # keine „use_backend”-Regel übereinstimmt. # https://docs.haproxy.org/3.3/configuration.html#default_backend default_backend fedora
Wir haben hier angegeben, dass der HAProxy die Zertifikats- und Schlüsselinformationen im Unterverzeichnis /etc/haproxy/certs/ finden wird. Wir legen also nun dieses Verzeichnis an.
# mkdir /etc/haproxy/certs/
Nun müssen wir nur noch dafür sorgen, dass der HAProxy dort für die Terminierung des SSL-/TLS-Verkehrs auf der Eingangsseite die entsprechenden Informationen auch vorfindet:
- privaten Schlüssel der Zertifikatesdatei
nausch.org_webkey.pem - Zertifikatesdatei
nausch.org_webcert.pem - Intermediate Zertifikatesdatei der CA, die den CSR signiert hat oder anders ausgedrückt, die das Zertifikat ausgestellt hat.
nausch.org_key_cert_intermediate.pem
Wir wechseln als an Ort und Stelle, wo wir diese drei Dateien vorhalten.
# cd /root
Dort haben wir z.B. folgende Dateien vorliegen.
# ll /root/*.pem
-rw-r----- 1 root root 8902 Feb 26 17:01 nausch.org_key_cert_intermediate.pem -rw-r----- 1 root root 2992 Feb 26 16:59 nausch.org_webcert.pem -rw-r----- 1 root root 3272 Feb 26 17:00 nausch.org_webkey.pem
Nun erstellen wir für jede (Sub-)Domain, die unser HAProxy abfrühstücken soll jeweils in der Form <- Schlüssel -><- Zertifikat -><- Intermediate Zertifikat -> . Im Falle der Domain mit dem Wildcard-Zertifikat für *.nausch.org wäre dies folgender Befehl:
# cat nausch.org_webkey.pem nausch.org_webcert.pem nausch.org_key_cert_intermediate.pem > /etc/haproxy/certs/nausch.org_key_cert_intermediate.pem
backend webui
Für die Administration unseres HAProxy werden wir unter anderem die WEB-GUI benujtzen, um so z.B. Ziele in den Maintenance-Modus zu versetzen, damit diese z.B. keinen Verkehr mehr abbekommen.
# vim /etc/haproxy/haproxy.cfg
... # Definition des Statistic Backends, der WEB-GUI für die Administration # des HAProxy Daemons. backend webui # Definition der URL mit Zugriffskontrolle für Layer-7-Anfragen # https://docs.haproxy.org/3.3/configuration.html#4.2-http-request http-request set-path /webui/%[path] if { hdr(host) -i lb-ha.nausch.org } acl AUTH http_auth(stats-auth) acl AUTH_ADMIN http_auth_group(stats-auth) admin stats enable stats refresh 60s stats show-desc HAProxy\ for\ NAUSCH.ORG stats show-legends stats show-node lb-ha.nausch.org stats uri /webui stats http-request auth realm HAProxy\ WEB-GUI\ for\ statistics\ and\ management unless AUTH stats admin if AUTH_ADMIN
Über die URL https://lb-ha.nausch.org/webui erhält der Administrator dann Zugriff auf die WEB-GUI unseres HAProxy. In unserem konkreten Konfigurationsbeispiel sieht das dann wie folgt aus:
Auf der Konsole kann ein Administrator auch entsprechend tätig werden. So kann man z.B. auf der Konsole über den UNIX-Datei-Socket die Programm-Version abfragen.
# echo "show version" | socat stdio unix-connect:/var/run/haproxy-admin.sock
3.3.4
Eine vollständige Liste aller Befehle erhält man wenn man den Befehl „help“ verwendet.
# echo "help" | socat stdio unix-connect:/var/run/haproxy-admin.sock
Ausgabe des obigen Befehlsaufrufes
Die Liste aller definierten und benutzten BAckend-Systeme erhält man mit der Option show backend.
echo "show backend" | socat stdio unix-connect:/var/run/haproxy-admin.sock
# name statistics dokuwiki.nausch.org ebersberger-liedersammlung.de wetterstation-pliening.info fedora
Eine Übersicht über den Status unseres HAProxys in Form einer strukturierten Tabelle erhält man mit folgendem Aufruf.
# echo "show stat" | socat stdio unix-connect:/var/run/haproxy-admin.sock | cut -d "," -f 1,2,5-11,18,24,27,30,36,50,37,56,57,62 | column -s, -t
Sektion backend dokuwiki.nausch.org
Nun beschreiben wir die Backends, also die Zielesysteme an die der HAProxy den ankommenden Verkehr weiterleiten wird. Als erstes definieren wir das backend dokuwiki.nausch.org. Hier soll der Verkehr auf die beiden WEB-Applikations-Server Apache Webserver I und Apache Webserver II gleichmäßig im roundrobin-Mode verteilt werden.
# vim /etc/haproxy/haproxy.cfg
... # Definition des Backends dokuwiki.nausch.org bei dem die Last gleich- # mäßig im Verfahren roundrobin auf die beiden Apache Webserver I und II # verteilt werden soll. backend dokuwiki.nausch.org # https://docs.haproxy.org/3.3/configuration.html#4-balance balance roundrobin default-server inter 3s fall 2 rise 3 on-marked-down shutdown-sessions # Apache Webserver I server apache_webserver_1_v4 10.0.0.85:443 check ssl verify none # Apache Webserver I server apache_webserver_1_v6 [fd00::03:10:0:0:85]:443 check ssl verify none # Apache Webserver II server apache_webserver_2_v4 10.0.0.86:443 check ssl verify none # Apache Webserver II server apache_webserver_2_v6 [fd00::03:10:0:0:86]:443 check ssl verify none
backend ebersberger-liedersammlung.de
Als nächstes definieren wir das backend ebersberger-liedersammlung.de. Gemäß unserer Vorüberlegungen im Abschnitt Herausforderung / Aufgabenstellung soll der Verkehr primär auf den Apache-Webserver I geroutet werden. Der zweite Web-Applikationsserver Apache-Webserver II ist hier „nur“ cold-stand-by, erreicht wird dies durch die Option disabled. Dadurch ist der Weg im Maintenance-Modus und das Zielö bekommt nur dann Verkehr ab, wenn ein Admin manuell eingreift und dieses Backendsystem aktiviert.
# vim /etc/haproxy/haproxy.cfg
... # Definition des Backends ebersberger-liedersammlung.de bei dem die Last # primär auf dem Apache-Webserver I ankommen soll. Der zweite Apache- # - Webserver wird als cold-stand-by vorgehalten und soll nur dann Ver- # kehr abbekommen, wenn ein Admin manuell eingreift und dieses Backend- # system aktiviert. backend ebersberger-liedersammlung.de # Apache Webserver I server apache_webserver_1_v4 10.0.0.85:443 check ssl verify none # Apache Webserver I server apache_webserver_1_v6 [fd00::03:10:0:0:85]:443 check ssl verify none # Apache Webserver II server apache_webserver_2_v4 10.0.0.87:443 disabled check ssl verify none # Apache Webserver II server apache_webserver_2_v6 [fd00::03:10:0:0:87]:443 disabled check ssl verify none
backend wetterstation-pliening.info
Nun Definieren wir das backend wetterstation-pliening.info bei dem es systembedingt lediglich ein Ziel gibt.
# vim /etc/haproxy/haproxy.cfg
... # Definition des Backends wetterstation-pliening.info bei dem nur der # Apache-Webserver II angesprochen werden soll. Hier gibt es *keinen* # cold-stand-by Webapplikations-Server. backend wetterstation-pliening.info # Apache Webserver II server apache_webserver_2_v4 10.0.0.87:443 check ssl verify none # Apache Webserver II server apache_webserver_2_v6 [fd00::03:10:0:0:87]:443 check ssl verify none
Sektion backend fedora
Zu guter Letzt brauchen wir noch ein Backend-System bei dem all der Verkehr dann weitergereicht werden soll, wenn wir keinen Treffer bei unseren acl Definitionen bekommen, weil wir keinen expliziten Weg für diese vHosts in der Sektion frontend https-in vorgegeben haben.
# vim /etc/haproxy/haproxy.cfg
... # Definition des Default-Backends. Hier soll aller HTTP/HTTPS-Traffic # abgeladen werden, für deren URLs keine der ACLs greift, die in der # Section https_in zutrifft. backend fedora # Fedora-Node server apache_fedora_webserver_v4 10.0.0.107:443 check ssl verify none # Fedora-Node server apache_fedora_webserver_v6 [fd00::03:10:0:0:107]:443 check ssl verify none
haproxy.cfg
Haben wir alle Sektionen in unserer HAProxy-Konfigurationsdatei, wie soeben aufgezeigt, hinterlegt. ergibt sich folgende Gesamtkonfigurationsdatei.
# vim /etc/haproxy/haproxy.cfg
vollständige Konfigurationsdatei /etc/haproxy/haproxy.cfg
Dem Puristen, der eine Konfigurationsdatei ohne jedwede Kommentare benötigt, kann sich natürlich auch einen geraffte Version ausgeben lassen.
# grep -Ev '(^.*#|^$)' /etc/haproxy/haproxy.cfg
Konfigurationsdatei ohne Kommentare, erstellt mit Hilfe des obigen Befehlsaufrufes
WICHTIG:
Immer dann wenn wir manuell die Konfigurationsdatei /etc/haproxy/haproxy.cfg eines gerade laufenden HAProxys bearbeitet haben, sind wir gut beraten vor dem Neustart des HAProxy-Daemons die Konfigurationsdatei auf etwaige Vertipper hin zu überprüfen. Folgneder Befehl leistet uns hierbei unschätzbare Hilfe:
# haproxy -c -f /etc/haproxy/haproxy.cfg
Da kein Typo-Error in der Datei ist steht einem Neustart des Daemon nichts im Wege.
# systemctl restart haproxy.service
ChangeRoot-Umgebung
Bei der Installation des haproxy Paketes wurden wir auf folgenden Umstand hingewiesen:
==> The example config chroots HAProxy, meaning that logging to journald won't work.
Either disable chrooting, use rsyslog, or bind /run/systemd/journal/dev-log into the chroot.
Wir werden also nun auch noch die Chroot-Umgebung passend einrichten und vervollständigen.
haproxy.cfg
Wir ergänzen zunächst unsere Zuvor angelegte HAProxy Konfigurationsdatei /etc/haproxy/haproxy.cfg. In der Sektion global fügen wir nun den nachfolgenden Abschnitt ein vor der Definition von user haproxy ein.
# vim /etc/haproxy/haproxy.cfg
... # Wechselt das aktuelle Verzeichnis zu <jail dir> und führt dort einen # chroot() aus, bevor die Berechtigungen aufgehoben werden. Dies erhöht # die Sicherheit für den Fall, dass eine unbekannte Schwachstelle aus- # genutzt wird, da es für den Angreifer sehr schwierig wäre, das System # zu kompromittieren. Dies funktioniert nur, wenn der Prozess mit # Superuser-Rechten gestartet wird. Es ist wichtig sicherzustellen, # dass <jail_dir> leer und für niemanden beschreibbar ist. # https://docs.haproxy.org/3.3/configuration.html#chroot chroot /var/lib/haproxy ...
Unsere Änderung überprüfen wir auf zufällig gemachte Typofehler.
# haproxy -c -f /etc/haproxy/haproxy.cfg
/var/lib/haproxy
Bevor aber nun die Änderungen an der Konfiguration scharf schalten indem wir den gerade laufenden Daemon neu starten, müssen wir noch das zugehörige Verzeichnis und eine device-Datei auf das gemounted als chroot-Verzeichnis gemounted werden kann, anlegen.
# mkdir -p /var/lib/haproxy/dev
# touch /var/lib/haproxy/dev/log
Anschließend passen wir noch die Dateiberechtigungen an und weisen dem Benutzer root dieses Verzeichnis mit der darin enthaltenen Datei zu.
# chown -R root: /var/lib/haproxy
# chmod -R 755 /var/lib/haproxy
var-lib-haproxy-dev-log.mount
Grundsätzlich gilt bei chroot-Umgebungen, dass auf Bereiche außerhalb dieser Umgebung nicht mehr zugegriffen werden kann,
u.a. ein grundlegende Idee bei diesen chroot-Umgebungen!
Wir müssen daher dafür sorgen, dass für die LOG-Ausgabe in Richtung journal die Device-Datei /dev/log in der chroot-Umgebung verfügbar ist und darauf zugegriffen werden kann! Wir werden daher mit Hilfe des systemd „in die chroot-Umgebung' gemounted wird.
Wir legen uns dazu die Datei /etc/systemd/system/var-lib-haproxy-dev-log.mount mit nachfolgendem Inhalt an.
# vim /etc/systemd/system/var-lib-haproxy-dev-log.mount
- /etc/systemd/system/var-lib-haproxy-dev-log.mount
[Unit] Requires=systemd-journald.service Description=Expose Systemd Log for HAProxy [Mount] What=/dev/log Where=/var/lib/haproxy/dev/log Type=none Options=bind
Unsere Änderungen müssen wir nun dem systemd-Daemon mit nachfolgendem Befehl bekannt gemacht werden:
# systemctl daemon-reload
Zum Schluß müssen wir nun noch dafür sorgen, dass der mount der zuvor erstellten systemd-unit-Datei vor dem Start des HAProxy erfolgt, was innerhalb der systemd-unit-Startdatei des haproxy-Daemon erfolgen kann. Hierzu editieren wir die betreffende Unit-Datei des HAProxys und tragen im oberen Abschnitt der Datei, die wir folgt gekennzeichnet ist:
### Editing /etc/systemd/system/haproxy.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file
### Edits below this comment will be discarded
die beiden Zeilen
[Unit]
Requires=var-lib-haproxy-dev-log.mount
ein, so dass dies nun wie folgt aussieht:
### Editing /etc/systemd/system/haproxy.service.d/override.conf ### Anything between here and the comment below will become the contents of the drop-in file [Unit] Requires=var-lib-haproxy-dev-log.mount ### Edits below this comment will be discarded
Auch diese Änderung müssen wir nun noch ebenfalls dem systemd-Daemon bekannt gemacht werden:
# systemctl daemon-reload
Es ist somit folgende Datei erzeugt worden:
# vim /etc/systemd/system/haproxy.service.d/override.conf
- /etc/systemd/system/haproxy.service.d/override.conf
[Unit] Requires=var-lib-haproxy-dev-log.mount
Neustart des Daemon
Bevor wir nun aber nun zur Aktivierung unserer Konfigurationsänderungen den haproxy-Daemon einmal durchstarten werfen, prüfen wir zur Sicherheit noch einmal, ob in der Konfigurationsdatei /etc/haproxy/haproxy.cfg sich kein syntaktischer Fehler eingeschlichen hat.
# haproxy -c -f /etc/haproxy/haproxy.cfg
[NOTICE] (18392) : haproxy version is 3.3.4 [NOTICE] (18392) : path to executable is /usr/bin/haproxy [ALERT] (18392) : config : parsing [/etc/haproxy/haproxy.cfg:46] : unknown keyword 'https://docs.haproxy.org/3.3/configuration.html' in 'global' section [ALERT] (18392) : config : Error(s) found in configuration file : /etc/haproxy/haproxy.cfg [ALERT] (18392) : config : Fatal errors found in configuration.
Hoppala, da müssen wir also nochmals ran! Ahhh, da haben wir doch ein # vergessen bei Zeile 46! Also kurz korrigieren und erneut testen …
# haproxy -c -f /etc/haproxy/haproxy.cfg
Nun steht dem Neustart des HAProxy Daemons nichts mehr im Wege.
# systemctl restart haproxy.service
Orchestrierung
Im Jahr 2026 wird niemand mehr wirklich händisch einen HAProxy aufsetzen und betreiben wollen. Vielmehr wird man hier auf ein entsprechendes Orchestrierungswerkzeug zurück greifen!
So zeigt das nachfolgende Beispiel wie z.B. automatisiert auf einem bestehenden ARch Linux System, der HA-Proxy installiert und gemäß dem obigen Konfigurationsbeispiel konfiguriert werden kann.
20:22 $ ansible-playbook playbooks/arch_haproxy.yml --limit vml000080
Ausgaben beim Aufruf von ansible-playbook playbooks/arch_haproxy.yml --limit vml000080
HAProxy und ACME
coming soon …
