Die Frage taucht in fast jedem unserer Beratungsgespraeche auf: “Wir haben hier einen Ordner voller Bash-Skripte — sollen wir auf Ansible umsteigen?” Die ehrliche Antwort lautet: Es kommt darauf an. Und zwar nicht auf das Buzzword-Bingo, sondern auf die Anzahl der Server, die Groesse des Teams und die Frequenz der Aenderungen.
In diesem Artikel zeigen wir den Kipppunkt, an dem der Wechsel von Bash zu Ansible tatsaechlich Zeit spart — und wann er nur Overhead produziert. Mit konkretem Migrationsbeispiel aus einem echten SMB-Projekt.
Der Ausgangspunkt: Warum Bash trotzdem lebt
Bash ist nicht tot. Bash ist auf jedem Linux-System vorinstalliert, hat keine Abhaengigkeiten, laesst sich per SSH auf jeden Host schieben und ist von jedem Admin lesbar. Fuer eine Handvoll Server — sagen wir zehn Proxmox-Nodes, drei TrueNAS-Systeme und zwei OPNsense-Firewalls — ist ein sauber strukturiertes Git-Repository mit Shell-Skripten oft die beste Loesung. Kein Kontrollknoten, kein YAML-Overhead, keine Python-Abhaengigkeiten auf den Zielen.
Der Klassiker sieht dann so aus:
#!/usr/bin/env bash
# update-node.sh -- Debian/Proxmox-Node updaten
set -euo pipefail
HOST="$1"
ssh "root@${HOST}" 'apt-get update && apt-get -y dist-upgrade && apt-get -y autoremove'
ssh "root@${HOST}" 'systemctl reboot'
Das funktioniert. Bis es das nicht mehr tut. Der Bruch kommt nicht schleichend, sondern an einem Freitagnachmittag, wenn ein Kollege denselben Befehl zweimal ausfuehrt oder ein Skript ohne set -e mittendrin abbricht und den Node in einem Zwischenzustand hinterlaesst.
Der Kipppunkt: Idempotenz wird zur Pflicht
Ab etwa 30 bis 50 verwalteten Systemen aendert sich die Physik. Nicht weil Bash technisch nicht mehr koennte, sondern weil zwei Eigenschaften kritisch werden, die Bash nicht mitbringt:
- Idempotenz — ein Skript beliebig oft ausfuehren zu koennen, ohne Schaden anzurichten.
- Inventarisierung — die Zuordnung “welcher Host bekommt welche Konfiguration” muss deklarativ, nicht in Skripten versteckt sein.
Ein Bash-Skript, das useradd monitoring aufruft, scheitert beim zweiten Lauf. Ein Ansible-Task ansible.builtin.user: name=monitoring state=present prueft den Zustand und tut beim zweiten Lauf schlicht nichts. Klingt banal, ist aber der Unterschied zwischen “ich fuehre das Playbook einmal pro Monat gegen alle Hosts aus” und “ich baue eigene Zustandspruefungen in jedes Skript ein”.
Die Faustregel aus unseren Kundenprojekten:
| Umgebung | Server-Zahl | Aenderungen/Monat | Empfehlung |
|---|---|---|---|
| Klein | 5-15 | 1-2 | Bash + Git, ssh in Schleife |
| Mittel | 15-40 | 3-10 | Bash strukturiert, ggf. Ansible-Ad-hoc |
| Wachsend | 40-100 | 10+ | Ansible mit Rollen und Inventory |
| Gross | 100+ | woechentlich | Ansible + AWX/Semaphore, CI/CD |
Der Uebergang von “wachsend” zu “gross” ist fliessend. Wichtiger als die reine Serverzahl ist die Zahl der Personen, die auf die Systeme zugreifen. Sobald mehr als zwei Admins parallel arbeiten, ist ein deklarativer Zustand Gold wert.
Migrationsbeispiel: Vom Skript zum Playbook
Nehmen wir einen konkreten Fall aus einem Linux-Consulting-Projekt: Ein Fertigungsbetrieb betrieb 42 Ubuntu-LTS-Server (24.04) auf zwei Proxmox-Clustern, plus zwoelf Debian-basierte Application-Server. Die Basiskonfiguration — SSH-Haertung, Monitoring-Agent, Backup-Client, Log-Shipping — lag in acht Bash-Skripten, die per Ansible… aeh, per for host in $(cat hosts.txt); do ssh ... verteilt wurden.
Das funktionierte drei Jahre lang. Dann kam der Wechsel von rsyslog auf journald-Remote-Forwarding, und ploetzlich hatten die Skripte drei Verzweigungen pro Host je nach Alter, Distributionsversion und ob ein frueherer Kollege manuell etwas veraendert hatte. Der Aufwand pro Rollout stieg von einer Stunde auf einen ganzen Tag.
Der Umbau lief in drei Schritten:
Schritt 1: Inventory extrahieren. Aus der bisherigen hosts.txt wurde eine strukturierte inventory.yml:
all:
children:
proxmox_hosts:
hosts:
pve01.intern:
pve02.intern:
app_servers:
hosts:
app[01:12].intern:
vars:
backup_target: nas01.intern
db_servers:
hosts:
db[01:04].intern:
vars:
backup_target: nas02.intern
Schritt 2: Ein Basis-Rolle statt acht Skripten. Die acht Shell-Skripte wurden zu einer Ansible-Rolle common mit Tasks fuer SSH-Config, User-Management, Monitoring-Agent und Log-Forwarding zusammengefuehrt. Jeder Task wurde bewusst idempotent formuliert:
- name: SSH -- root-Login per Passwort deaktivieren
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin prohibit-password'
validate: 'sshd -t -f %s'
notify: restart sshd
- name: Monitoring-Agent installieren
ansible.builtin.apt:
name: prometheus-node-exporter
state: present
update_cache: yes
cache_valid_time: 3600
Schritt 3: Dry-Run und Rollout. ansible-playbook site.yml --check --diff gegen alle 54 Hosts zeigte, welche Systeme abweichen — ohne etwas zu aendern. Das war der Aha-Moment fuer das Team: Zum ersten Mal war der Ist-Zustand aller Hosts auf einer Seite sichtbar.
Der eigentliche Rollout lief anschliessend in vier Wellen a zwoelf bis fuenfzehn Hosts. Zeitbedarf: knapp drei Stunden statt vorher acht.
Was Ansible nicht loest
Ansible ist kein Wundermittel. Drei Punkte, die wir in jedem Beratungsgespraech betonen:
Erstens: Ansible ersetzt kein Monitoring. Ein Playbook, das erfolgreich durchlaeuft, sagt nichts darueber aus, ob der Dienst danach tatsaechlich Anfragen beantwortet. ansible.builtin.uri als Post-Check ist Pflicht, aber ein echtes Monitoring mit Zabbix, Checkmk oder Prometheus bleibt daneben notwendig.
Zweitens: Ansible ist langsam. Fuer 200 Hosts mit einer komplexen Rolle koennen Playbook-Laufzeiten von 20 bis 40 Minuten entstehen. strategy: free, serial-Batches und Mitigationen wie Pipelining oder Fact-Caching helfen, aber wer Sub-Minuten-Deployments braucht, schaut Richtung Salt oder Immutable Infrastructure.
Drittens: YAML ist nicht selbsterklaerend. Ein 2000-Zeilen-Playbook mit Jinja-Templates, when-Bedingungen und Handlern kann genauso unwartbar sein wie ein Bash-Wildwuchs. Ohne klare Rollen-Struktur, Namenskonventionen und Peer-Review verlagert sich das Problem nur.
Der pragmatische Mittelweg
Fuer viele mittelstaendische Umgebungen empfehlen wir eine hybride Strategie: Bash bleibt fuer einmalige Wartungsjobs, Notfall-Skripte und Boot-Automatisierungen. Ansible uebernimmt alles, was wiederholt oder auf mehreren Hosts synchron passieren soll. Der Kontrollknoten kann eine kleine VM auf dem Proxmox-Cluster sein, ein Ansible-Aufruf pro Nacht per Cron reicht fuer den Anfang. AWX oder Semaphore als Web-UI kommen erst, wenn Nicht-Admins Playbooks anstossen sollen.
Wichtig ist die Disziplin, jede Aenderung ueber Ansible laufen zu lassen — auch wenn “einmal schnell per SSH” schneller waere. Sobald zwei Wege existieren, driftet der Zustand.
Fazit
Bash ist kein Anfaenger-Werkzeug, und Ansible ist keine Silberkugel. Der Kipppunkt liegt weniger bei einer bestimmten Serverzahl als beim Moment, in dem drift zwischen “so soll es sein” und “so ist es tatsaechlich” auftritt. Wer den Zustand seiner Server nicht mehr in zehn Minuten pruefen kann, hat Ansible noetig — egal wie viele Systeme es sind.
DATAZONE unterstuetzt kleine und mittlere IT-Teams beim strukturierten Aufbau von Ansible-Rollen, Inventory-Design und der Migration bestehender Skript-Landschaften. Von der ersten Rolle bis zur produktiven AWX-Instanz auf Proxmox — sprechen Sie uns an unter /kontakt/, wir schauen uns Ihre Automations-Landschaft gemeinsam an und finden den richtigen Zeitpunkt fuer den Wechsel.
Mehr zu diesen Themen:
Weitere Artikel
Samba als Active Directory: Windows-Domäne ablösen
Windows Server AD durch Samba 4 AD-DC ersetzen: DNS mit BIND9, Replikation, Gruppenrichtlinien-Grenzen und Koexistenz während der Migration.
systemd-networkd vs. NetworkManager: Wann was auf Servern
systemd-networkd oder NetworkManager auf Linux-Servern? Vergleich der Netzwerkstacks mit Bridge-, VLAN- und Migrations-Beispielen für Proxmox, KVM und Container.
Proxmox Templates + Cloud-Init: Ein Praxis-Workflow
Proxmox Templates mit Cloud-Init automatisieren: Vom Cloud-Image zum reproduzierbaren VM-Deployment mit Bash-Skript, das 10 VMs in unter 60 Sekunden ausrollt.