Ansible

Einleitung

Wer Server betreibt wird sich früher oder später die Frage stellen, wie diese Server möglichst sauber (und ggf. auch möglichst homogen) konfiguriert werden können. Weil das so ist, gibt es hierfür auch gleich eine ganze Reihe von entsprechenden Tools, z.B. SaltStack1, Ansible2, Puppet3, Chef4, CFEngine5 und Terraform6, um nur einige zu nennen. Persönlich habe ich sehr viel mit SaltStack gearbeitet, aber auch Ansible kam hier und da zum Einsatz. Im ersten Moment wirken SaltStack und Ansible auch sehr ähnlich. Beide setzen stark auf YAML7 und Jinja8. Unter der Haube unterscheiden sie sich aber dann doch recht deutlich. Salt setzt auf einen zentralisierten Ansatz mit eigenem Server, Clients und entsprechendem Protokoll, Ansible nutzt einfach SSH-Verbindungen und benötigt keinen zentralen Server zur Steuerung. Ansible ist zudem stärker darauf ausgelegt in den sog. Tasks Bezug auf vorangegangene Schritte zu nehmen dadurch fühlt sich Ansible (für mich) etwas "scriptiger" an. Ob man das gut oder schlecht findet, ist vermutlich Geschmackssache.

An sich mag ich den zentralistischen Ansatz von Salt sehr gern, durch das eigene Protokoll ist Salt auch um einiges schneller als Ansible, welches ja jeden einzelnen Step über eine SSH-Verbindung ausführen muss. Aber gerade wenn man z.B. gar keinen zentralen Server für die Verwaltung der Infrastruktur bereitstellen kann oder möchte, ist Ansible mir hier lieber (auch wenn es salt-ssh9 gibt). Deswegen und weil ich einfach gerne mal wieder etwas mit Ansible machen wollte, habe ich mein kleines Heimsetup in den letzten Wochen unter Ansibleverwaltung gestellt.

In letzter Zeit hatte ich häufiger DNS-Probleme nachdem mein Rechner aus dem Suspend zurückkehrt. Ich vermute, dass während bzw. vor dem Suspend mein WLAN Interface deaktiviert wird und aus irgendeinem Grund scheint systemd1 es nicht für nötig zu halten die DNS Einstellungen erneut zuzuweisen, wenn das Gerät wieder aktiviert wird. Eine korrekte Lösung über systemd-resolved2 habe ich auf die Schnelle nicht finden können (und hatte ehrlich gesagt auch wenig Lust mich da tiefer einzuarbeiten und überlege auch ständig einfach wieder die gute alte /etc/resolv.conf zu nutzen).

Aber hier soll es ja auch gar nicht um meine DNS-Auflösung gehen, sondern um das Ausführen von Scripten/Befehlen beim Wechsel des Suspend-Status.

Im Artikel SSH-Keys mit Yubikey hatte ich erläutert, wie man einen SSH-Key mit einem Yubikey1 absichert/ersetzt. Aber natürlich kann man auch die Anmeldung am Rechner mit einem Yubikey absichern.

Ich hatte diesen Artikel bei der Einrichtung des Blogs geschrieben und ihn beim Aufräumen der Testeinträge mitgelöscht. Leider hatte ich zu diesem Zeitpunkt noch keine Versionierung eingerichtet. Ich habe mich daher entschlossen den Artikel einmal von OpenAI/ChatGPT neu erstellen zu lassen. Das Ergebnis kann sich durchaus sehen lassen.

Ich habe folgenden Prompt verwendet:

Schreibe einen Artikel, der die Funktion und Einrichtung von Wireguard unter Linux (Server und Client) beschreibt. Zeige jeweils beispielhafte Konfigurationsdateien und nutze Preshared Keys. Erkläre zudem die nötigen Einstellungen (iptables und sysctl) zum Forwarden von Traffic und binde diese in die Wireguard Konfigurationsdatei ein (postup/postdown). Erkläre jede Zeile der Konfigurationsdateien im Detail.

Das Ergebnis war ok, man hätte eine funktionierende Konfiguration erhalten. Allerdings hat ChatGPT eine separate Konfiguration für iptables erzeugt (/etc/iptables/rules.v4). Dies war anders gefordert, daher habe ich ChatGPT gebeten den Artikel erneut zu schreiben:

Die iptables Befehle sollen in die Wireguard Konfigurationsdateien übernommen werden. Schreibe den Artikel neu.

Das hat OpenAI so umgesetzt, die Postup/Postdown Befehle für iptables aber auch in die Client-Konfigurationsdatei geschrieben, was natürlich komplett sinnlos ist. Daher habe ich OpenAI erneut gebeten den Artikel neu zu verfassen:

Die iptables Befehle sind nur in der Server Konfigurationsdatei sinnvoll. Schreibe den Artikel neu.

Das Einzige was nun noch fehlte, waren die Preshared Keys:

Das ist gut, es fehlen aber die Preshared Keys. Schreibe den Artikel neu.

ChatGPT hat daraufhin zwar die Konfigurationseinträge in die beiden Konfigurationsateien aufgenommen, aber den Befehl zum Erzeugen des Preshared Keys nicht erwähnt.

Es fehlt der Befehl zum Erzeugen des Preshared Keys. Schreibe den Artikel neu.

Das Ergebnis ist der folgende Artikel. Sein einziges Manko ist vielleicht noch die Erklärung des Unterschieds des AllowedIPs Eintrags zwischen Server und Client. Auf Serverseite legt AllowedIPs die IP-Adresse des Clients fest, nutzt also das Subnet /32. Auf dem Client gibt AllowedIPs die Subnets an, die vom Wireguard-Server geroutet werden sollen. Gibt man hier z.B. 0.0.0.0/0 an, wird der gesamte Traffic über das VPN geleitet.

Ich habe ChatGPT daher gebeten, diesen Unterschied separat zu erläutern:

Erläutere den Unterschied der AllowedIPs Konfigurationsanweisung zwischen Client und Server.

Das Ergebnis habe ich als Hinweis unter das Fazit des eigentlichen Artikels angehängt.

Ich kenne eine ganze Reihe von IT-Leuten, die täglich SSH nutzen. Doch die wenigsten nutzen eine ~/.ssh/config1. Dabei ist sie ein durchaus mächtiges Werkzeug und kann den SSH-Workflow stark vereinfachen und bereichern.

Nachdem wir die Datenerfassung mit Prometheus bewerkstelligt haben, ist es nun natürlich sinnvoll auch eine Datenvisualisierung einzurichten. Hier kommt Grafana1 ins Spiel.

Es kommt leider immer mal wieder vor, dass ein automatisierter Prozess auf ein Problem stößt und daher seine Verarbeitung abbricht. Das ist meistens kein Problem, man schaut nach woran es gelegen hat, behebt das Problem und führt den Prozess erneut aus. In manchen Fällen nimmt ein Script aber bestimmte Vorarbeiten vor, die ein erneutes Ausführen behindern, z.B. könnte ein Script Snapshots erzeugen und Mounten. Versucht man dies ein zweites Mal, wird dies zu Fehlermeldungen führen. Nutzt ein Script dann z.B. set -e1 um bei Fehlern die weitere Ausführung abzubrechen, haben wir ein Problem und müssen die abschließenden Arbeiten des Scripts einmal manuell ausführen. Das kann realtiv komplex werden, vor allem weil man solche - eigentlich automatisierten - Vorgänge ja meist nicht mehr so wirklich auf dem Schirm hat.

Immer wieder gibt es Prozesse die sehr lange dauern und die auf keinen Fall doppelt gestartet werden sollten. Vor vielen Jahren bin ich über eine Lösung für Lockfiles in Bash-Scripten gestolpert, die ich seitdem in fast jedem Script mit potenziell langer Laufzeit nutze.

Das Backuptool borg1 habe ich hier ein wenig beschrieben. Nun soll es darum gehen mittels borg saubere Backups zu erstellen und auch sicherzustellen, diese jederzeit wiederherstellen zu können.

LVM (Logical Volume Manager) erlaubt im Grunde die flexiblere Verwaltung von "Partitionen" einer Festplatte. Anstatt die Partitionen beim Einrichten eines Datenträgers (z.B. mittels fdisk) einmal - mehr oder weniger - fix festzulegen, erzeugt man mit LVM sog. Volume Groups (VG). Eine solche Volume Group kann mehrere physikalische Datenträger umfassen1. Innerhalb der Volume Groups werden dann die eigentlichen Logical Volumes (LV) erzeugt. Diese können dann wie physikalische Datenträger behandelt und mit beliebigen Dateisystemen versehen werden.

Ein weiteres Feature von LVM sind sog. Snapshots. Ein Snapshot friert den Zustand des Dateisystems zum Zeitpunkt der Erstellung des Snapshots quasi ein. Die Daten im Snapshot verändern sich nicht mehr. Technisch funktioniert dies über das sog. Copy on write2. Dies ist sehr hilfreich um konsistente Backups erstellen zu können.