- Python 91.4%
- Shell 3.3%
- Nix 3.1%
- Just 2.2%
- 14 Switches unter switches.{cisco,fs} (Portalbrücke LS/STS = fs, Rest cisco),
je mit ansible_host und standort-Label. Nebenbei die Gruppen korrekt unter
switches.children gehängt (lagen ohne children und wurden ignoriert).
- playbooks/switches-ping.yml: ICMP-Test vom Control-Node (connection: local),
mit Retries und throttle gegen sporadischen Paketverlust / ICMP-Rate-Limits.
- playbooks/switches-connect.yml: SSH-Verbindungstest via raw, mit Legacy-SSH-
Defaults (ssh-rsa Host-Key/Pubkey, IdentitiesOnly) für alte Switch-Stacks.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FUpAY7ioxQJCsLNbFgHGLP
|
||
|---|---|---|
| files | ||
| inventories | ||
| playbooks | ||
| roles | ||
| scripts | ||
| templates | ||
| .ansible-lint | ||
| .envrc | ||
| .gitignore | ||
| .sops.yaml | ||
| .vault-pass.example | ||
| .yamllint | ||
| ansible.cfg | ||
| CLAUDE.md | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| README.md | ||
| requirements.yml | ||
ansible-scripts
Zentrales Repository für Ansible Playbooks, Inventories und Scripts. Die Entwicklungsumgebung wird vollständig über eine Nix Flake Dev-Shell bereitgestellt – kein manuelles Installieren von Ansible, Linters oder Secret-Tools nötig.
Schnellstart
# Dev-Shell betreten (installiert/aktiviert alle Tools)
nix develop
# oder automatisch via direnv: direnv allow
# Galaxy-Abhängigkeiten holen
just deps
# Linten und Syntax prüfen
just lint
just check staging
# Dry-run bzw. Ausführung
just diff staging
just run staging
Ohne just gehen alle Befehle auch direkt, z. B.:
ansible-playbook -i inventories/production/hosts.yml playbooks/site.yml
Verzeichnisstruktur
.
├── flake.nix / flake.lock # Nix Dev-Shell (Ansible, ansible-lint, sops, age, …)
├── .envrc # optionales direnv-Hook auf die Dev-Shell
├── ansible.cfg # Ansible-Konfiguration (inventory, roles_path, ssh)
├── requirements.yml # externe Collections/Rollen (Ansible Galaxy)
├── justfile # Kurzbefehle (just deps | lint | run | …)
│
├── inventories/ # eine Umgebung = ein Unterordner
│ ├── production/
│ │ ├── hosts.yml # Host-/Gruppendefinition
│ │ ├── group_vars/
│ │ │ └── all/
│ │ │ ├── vars.yml # NICHT-geheime Variablen (committet)
│ │ │ ├── vault.yml # geheime Variablen, ansible-vault-verschlüsselt (committet)
│ │ │ └── vault.yml.example # Vorlage (committet)
│ │ └── host_vars/ # host-spezifische Variablen
│ └── staging/ # gleiche Struktur
│
├── playbooks/ # Playbooks; Einstieg: site.yml
├── roles/ # selbst entwickelte Rollen (committet)
│ └── .galaxy/ # von Galaxy installierte Rollen/Collections (gitignored)
├── scripts/ # Hilfs-Scripts (check-secrets.sh, install-hooks.sh, …)
│ └── netbox/ # NetBox-Auswertungen; .env mit API-Token (gitignored)
├── files/ # statische Dateien für copy-Tasks
└── templates/ # Jinja2-Templates
Weitere Umgebungen werden als zusätzliche Ordner unter inventories/ angelegt
(z. B. inventories/lab/).
Secrets – so werden sie gehandhabt, ohne sie zu committen
Grundregel: Klartext-Geheimnisse landen nie im Git. Committet wird nur, was verschlüsselt oder eine Vorlage ist. Der pre-commit-Hook erzwingt das.
Standard: ansible-vault
-
Vault-Passwort anlegen (Datei ist in
.gitignore):cp .vault-pass.example .vault-pass $EDITOR .vault-pass # echtes Passwort eintragen chmod 600 .vault-passDie Dev-Shell exportiert automatisch
ANSIBLE_VAULT_PASSWORD_FILE=.vault-pass, sobald die Datei existiert. Das Passwort selbst wird über einen sicheren Kanal geteilt (Passwort-Manager, nicht per Chat/Mail). -
Secret-Datei erzeugen und verschlüsseln:
cd inventories/production/group_vars/all cp vault.yml.example vault.yml $EDITOR vault.yml ansible-vault encrypt vault.ymlDie verschlüsselte
vault.ymlbeginnt mit$ANSIBLE_VAULT;...und wird committet – der Inhalt ist ohne.vault-passunlesbar. -
Konvention: geheime Variablen mit Präfix
vault_benennen und invars.ymlreferenzieren:# vars.yml (committet, lesbar) db_password: "{{ vault_db_password }}"So ist dokumentiert, welche Secrets existieren, ohne die Werte zu zeigen.
-
Bearbeiten / Ansehen später:
ansible-vault edit inventories/production/group_vars/all/vault.yml ansible-vault view inventories/production/group_vars/all/vault.yml just vault-edit inventories/production/group_vars/all/vault.yml
Einzelne Werte statt ganzer Dateien gehen auch:
ansible-vault encrypt_string 's3cr3t' --name 'vault_api_token'
Alternative: SOPS + age
Für granulare Verschlüsselung (Werte statt ganzer Datei) und Git-freundliche
Diffs liegt .sops.yaml bei. Kurz:
mkdir -p .sops && age-keygen -o .sops/age.key # .sops/ ist gitignored
age-keygen -y .sops/age.key # public key -> in .sops.yaml eintragen
sops -e -i inventories/production/group_vars/all/vault.sops.yml
Die Dev-Shell setzt SOPS_AGE_KEY_FILE=.sops/age.key, sobald vorhanden.
Zur Nutzung in Ansible die Collection community.sops in requirements.yml
aufnehmen.
Schutz gegen versehentliches Committen
just install-hooks # pre-commit-Hook: scripts/check-secrets.sh
just secrets-check # ganzes Repo prüfen
Der Hook blockiert jeden Commit, bei dem eine Datei mit vault/secret im
Namen unverschlüsselt ist. Zusätzlich fängt .gitignore Dateien wie
.vault-pass, *.pem, .sops/, secrets.yml ab.
Was tun, wenn doch mal ein Secret committet wurde
- Das betroffene Geheimnis rotieren (neu setzen) – es gilt als kompromittiert.
- History bereinigen (
git filter-repo/ BFG) und Force-Push abstimmen.
Voraussetzungen
- Nix mit aktivierten Flakes
(
experimental-features = nix-command flakes) - SSH-Zugang zu den Zielhosts (Key-basiert, siehe
ansible.cfg) - optional:
direnvfür automatisches Laden der Dev-Shell
Enthaltene Tools (Dev-Shell)
ansible, ansible-lint, yamllint, sops, age, ssh-to-age, gnupg,
openssh, sshpass, python3 (+ passlib, netaddr), jq, yq-go, git,
just.