Ansible: Unterschied zwischen den Versionen
Rolf (Diskussion | Beiträge) |
Rolf (Diskussion | Beiträge) Add Categorie |
||
| (2 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
= | === 1. Zielsetzung === | ||
* Zentrale Verwaltung einer einzelnen Datei (~/.bash_aliases) auf ~10 Debian/Ubuntu-VMs | * Zentrale Verwaltung einer einzelnen Datei (~/.bash_aliases) auf ~10 Debian/Ubuntu-VMs | ||
* Sicherer SSH-Zugriff mit SSH-Keys | * Sicherer SSH-Zugriff mit SSH-Keys | ||
* Idempotente Verteilung per Ansible (owner, group, mode, Backup) | * Idempotente Verteilung per Ansible (owner, group, mode, Backup) | ||
| Zeile 8: | Zeile 10: | ||
---- | ---- | ||
=== 2. Kurzüberblick / Ablauf === | |||
# Namenauflösung (Admin-Rechner → /etc/hosts) prüfen | # Namenauflösung (Admin-Rechner → /etc/hosts) prüfen | ||
# SSH-Key auf Controller erzeugen und auf alle VMs verteilen | # SSH-Key auf Controller erzeugen und auf alle VMs verteilen | ||
| Zeile 19: | Zeile 21: | ||
---- | ---- | ||
=== 3. Voraussetzungen === | |||
* Admin-Rechner (Controller) mit Debian/Ubuntu | * Admin-Rechner (Controller) mit Debian/Ubuntu | ||
* Ziel-VMs: Debian oder Ubuntu | * Ziel-VMs: Debian oder Ubuntu | ||
| Zeile 28: | Zeile 30: | ||
---- | ---- | ||
=== 4. Wichtige Prinzipien und Regeln === | |||
* '''Eine Wahrheit für Hostnamen/IPs''' — verwalte IPs zentral (z. B. /etc/hosts) statt mehrere Orte. | * '''Eine Wahrheit für Hostnamen/IPs''' — verwalte IPs zentral (z. B. /etc/hosts) statt mehrere Orte. | ||
* '''SSH-Keys zuerst''' — nie per Passwort-Only operieren, wenn du Automatisierung planst. | * '''SSH-Keys zuerst''' — nie per Passwort-Only operieren, wenn du Automatisierung planst. | ||
| Zeile 38: | Zeile 40: | ||
---- | ---- | ||
=== 5. Namensauflösung (wichtig) === | |||
Auf dem Controller (Admin-Rechner) /etc/hosts pflegen: | Auf dem Controller (Admin-Rechner) /etc/hosts pflegen: | ||
# Beispiel 192.168.10.11 vm1 192.168.10.12 vm2 192.168.10.13 vm3 ... | |||
Test nach Eintrag: | Test nach Eintrag: | ||
ssh rolf@vm1 | |||
Wenn "Could not resolve hostname" → /etc/hosts nicht korrekt. | Wenn "Could not resolve hostname" → /etc/hosts nicht korrekt. | ||
---- | ---- | ||
=== 6. SSH-Key: Erzeugen & Verteilen === | |||
==== | ==== 6.1 SSH-Key erzeugen (Controller) ==== | ||
ssh-keygen -t ed25519 -a 100 # Pfad: /home/rolf/.ssh/id_ed25519 + id_ed25519.pub | |||
6.2 Public Key auf Ziel-VMs verteilen | |||
ssh-copy-id rolf@vm1 ssh-copy-id rolf@vm2 ... | |||
= | ==== 6.3 Wichtige Fehler & Lösungen ==== | ||
<nowiki>{| class="wikitable"</nowiki> | <nowiki>{| class="wikitable"</nowiki> | ||
| Zeile 93: | Zeile 92: | ||
---- | ---- | ||
=== 7. Ansible auf Controller installieren === | |||
sudo apt update sudo apt install -y ansible ansible --version | |||
---- | ---- | ||
=== 8. Projektstruktur (empfohlen) === | |||
Empfohlenes Verzeichnis auf Controller: ~/ansible | Empfohlenes Verzeichnis auf Controller: ~/ansible | ||
ansible/ ├── inventory.ini ├── playbook.yml # für .bash_aliases ├── playbook-apt-upgrade.yml # optional: apt-upgrade └── files/ ├── bash_aliases └── sudoers_rolf | |||
Wichtig: | Wichtig: | ||
| Zeile 107: | Zeile 106: | ||
---- | ---- | ||
=== 9. Inventory === | |||
Beispiel inventory.ini (Hostnamen; /etc/hosts sorgt für Auflösung): | Beispiel inventory.ini (Hostnamen; /etc/hosts sorgt für Auflösung): | ||
[linux] vm1 vm2 vm3 vm4 vm5 vm6 vm8 [linux:vars] ansible_user=rolf | |||
Tipp: Wenn du IPs direkt nutzt, setze ansible_host explizit, aber vermeide mehrere Wahrheiten. | Tipp: Wenn du IPs direkt nutzt, setze ansible_host explizit, aber vermeide mehrere Wahrheiten. | ||
---- | ---- | ||
=== 10. Playbook: .bash_aliases verteilen === | |||
Datei: playbook.yml | Datei: playbook.yml | ||
- name: Bash Aliases verteilen hosts: linux become: true tasks: - name: Home-Verzeichnis ermitteln set_fact: user_home: "<nowiki>{{ ansible_env.HOME }}</nowiki>" - name: .bash_aliases kopieren copy: src: "<nowiki>{{ playbook_dir }}</nowiki>/files/bash_aliases" dest: "<nowiki>{{ user_home }}</nowiki>/.bash_aliases" owner: "<nowiki>{{ ansible_user }}</nowiki>" group: "<nowiki>{{ ansible_user_gid }}</nowiki>" mode: '0644' backup: yes | |||
Erläuterung: | Erläuterung: | ||
| Zeile 124: | Zeile 123: | ||
---- | ---- | ||
=== 11. Playbook: APT-Updates (sichere Variante) === | |||
Datei: playbook-apt-upgrade.yml | Datei: playbook-apt-upgrade.yml | ||
Hinweis: Wenn Zielhosts unterschiedliche sudo-Passwörter haben, ist ein einmaliger Bootstrap notwendig (siehe Abschnitt 12). Das Playbook unten ist die Endversion, die nach Bootstrap ohne Password läuft. | Hinweis: Wenn Zielhosts unterschiedliche sudo-Passwörter haben, ist ein einmaliger Bootstrap notwendig (siehe Abschnitt 12). Das Playbook unten ist die Endversion, die nach Bootstrap ohne Password läuft. | ||
- name: Sudo ohne Passwort + APT Full Upgrade hosts: linux gather_facts: no serial: 50 tasks: - name: Passwortloses sudo für rolf setzen become: true copy: src: "<nowiki>{{ playbook_dir }}</nowiki>/files/sudoers_rolf" dest: /etc/sudoers.d/rolf owner: root group: root mode: '0440' validate: 'visudo -cf %s' - name: Facts sammeln (jetzt, nach sudoers drop) ansible.builtin.setup: - name: APT Cache aktualisieren become: true apt: update_cache: yes cache_valid_time: 3600 - name: Full Upgrade durchführen become: true apt: upgrade: full autoremove: no - name: Nicht mehr benötigte Pakete entfernen become: true apt: autoremove: yes | |||
Wichtig: | Wichtig: | ||
| Zeile 136: | Zeile 135: | ||
---- | ---- | ||
=== 12. Bootstrap: wenn jeder Client ein anderes sudo-Passwort hat === | |||
Ansible kann '''nicht''' unterschiedliche sudo-Passwörter parallel verarbeiten. Wenn jedes Ziel ein eigenes Passwort hat, musst du den NOPASSWD-Eintrag pro Host einmalig manuell anlegen (Bootstrap). Das ist sicher, kurz und transparent. | Ansible kann '''nicht''' unterschiedliche sudo-Passwörter parallel verarbeiten. Wenn jedes Ziel ein eigenes Passwort hat, musst du den NOPASSWD-Eintrag pro Host einmalig manuell anlegen (Bootstrap). Das ist sicher, kurz und transparent. | ||
==== 12.1 Manuelles, sicheres Bootstrap (pro Host) ==== | |||
Auf dem Controller: | Auf dem Controller: | ||
ssh rolf@vmX | |||
Dann auf der VM (interaktiv, Passwort von rolf eingeben): | Dann auf der VM (interaktiv, Passwort von rolf eingeben): | ||
sudo -i echo 'rolf ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/rolf chmod 0440 /etc/sudoers.d/rolf visudo -cf /etc/sudoers.d/rolf exit exit | |||
Kontrolle (auf Controller oder VM als rolf): | Kontrolle (auf Controller oder VM als rolf): | ||
<nowiki><pre> ssh rolf@vmX sudo -n true && echo "sudo ohne Passwort OK" | <nowiki><pre> ssh rolf@vmX sudo -n true && echo "sudo ohne Passwort OK"</nowiki> | ||
==== 12.2 Hinweis zu Ownership ==== | |||
Die Datei /etc/sudoers.d/rolf muss root:root gehören und 0440-Rechte haben — genau das macht der Befehl oben (als root ausgeführt). Das ist korrekt. | Die Datei /etc/sudoers.d/rolf muss root:root gehören und 0440-Rechte haben — genau das macht der Befehl oben (als root ausgeführt). Das ist korrekt. | ||
==== 12.3 Alternative (riskanter): Root-SSH temporär verwenden ==== | |||
Nicht empfohlen, nur aufgeführt: root-SSH aktivieren, Root-Key verteilen, sudoers setzten, Root-SSH wieder deaktivieren. Mehr Aufwand & Risiko. | Nicht empfohlen, nur aufgeführt: root-SSH aktivieren, Root-Key verteilen, sudoers setzten, Root-SSH wieder deaktivieren. Mehr Aufwand & Risiko. | ||
---- | ---- | ||
=== 13. Laufendes Beispiel: Ausführen der Playbooks === | |||
# Test der Verbindung (nach SSH-Key-Setup) | # Test der Verbindung (nach SSH-Key-Setup) | ||
ansible linux -m ping -i inventory.ini | |||
# Alias-Playbook ausführen | # Alias-Playbook ausführen | ||
cd ~/ansible ansible-playbook -i inventory.ini playbook.yml | |||
# Bootstrap (falls nötig) — siehe Abschnitt 12 | # Bootstrap (falls nötig) — siehe Abschnitt 12 | ||
# APT-Upgrade-Playbook (nach Bootstrap) | # APT-Upgrade-Playbook (nach Bootstrap) | ||
ansible-playbook -i inventory.ini playbook-apt-upgrade.yml | |||
Wenn beim ersten Lauf sudo-Passwort abgefragt wird (wenn gather_facts:NO nicht gesetzt war), nutze: | Wenn beim ersten Lauf sudo-Passwort abgefragt wird (wenn gather_facts:NO nicht gesetzt war), nutze: | ||
ansible-playbook -i inventory.ini playbook-apt-upgrade.yml --ask-become-pass | |||
Aber: das funktioniert nur, wenn alle Hosts dasselbe sudo-Passwort haben. | Aber: das funktioniert nur, wenn alle Hosts dasselbe sudo-Passwort haben. | ||
---- | ---- | ||
=== 14. Troubleshooting: typische Fehlermeldungen & Abhilfe === | |||
==== 14.1 UNREACHABLE / Connection timed out ==== | |||
fatal: [vmX]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ... Connection timed out"} | |||
==== | ==== Ursachen & Checks: ==== | ||
* /etc/hosts stimmt? (Controller) | * /etc/hosts stimmt? (Controller) | ||
* nc -vz vmX 22 → erreicht Port 22? | * nc -vz vmX 22 → erreicht Port 22? | ||
| Zeile 181: | Zeile 178: | ||
* IP oder Bridge falsch? qm config <VMID> auf Proxmox prüfen | * IP oder Bridge falsch? qm config <VMID> auf Proxmox prüfen | ||
= | ==== 14.2 Host key verification failed ==== | ||
"msg": "Failed to connect to the host via ssh: Host key verification failed." | |||
===== Lösung: ===== | |||
* ssh-keygen -R vmX | * ssh-keygen -R vmX | ||
* ssh-keygen -R 192.168.x.y | * ssh-keygen -R 192.168.x.y | ||
* Falls gehasht oder mehrfach: backup + leeren known_hosts, dann neu anlernen (siehe 6.3) | * Falls gehasht oder mehrfach: backup + leeren known_hosts, dann neu anlernen (siehe 6.3) | ||
= | ==== 14.3 Missing sudo password (bei Gathering Facts) ==== | ||
Problem: | Problem: | ||
| Zeile 194: | Zeile 193: | ||
* Alternativ initial manuell sudoers installieren (Bootstrap) | * Alternativ initial manuell sudoers installieren (Bootstrap) | ||
= | ==== 14.4 Could not find or access 'files/bash_aliases' ==== | ||
Problem: | Problem: | ||
| Zeile 201: | Zeile 200: | ||
* Oder adjust src im copy-Task: src: "<nowiki>{{ playbook_dir }}</nowiki>/files/.bash_aliases" (nicht empfohlen) | * Oder adjust src im copy-Task: src: "<nowiki>{{ playbook_dir }}</nowiki>/files/.bash_aliases" (nicht empfohlen) | ||
= | ==== 14.5 failed to look up group rolf ==== | ||
Problem: | Problem: | ||
| Zeile 207: | Zeile 206: | ||
* Playbook nicht hart auf group: rolf setzen; stattdessen group: "<nowiki>{{ ansible_user_gid }}</nowiki>" | * Playbook nicht hart auf group: rolf setzen; stattdessen group: "<nowiki>{{ ansible_user_gid }}</nowiki>" | ||
= | ==== 14.6 chown / Operation not permitted (chown failed) ==== | ||
Problem: | Problem: | ||
| Zeile 213: | Zeile 212: | ||
* use become: true für den copy-Task oder global auf Play-Ebene | * use become: true für den copy-Task oder global auf Play-Ebene | ||
= | ==== 14.7 visudo validation failed beim Setzen von sudoers (validate) ==== | ||
Problem: | Problem: | ||
| Zeile 221: | Zeile 220: | ||
---- | ---- | ||
=== 15. Patchmon / andere Automatisierung berücksichtigen === | |||
* known_hosts reset kann andere Tools (Patchmon) temporär stören, wenn sie nicht interaktiv mit Fingerprint-Abfrage umgehen. | * known_hosts reset kann andere Tools (Patchmon) temporär stören, wenn sie nicht interaktiv mit Fingerprint-Abfrage umgehen. | ||
* Empfohlen: wenn du Patchmon in Betrieb hast und es per SSH auf Hosts zugreift, vor großen known_hosts-Aktionen Patchmon zeitweise stoppen oder sicherstellen, dass Patchmon seine eigene known_hosts hat / nicht interaktiv ist. | * Empfohlen: wenn du Patchmon in Betrieb hast und es per SSH auf Hosts zugreift, vor großen known_hosts-Aktionen Patchmon zeitweise stoppen oder sicherstellen, dass Patchmon seine eigene known_hosts hat / nicht interaktiv ist. | ||
Stop/Start (nur, wenn Patchmon lokal als Service läuft): | Stop/Start (nur, wenn Patchmon lokal als Service läuft): | ||
sudo systemctl stop patchmon # ... known_hosts reset + anlernen ... sudo systemctl start patchmon | |||
---- | ---- | ||
=== 16. Best Practices / Langfristige Empfehlungen === | |||
* Versioniere ansible/ (git init; commit playbooks + files + inventory). | * Versioniere ansible/ (git init; commit playbooks + files + inventory). | ||
* Erstelle Ansible-Roles, wenn mehr Dateien oder Konfigurationen hinzukommen. | * Erstelle Ansible-Roles, wenn mehr Dateien oder Konfigurationen hinzukommen. | ||
* Bei produktiver Nutzung: beschränke sudoers auf notwendige Befehle statt NOPASSWD: ALL. | * Bei produktiver Nutzung: beschränke sudoers auf notwendige Befehle statt NOPASSWD: ALL. | ||
* Bei VM-Cloning: nach dem ersten Boot SSH Host Keys neu generieren: | * Bei VM-Cloning: nach dem ersten Boot SSH Host Keys neu generieren: | ||
sudo rm /etc/ssh/ssh_host_* sudo dpkg-reconfigure openssh-server | |||
* Optional: vor risky full-upgrade Snapshots (Proxmox) automatisch erstellen. | * Optional: vor risky full-upgrade Snapshots (Proxmox) automatisch erstellen. | ||
---- | ---- | ||
=== 17. Kurze Checkliste (Schnellreferenz) === | |||
1) /etc/hosts auf Controller prüfen | 1) /etc/hosts auf Controller prüfen | ||
2) ssh-keygen & ssh-copy-id auf alle VMs | |||
3) ansible --version prüfen | 2) ssh-keygen & ssh-copy-id auf alle VMs | ||
4) inventory.ini korrekt (Hostnamen) | |||
5) cd ~/ansible | 3) ansible --version prüfen | ||
6) ansible linux -m ping -i inventory.ini | |||
7) ansible-playbook -i inventory.ini playbook.yml | 4) inventory.ini korrekt (Hostnamen) | ||
5) cd ~/ansible | |||
6) ansible linux -m ping -i inventory.ini | |||
7) ansible-playbook -i inventory.ini playbook.yml | |||
8) Falls sudo passwort-geschützt auf VMs: bootstrap (siehe 12) | 8) Falls sudo passwort-geschützt auf VMs: bootstrap (siehe 12) | ||
9) ansible-playbook -i inventory.ini playbook-apt-upgrade.yml | |||
9) ansible-playbook -i inventory.ini playbook-apt-upgrade.yml | |||
---- | ---- | ||
[[Kategorie:Homelab]] | |||
Aktuelle Version vom 18. Februar 2026, 18:07 Uhr
1. Zielsetzung[Bearbeiten | Quelltext bearbeiten]
- Zentrale Verwaltung einer einzelnen Datei (~/.bash_aliases) auf ~10 Debian/Ubuntu-VMs
- Sicherer SSH-Zugriff mit SSH-Keys
- Idempotente Verteilung per Ansible (owner, group, mode, Backup)
- Optionales, sicheres Ausführen von APT-Updates per Ansible
- Dokumentation aller Fallstricke + Gegenmaßnahmen
2. Kurzüberblick / Ablauf[Bearbeiten | Quelltext bearbeiten]
- Namenauflösung (Admin-Rechner → /etc/hosts) prüfen
- SSH-Key auf Controller erzeugen und auf alle VMs verteilen
- Ansible auf Controller installieren
- Projektstruktur anlegen (inventory, playbook, files)
- Playbook zum Verteilen von .bash_aliases ausführen
- Falls sudo-Passwords unterschiedlich: einmaliger Bootstrap (manuell) zum Anlegen /etc/sudoers.d/rolf
- Optional: Playbook zum APT-Upgrade ausführen (mit Bootstrap-Mechanik)
3. Voraussetzungen[Bearbeiten | Quelltext bearbeiten]
- Admin-Rechner (Controller) mit Debian/Ubuntu
- Ziel-VMs: Debian oder Ubuntu
- Netzwerkverbindung zwischen Controller und VMs
- Benutzername auf Zielen (Beispiel: rolf) vorhanden und in sudoers oder mit sudo-Rechten
- Proxmox-Konsole zugänglich für den Fall, dass SSH nicht geht
4. Wichtige Prinzipien und Regeln[Bearbeiten | Quelltext bearbeiten]
- Eine Wahrheit für Hostnamen/IPs — verwalte IPs zentral (z. B. /etc/hosts) statt mehrere Orte.
- SSH-Keys zuerst — nie per Passwort-Only operieren, wenn du Automatisierung planst.
- Sudo ohne Passwort nur bewusst — NOPASSWD ist mächtig; im Homelab üblich, in Prod einschränken.
- visudo -cf vor dem Installieren von sudoers-Dateien verwenden (Ansible bietet validate).
- Ansible
becomeeinsetzen, wenn Systemdateien oder owner/group geändert werden. - Keine
StrictHostKeyChecking=nooder dauerhafte Deaktivierung der HostKey-Prüfung.
5. Namensauflösung (wichtig)[Bearbeiten | Quelltext bearbeiten]
Auf dem Controller (Admin-Rechner) /etc/hosts pflegen:
# Beispiel 192.168.10.11 vm1 192.168.10.12 vm2 192.168.10.13 vm3 ...
Test nach Eintrag:
ssh rolf@vm1
Wenn "Could not resolve hostname" → /etc/hosts nicht korrekt.
6. SSH-Key: Erzeugen & Verteilen[Bearbeiten | Quelltext bearbeiten]
6.1 SSH-Key erzeugen (Controller)[Bearbeiten | Quelltext bearbeiten]
ssh-keygen -t ed25519 -a 100 # Pfad: /home/rolf/.ssh/id_ed25519 + id_ed25519.pub
6.2 Public Key auf Ziel-VMs verteilen
ssh-copy-id rolf@vm1 ssh-copy-id rolf@vm2 ...
6.3 Wichtige Fehler & Lösungen[Bearbeiten | Quelltext bearbeiten]
{| class="wikitable"
! Fehlermeldung
! Ursache
| ! Sofortmaßnahme |
|---|
| No identities found |
| kein SSH-Key (oder nicht im Standardpfad) |
| ssh-keygen ausführen |
| - |
| Connection timed out |
| falsche IP oder Hostname |
| /etc/hosts & Netzwerk prüfen; nc -vz host 22 |
| - |
| Host key verification failed |
| known_hosts enthält alten Fingerprint (Host wurde neu installiert / geklont / IP geändert) |
| ssh-keygen -R vmX ; ggf. ssh-keygen -R 192.168.x.y ; wenn Hashes stören: backup + leeren known_hosts / then re-add hosts |
| } |
Hinweis: known_hosts kann gehasht sein. Wenn einzelne Löschungen fehlschlagen, backup anlegen und Datei neu erstellen:
cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak > ~/.ssh/known_hosts ssh rolf@vm1 # accept ssh rolf@vm2 # accept
7. Ansible auf Controller installieren[Bearbeiten | Quelltext bearbeiten]
sudo apt update sudo apt install -y ansible ansible --version
8. Projektstruktur (empfohlen)[Bearbeiten | Quelltext bearbeiten]
Empfohlenes Verzeichnis auf Controller: ~/ansible
ansible/ ├── inventory.ini ├── playbook.yml # für .bash_aliases ├── playbook-apt-upgrade.yml # optional: apt-upgrade └── files/ ├── bash_aliases └── sudoers_rolf
Wichtig:
- Dateiname auf Controller für die Alias-Vorlage: files/bash_aliases (ohne führenden Punkt)
- sudoers_rolf enthält genau: rolf ALL=(ALL) NOPASSWD: ALL
9. Inventory[Bearbeiten | Quelltext bearbeiten]
Beispiel inventory.ini (Hostnamen; /etc/hosts sorgt für Auflösung):
[linux] vm1 vm2 vm3 vm4 vm5 vm6 vm8 [linux:vars] ansible_user=rolf
Tipp: Wenn du IPs direkt nutzt, setze ansible_host explizit, aber vermeide mehrere Wahrheiten.
10. Playbook: .bash_aliases verteilen[Bearbeiten | Quelltext bearbeiten]
Datei: playbook.yml
- name: Bash Aliases verteilen hosts: linux become: true tasks: - name: Home-Verzeichnis ermitteln set_fact: user_home: "{{ ansible_env.HOME }}" - name: .bash_aliases kopieren copy: src: "{{ playbook_dir }}/files/bash_aliases" dest: "{{ user_home }}/.bash_aliases" owner: "{{ ansible_user }}" group: "{{ ansible_user_gid }}" mode: '0644' backup: yes
Erläuterung:
- become: true → erlaubt chown/chgrp auch wenn Datei vorher root-owned war
- ansible_user_gid → verhindert "failed to look up group" falls Gruppe nicht wie Benutzer heißt
- backup: yes → speichert vorhandene Datei als Sicherung
11. Playbook: APT-Updates (sichere Variante)[Bearbeiten | Quelltext bearbeiten]
Datei: playbook-apt-upgrade.yml
Hinweis: Wenn Zielhosts unterschiedliche sudo-Passwörter haben, ist ein einmaliger Bootstrap notwendig (siehe Abschnitt 12). Das Playbook unten ist die Endversion, die nach Bootstrap ohne Password läuft.
- name: Sudo ohne Passwort + APT Full Upgrade hosts: linux gather_facts: no serial: 50 tasks: - name: Passwortloses sudo für rolf setzen become: true copy: src: "{{ playbook_dir }}/files/sudoers_rolf" dest: /etc/sudoers.d/rolf owner: root group: root mode: '0440' validate: 'visudo -cf %s' - name: Facts sammeln (jetzt, nach sudoers drop) ansible.builtin.setup: - name: APT Cache aktualisieren become: true apt: update_cache: yes cache_valid_time: 3600 - name: Full Upgrade durchführen become: true apt: upgrade: full autoremove: no - name: Nicht mehr benötigte Pakete entfernen become: true apt: autoremove: yes
Wichtig:
- gather_facts: no verhindert, dass Ansible vorab beim Facts-Gathering schon sudo benötigt (Problem: Missing sudo password).
- Der erste Task setzt die sudoers-Datei; dafür ist beim ersten Lauf (falls sudo noch passwortgeschützt ist) ein Passwort erforderlich (siehe Abschnitt 12).
12. Bootstrap: wenn jeder Client ein anderes sudo-Passwort hat[Bearbeiten | Quelltext bearbeiten]
Ansible kann nicht unterschiedliche sudo-Passwörter parallel verarbeiten. Wenn jedes Ziel ein eigenes Passwort hat, musst du den NOPASSWD-Eintrag pro Host einmalig manuell anlegen (Bootstrap). Das ist sicher, kurz und transparent.
12.1 Manuelles, sicheres Bootstrap (pro Host)[Bearbeiten | Quelltext bearbeiten]
Auf dem Controller:
ssh rolf@vmX
Dann auf der VM (interaktiv, Passwort von rolf eingeben):
sudo -i echo 'rolf ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/rolf chmod 0440 /etc/sudoers.d/rolf visudo -cf /etc/sudoers.d/rolf exit exit
Kontrolle (auf Controller oder VM als rolf): <pre> ssh rolf@vmX sudo -n true && echo "sudo ohne Passwort OK"
12.2 Hinweis zu Ownership[Bearbeiten | Quelltext bearbeiten]
Die Datei /etc/sudoers.d/rolf muss root:root gehören und 0440-Rechte haben — genau das macht der Befehl oben (als root ausgeführt). Das ist korrekt.
12.3 Alternative (riskanter): Root-SSH temporär verwenden[Bearbeiten | Quelltext bearbeiten]
Nicht empfohlen, nur aufgeführt: root-SSH aktivieren, Root-Key verteilen, sudoers setzten, Root-SSH wieder deaktivieren. Mehr Aufwand & Risiko.
13. Laufendes Beispiel: Ausführen der Playbooks[Bearbeiten | Quelltext bearbeiten]
- Test der Verbindung (nach SSH-Key-Setup)
ansible linux -m ping -i inventory.ini
- Alias-Playbook ausführen
cd ~/ansible ansible-playbook -i inventory.ini playbook.yml
- Bootstrap (falls nötig) — siehe Abschnitt 12
- APT-Upgrade-Playbook (nach Bootstrap)
ansible-playbook -i inventory.ini playbook-apt-upgrade.yml
Wenn beim ersten Lauf sudo-Passwort abgefragt wird (wenn gather_facts:NO nicht gesetzt war), nutze:
ansible-playbook -i inventory.ini playbook-apt-upgrade.yml --ask-become-pass
Aber: das funktioniert nur, wenn alle Hosts dasselbe sudo-Passwort haben.
14. Troubleshooting: typische Fehlermeldungen & Abhilfe[Bearbeiten | Quelltext bearbeiten]
14.1 UNREACHABLE / Connection timed out[Bearbeiten | Quelltext bearbeiten]
fatal: [vmX]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ... Connection timed out"}
Ursachen & Checks:[Bearbeiten | Quelltext bearbeiten]
- /etc/hosts stimmt? (Controller)
- nc -vz vmX 22 → erreicht Port 22?
- VM läuft? (Proxmox Console prüfen)
- SSH-Dienst aktiv? sudo systemctl status ssh
- IP oder Bridge falsch? qm config <VMID> auf Proxmox prüfen
14.2 Host key verification failed[Bearbeiten | Quelltext bearbeiten]
"msg": "Failed to connect to the host via ssh: Host key verification failed."
Lösung:[Bearbeiten | Quelltext bearbeiten]
- ssh-keygen -R vmX
- ssh-keygen -R 192.168.x.y
- Falls gehasht oder mehrfach: backup + leeren known_hosts, dann neu anlernen (siehe 6.3)
14.3 Missing sudo password (bei Gathering Facts)[Bearbeiten | Quelltext bearbeiten]
Problem:
- Ansible benötigt become schon beim Facts-Gathering, aber sudo ist noch passwortgeschützt. Lösung:
- Playbook: gather_facts: no und erster Task setzt sudoers via become (siehe 11 & 12)
- Alternativ initial manuell sudoers installieren (Bootstrap)
14.4 Could not find or access 'files/bash_aliases'[Bearbeiten | Quelltext bearbeiten]
Problem:
- falscher Dateiname/Ort auf Controller Lösung:
- Datei muss unter ~/ansible/files/bash_aliases liegen (ohne führenden Punkt)
- Oder adjust src im copy-Task: src: "{{ playbook_dir }}/files/.bash_aliases" (nicht empfohlen)
14.5 failed to look up group rolf[Bearbeiten | Quelltext bearbeiten]
Problem:
- Benutzer-Primärgruppe heißt anders (z. B. users) Lösung:
- Playbook nicht hart auf group: rolf setzen; stattdessen group: "{{ ansible_user_gid }}"
14.6 chown / Operation not permitted (chown failed)[Bearbeiten | Quelltext bearbeiten]
Problem:
- Datei gehört root, Ansible läuft ohne become Lösung:
- use become: true für den copy-Task oder global auf Play-Ebene
14.7 visudo validation failed beim Setzen von sudoers (validate)[Bearbeiten | Quelltext bearbeiten]
Problem:
- Datei beinhaltet unsaubere Zeichen / Leerzeilen / CRLF / encoding Lösung:
- Prüfe Datei encoding, keine leere Zeile am Anfang/Ende; Ansible validate: 'visudo -cf %s' fängt das meist ab
15. Patchmon / andere Automatisierung berücksichtigen[Bearbeiten | Quelltext bearbeiten]
- known_hosts reset kann andere Tools (Patchmon) temporär stören, wenn sie nicht interaktiv mit Fingerprint-Abfrage umgehen.
- Empfohlen: wenn du Patchmon in Betrieb hast und es per SSH auf Hosts zugreift, vor großen known_hosts-Aktionen Patchmon zeitweise stoppen oder sicherstellen, dass Patchmon seine eigene known_hosts hat / nicht interaktiv ist.
Stop/Start (nur, wenn Patchmon lokal als Service läuft):
sudo systemctl stop patchmon # ... known_hosts reset + anlernen ... sudo systemctl start patchmon
16. Best Practices / Langfristige Empfehlungen[Bearbeiten | Quelltext bearbeiten]
- Versioniere ansible/ (git init; commit playbooks + files + inventory).
- Erstelle Ansible-Roles, wenn mehr Dateien oder Konfigurationen hinzukommen.
- Bei produktiver Nutzung: beschränke sudoers auf notwendige Befehle statt NOPASSWD: ALL.
- Bei VM-Cloning: nach dem ersten Boot SSH Host Keys neu generieren:
sudo rm /etc/ssh/ssh_host_* sudo dpkg-reconfigure openssh-server
- Optional: vor risky full-upgrade Snapshots (Proxmox) automatisch erstellen.
17. Kurze Checkliste (Schnellreferenz)[Bearbeiten | Quelltext bearbeiten]
1) /etc/hosts auf Controller prüfen
2) ssh-keygen & ssh-copy-id auf alle VMs
3) ansible --version prüfen
4) inventory.ini korrekt (Hostnamen)
5) cd ~/ansible
6) ansible linux -m ping -i inventory.ini
7) ansible-playbook -i inventory.ini playbook.yml
8) Falls sudo passwort-geschützt auf VMs: bootstrap (siehe 12)
9) ansible-playbook -i inventory.ini playbook-apt-upgrade.yml