Warum Server-Configs in Git gehören und nicht in deinen Kopf
Werbung
Fast jeder Server, den ich übernehme, leidet unter demselben stillen Problem: Die Configs funktionieren zwar, aber niemand kann dir mehr sagen, warum sie so aussehen, wie sie aussehen.
In einem Nginx-vHost wurde das proxy_read_timeout auf 300 Sekunden hochgesetzt. Eine fail2ban-Jail hat eine per Whitelist freigegebene IP-Range. Ein sysctl-Tweak verdoppelt ein Connection-Limit. Jede dieser Änderungen war zum damaligen Zeitpunkt wahrscheinlich goldrichtig. Sie wurde live gemacht, unter Zeitdruck, und danach nirgends dokumentiert – außer in der Datei selbst. Ein halbes Jahr später weiß niemand mehr, welche Zeilen das System tragen und welche nur Überbleibsel von alten Experimenten sind. Und niemand möchte derjenige sein, der die falsche Zeile entfernt.
Die schlankeste Lösung: etckeeper
Für einen einzelnen Server ist etckeeper der kleinste, aber nützlichste Schritt. Das Tool packt /etc unter Git und committet automatisch, sobald ein Paketmanager eine Konfigurationsdatei anfasst:
apt install etckeeper
cd /etc
git log --oneline -10
Von diesem Moment an wird jede manuelle Änderung bei der nächsten Paketinstallation mit erfasst – oder man pusht sie direkt nach der Bearbeitung selbst mit git add -A && git commit. Die wahre Belohnung dafür erntet man, wenn das erste Mal etwas nach einer Config-Änderung bricht und man diesen Befehl ausführt:
git log -p -- nginx/sites-enabled/example.com
Man sieht exakt, was wann geändert wurde – und wenn man eine Commit-Nachricht hinterlassen hat, auch warum. Dieser letzte Punkt ist entscheidend. Ein git commit -m "proxy_read_timeout für langsamen Report-Export erhöht" macht den Unterschied, ob das Zukunfts-Ich eine Config versteht oder ob es Angst hat, sie anzufassen.
Für mehrere Server: Ein Config-Repo pro Kunde
etckeeper ist lokal an eine Maschine gebunden. Das reicht für einen einzelnen VPS völlig aus, skaliert aber nicht, wenn ein Kunde drei oder vier Server mit zusammenhängenden Konfigurationen betreibt. Für diese Fälle pflege ich ein separates Git-Repo, das nach Hosts strukturiert ist:
client-configs/
├── web-01/
│ ├── nginx/sites-available/example.com
│ └── fail2ban/jail.local
├── db-01/
│ ├── postgresql/postgresql.conf
│ └── pgbackrest/pgbackrest.conf
└── deploy.sh
Änderungen passieren lokal. Sie werden über einen Diff geprüft, bevor sie das System verlassen. Danach pusht ein kurzes deploy.sh-Skript die entsprechenden Dateien auf den richtigen Host:
#!/bin/bash
HOST=$1
rsync -av "$HOST/" "deploy@$HOST.internal:/" --dry-run
# --dry-run entfernen, sobald das Diff sauber aussieht
Das --dry-run als Standard ist reine Absicht. Config-Deployments sind genau die Art von Aufgabe, bei der ein versehentlicher abschließender Slash (/) im rsync viel mehr überschreiben kann als gewollt. Das Standardverhalten zwingt einen dazu, vorher anzuschauen, was sich ändern wird.
Was dir das bringt (und ein Wiki nicht)
Die übliche Alternative ist ein Wiki oder eine README-Datei mit "wichtigen Config-Änderungen". Diese verrotten fast sofort. Ein Wiki zu aktualisieren ist ein separater Schritt, der nichts mit der eigentlichen Arbeit zu tun hat – und unter Zeitdruck fallen separate Schritte als Erstes unter den Tisch. Eine Git-Historie hat dieses Problem nicht: Die Dokumentation ist ein natürliches Abfallprodukt der eigentlichen Arbeit.
Gleichzeitig erzwingt es einen anderen Workflow. Wenn eine Config in Git liegt, ist es viel natürlicher, sie lokal zu editieren, mit einer kurzen Begründung zu committen und sie dann zu deployen – anstatt sich per SSH einzuwählen und die Live-Datei direkt zu hacken. Der größte Wert liegt nicht in der reinen Backup-Funktion, sondern in der Gewohnheit, das Warum aufzuschreiben, kurz bevor man das Was tut.
Wenn du drei Monate später auf eine Config starrst und dich fragst, ob du diese eine Zeile gefahrlos löschen kannst, dann spart dir genau dieser eine Satz in der Commit-Message eine Stunde an vorsichtiger IT-Archäologie.
Werbung