HAProxy unter ArchLinux installieren und einrichten

BILD: HAProxy Community Edition Logo 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.

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.

Bild: Systemskizze der grundlegenden Netzwerkstruktur bei nausch.org

Mit Hilfe von HAProxy wollen wir nun genau folgende Punkte erledigen:

  1. 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.
  2. 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.
  3. Die Wetterstation Pliening hingegen läuft aktuell systembedingt nur auf dem Apache-Webserver II.
  4. Aller anderer Verkehr soll ausnahmslos direkt zu dem Fedora-Node weiter gereicht werden.
  5. Sofern die Ressource für die Weiterleitung nicht zur Verfügung steht, soll ein Besuchender eine entsprechende Hinweisseite angezeigt bekommen.

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 Manualconfiguration.txt sowie weitere erklärende Dokumente,
    sowie im Unterordner /usr/share/haproxy/examples viele 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

haproxy manpage

Die Installation und Konfiguration des HAProxy gestaltet sich relativ einfach. Zur Installation des Paketes verwenden wir unter Arch Linux den Paketmanager pacman.

  1. Als User:
     $ sudo pacman -S haproxy
  2. 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

Paketinhalt haproxy

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:

  1. Logging aktivieren:
     # firewall-cmd --set-log-denied=all
  2. Firewall-Zone anlegen:
     # firewall-cmd --permanent --new-zone=idmz
     # firewall-cmd --reload
  3. Netzwerkinterfaces der Zonen zuordnen:
     # firewall-cmd --permanent --zone=idmz --add-interface=net0
     # firewall-cmd --reload
  4. Firewalld Default Zone setzen:
     # firewall-cmd --set-default-zone idmz
  5. 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
  6. Regelwerk persistieren:
     # firewall-cmd --reload
  7. 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

erster manueller Start

 # systemctl start haproxy.service

Im Journal wird der Start unseres HTTP-Servers entsprechend vermerkt.

 # journalctl -fu haproxy

Ausgabe im journal

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

Ausgabe des Befehls 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'.

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.org bei 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.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 Verkehr abbekommen, wenn ein Admin manuell eingreift und dieses Backend-System aktiviert.
    • backend wetterstation-pliening.info : 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 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_in zutrifft.

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.

  1. Als User:
     $ sudo pacman -S socat
  2. 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:

  1. privaten Schlüssel der Zertifikatesdatei nausch.org_webkey.pem
  2. Zertifikatesdatei nausch.org_webcert.pem
  3. 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:

Bild: Bildschirmhardcopy der HAProxy WEB-GUI

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

Ergebnis des obigen Befehlsaufrufs

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

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

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

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

FIXME coming soon … FIXME

Links

Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
  • linux/haproxy.txt
  • Zuletzt geändert: 09.03.2026 11:09.
  • von django