Zum Inhalt springen

Ansible: Unterschied zwischen den Versionen

Aus RolfWiki
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
<nowiki>== 1. Zielsetzung ==</nowiki>
=== <nowiki>== 1. Zielsetzung ==</nowiki> ===
 
* 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
Zeile 7: Zeile 6:
* Dokumentation aller Fallstricke + Gegenmaßnahmen
* Dokumentation aller Fallstricke + Gegenmaßnahmen


----== 2. Kurzüberblick / Ablauf ==
----


=== == 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 17: Zeile 17:
# Optional: Playbook zum APT-Upgrade ausführen (mit Bootstrap-Mechanik)
# Optional: Playbook zum APT-Upgrade ausführen (mit Bootstrap-Mechanik)


----== 3. Voraussetzungen ==
----


=== == 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 25: Zeile 26:
* Proxmox-Konsole zugänglich für den Fall, dass SSH nicht geht
* Proxmox-Konsole zugänglich für den Fall, dass SSH nicht geht


----== 4. Wichtige Prinzipien und Regeln ==
----


=== == 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 34: Zeile 36:
* '''Keine <code>StrictHostKeyChecking=no</code>''' oder dauerhafte Deaktivierung der HostKey-Prüfung.
* '''Keine <code>StrictHostKeyChecking=no</code>''' oder dauerhafte Deaktivierung der HostKey-Prüfung.


----== 5. Namensauflösung (wichtig) ==
----


=== == 5. Namensauflösung (wichtig) == ===
Auf dem Controller (Admin-Rechner) /etc/hosts pflegen:
Auf dem Controller (Admin-Rechner) /etc/hosts pflegen:
<nowiki><pre> # Beispiel 192.168.10.11  vm1 192.168.10.12  vm2 192.168.10.13  vm3 ... </pre></nowiki>
<nowiki><pre> # Beispiel 192.168.10.11  vm1 192.168.10.12  vm2 192.168.10.13  vm3 ... </pre></nowiki>
Zeile 41: Zeile 44:
<nowiki><pre> ssh rolf@vm1 </pre></nowiki>
<nowiki><pre> ssh rolf@vm1 </pre></nowiki>
Wenn "Could not resolve hostname" → /etc/hosts nicht korrekt.
Wenn "Could not resolve hostname" → /etc/hosts nicht korrekt.
----== 6. SSH-Key: Erzeugen & Verteilen ==
----


<nowiki>=== 6.1 SSH-Key erzeugen (Controller) ===</nowiki>
=== == 6. SSH-Key: Erzeugen & Verteilen == ===
 
==== <nowiki>=== 6.1 SSH-Key erzeugen (Controller) ===</nowiki>
<nowiki><pre> ssh-keygen -t ed25519 -a 100 # Pfad: /home/rolf/.ssh/id_ed25519 + id_ed25519.pub </pre></nowiki>
<nowiki><pre> ssh-keygen -t ed25519 -a 100 # Pfad: /home/rolf/.ssh/id_ed25519 + id_ed25519.pub </pre></nowiki>
<nowiki>=== 6.2 Public Key auf Ziel-VMs verteilen ===</nowiki>
<nowiki>=== 6.2 Public Key auf Ziel-VMs verteilen ===</nowiki>
<nowiki><pre> ssh-copy-id rolf@vm1 ssh-copy-id rolf@vm2 ... </pre></nowiki>
<nowiki><pre> ssh-copy-id rolf@vm1 ssh-copy-id rolf@vm2 ... </pre></nowiki>
<nowiki>=== 6.3 Wichtige Fehler & Lösungen ===</nowiki>
<nowiki>=== 6.3 Wichtige Fehler & Lösungen ===</nowiki> ====
 
<nowiki>{| class="wikitable"</nowiki>
<nowiki>{| class="wikitable"</nowiki>


Zeile 83: Zeile 87:
Hinweis: known_hosts kann gehasht sein. Wenn einzelne Löschungen fehlschlagen, backup anlegen und Datei neu erstellen:
Hinweis: known_hosts kann gehasht sein. Wenn einzelne Löschungen fehlschlagen, backup anlegen und Datei neu erstellen:
<nowiki><pre> cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak > ~/.ssh/known_hosts ssh rolf@vm1  # accept ssh rolf@vm2  # accept </pre></nowiki>
<nowiki><pre> cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak > ~/.ssh/known_hosts ssh rolf@vm1  # accept ssh rolf@vm2  # accept </pre></nowiki>
----== 7. Ansible auf Controller installieren ==
----
 
=== == 7. Ansible auf Controller installieren == ===
<nowiki><pre> sudo apt update sudo apt install -y ansible ansible --version </pre></nowiki>
<nowiki><pre> sudo apt update sudo apt install -y ansible ansible --version </pre></nowiki>
----== 8. Projektstruktur (empfohlen) ==
----


=== == 8. Projektstruktur (empfohlen) == ===
Empfohlenes Verzeichnis auf Controller: ~/ansible
Empfohlenes Verzeichnis auf Controller: ~/ansible
<nowiki><pre> ansible/ ├── inventory.ini ├── playbook.yml              # für .bash_aliases ├── playbook-apt-upgrade.yml  # optional: apt-upgrade └── files/    ├── bash_aliases    └── sudoers_rolf </pre></nowiki>
<nowiki><pre> ansible/ ├── inventory.ini ├── playbook.yml              # für .bash_aliases ├── playbook-apt-upgrade.yml  # optional: apt-upgrade └── files/    ├── bash_aliases    └── sudoers_rolf </pre></nowiki>
Zeile 94: Zeile 101:
* sudoers_rolf enthält genau:  rolf ALL=(ALL) NOPASSWD: ALL
* sudoers_rolf enthält genau:  rolf ALL=(ALL) NOPASSWD: ALL


----== 9. Inventory ==
----


=== == 9. Inventory == ===
Beispiel inventory.ini (Hostnamen; /etc/hosts sorgt für Auflösung):
Beispiel inventory.ini (Hostnamen; /etc/hosts sorgt für Auflösung):
<nowiki><pre> [linux] vm1 vm2 vm3 vm4 vm5 vm6 vm8 [linux:vars] ansible_user=rolf </pre></nowiki>
<nowiki><pre> [linux] vm1 vm2 vm3 vm4 vm5 vm6 vm8 [linux:vars] ansible_user=rolf </pre></nowiki>
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 ==
----


=== == 10. Playbook: .bash_aliases verteilen == ===
Datei: playbook.yml
Datei: playbook.yml
<nowiki><pre> - 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 </pre></nowiki>
<nowiki><pre> - 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 </pre></nowiki>
Zeile 109: Zeile 118:
* backup: yes → speichert vorhandene Datei als Sicherung
* backup: yes → speichert vorhandene Datei als Sicherung


----== 11. Playbook: APT-Updates (sichere Variante) ==
----


=== == 11. Playbook: APT-Updates (sichere Variante) == ===
Datei: playbook-apt-upgrade.yml
Datei: playbook-apt-upgrade.yml


Zeile 120: Zeile 130:
* 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).
* 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 ==
----


=== == 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.


Zeile 139: Zeile 150:


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 ==
----


=== == 13. Laufendes Beispiel: Ausführen der Playbooks == ===
# Test der Verbindung (nach SSH-Key-Setup)
# Test der Verbindung (nach SSH-Key-Setup)
<nowiki><pre> ansible linux -m ping -i inventory.ini </pre></nowiki>
<nowiki><pre> ansible linux -m ping -i inventory.ini </pre></nowiki>
Zeile 153: Zeile 165:
<nowiki><pre> ansible-playbook -i inventory.ini playbook-apt-upgrade.yml --ask-become-pass </pre></nowiki>
<nowiki><pre> ansible-playbook -i inventory.ini playbook-apt-upgrade.yml --ask-become-pass </pre></nowiki>
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 ==
----


<nowiki>=== 14.1 UNREACHABLE / Connection timed out ===</nowiki>
=== == 14. Troubleshooting: typische Fehlermeldungen & Abhilfe == ===
<nowiki><pre> fatal: [vmX]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ... Connection timed out"} </pre></nowiki>
Ursachen & Checks:


==== <nowiki>=== 14.1 UNREACHABLE / Connection timed out ===</nowiki>
<nowiki><pre> fatal: [vmX]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ... Connection timed out"} </pre></nowiki> 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 165: Zeile 177:
* IP oder Bridge falsch? qm config <VMID> auf Proxmox prüfen
* IP oder Bridge falsch? qm config <VMID> auf Proxmox prüfen


<nowiki>=== 14.2 Host key verification failed ===</nowiki>
==== <nowiki>=== 14.2 Host key verification failed ===</nowiki>
<nowiki><pre> "msg": "Failed to connect to the host via ssh: Host key verification failed." </pre></nowiki>
<nowiki><pre> "msg": "Failed to connect to the host via ssh: Host key verification failed." </pre></nowiki> Lösung: ====
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)


<nowiki>=== 14.3 Missing sudo password (bei Gathering Facts) ===</nowiki>
==== <nowiki>=== 14.3 Missing sudo password (bei Gathering Facts) ===</nowiki> ====
 
Problem:
Problem:


Zeile 181: Zeile 190:
* Alternativ initial manuell sudoers installieren (Bootstrap)
* Alternativ initial manuell sudoers installieren (Bootstrap)


<nowiki>=== 14.4 Could not find or access 'files/bash_aliases' ===</nowiki>
==== <nowiki>=== 14.4 Could not find or access 'files/bash_aliases' ===</nowiki> ====
 
Problem:
Problem:


Zeile 189: Zeile 197:
* 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)


<nowiki>=== 14.5 failed to look up group rolf ===</nowiki>
==== <nowiki>=== 14.5 failed to look up group rolf ===</nowiki> ====
 
Problem:
Problem:


Zeile 196: Zeile 203:
* 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>"


<nowiki>=== 14.6 chown / Operation not permitted (chown failed) ===</nowiki>
==== <nowiki>=== 14.6 chown / Operation not permitted (chown failed) ===</nowiki> ====
 
Problem:
Problem:


Zeile 203: Zeile 209:
* 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


<nowiki>=== 14.7 visudo validation failed beim Setzen von sudoers (validate) ===</nowiki>
==== <nowiki>=== 14.7 visudo validation failed beim Setzen von sudoers (validate) ===</nowiki> ====
 
Problem:
Problem:


Zeile 210: Zeile 215:
* Prüfe Datei encoding, keine leere Zeile am Anfang/Ende; Ansible validate: 'visudo -cf %s' fängt das meist ab
* 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 ==
----


=== == 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.
Zeile 217: Zeile 223:
Stop/Start (nur, wenn Patchmon lokal als Service läuft):
Stop/Start (nur, wenn Patchmon lokal als Service läuft):
<nowiki><pre> sudo systemctl stop patchmon # ... known_hosts reset + anlernen ... sudo systemctl start patchmon </pre></nowiki>
<nowiki><pre> sudo systemctl stop patchmon # ... known_hosts reset + anlernen ... sudo systemctl start patchmon </pre></nowiki>
----== 16. Best Practices / Langfristige Empfehlungen ==
----


=== == 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.
Zeile 227: Zeile 234:
* Optional: vor risky full-upgrade Snapshots (Proxmox) automatisch erstellen.
* Optional: vor risky full-upgrade Snapshots (Proxmox) automatisch erstellen.


----== 17. Kurze Checkliste (Schnellreferenz) ==
----
 
=== == 17. Kurze Checkliste (Schnellreferenz) == ===
<nowiki><pre> 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 </pre></nowiki>
<nowiki><pre> 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 </pre></nowiki>
----== 18. Falls du Hilfe beim Einfügen brauchst ==
----
 
* Öffne im MediaWiki die Seite im Reiner Quelltext-Modus (nicht Rich-Editor).
* Gesamten obigen Quelltext kopieren und einfügen.
* Speichern.
* Beim ersten Rendern: Seite prüfen (Tabellen, <nowiki><pre>-Blöcke). Wenn etwas seltsam aussieht, melde mir die genaue Zeile - ich passe sofort an.</nowiki>


----= Ende =




<nowiki>[[Category: Homelab]]</nowiki>
<nowiki>[[Category: Homelab]]</nowiki>

Version vom 17. Februar 2026, 12:20 Uhr

== 1. Zielsetzung ==

  • 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 ==

  1. Namenauflösung (Admin-Rechner → /etc/hosts) prüfen
  2. SSH-Key auf Controller erzeugen und auf alle VMs verteilen
  3. Ansible auf Controller installieren
  4. Projektstruktur anlegen (inventory, playbook, files)
  5. Playbook zum Verteilen von .bash_aliases ausführen
  6. Falls sudo-Passwords unterschiedlich: einmaliger Bootstrap (manuell) zum Anlegen /etc/sudoers.d/rolf
  7. Optional: Playbook zum APT-Upgrade ausführen (mit Bootstrap-Mechanik)

== 3. Voraussetzungen ==

  • 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 ==

  • 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 become einsetzen, wenn Systemdateien oder owner/group geändert werden.
  • Keine StrictHostKeyChecking=no oder dauerhafte Deaktivierung der HostKey-Prüfung.

== 5. Namensauflösung (wichtig) ==

Auf dem Controller (Admin-Rechner) /etc/hosts pflegen: <pre> # Beispiel 192.168.10.11 vm1 192.168.10.12 vm2 192.168.10.13 vm3 ... </pre> Test nach Eintrag: <pre> ssh rolf@vm1 </pre> Wenn "Could not resolve hostname" → /etc/hosts nicht korrekt.


== 6. SSH-Key: Erzeugen & Verteilen ==

==== === 6.1 SSH-Key erzeugen (Controller) === <pre> ssh-keygen -t ed25519 -a 100 # Pfad: /home/rolf/.ssh/id_ed25519 + id_ed25519.pub </pre> === 6.2 Public Key auf Ziel-VMs verteilen === <pre> ssh-copy-id rolf@vm1 ssh-copy-id rolf@vm2 ... </pre> === 6.3 Wichtige Fehler & Lösungen === ==== {| 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: <pre> cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak > ~/.ssh/known_hosts ssh rolf@vm1 # accept ssh rolf@vm2 # accept </pre>


== 7. Ansible auf Controller installieren ==

<pre> sudo apt update sudo apt install -y ansible ansible --version </pre>


== 8. Projektstruktur (empfohlen) ==

Empfohlenes Verzeichnis auf Controller: ~/ansible <pre> ansible/ ├── inventory.ini ├── playbook.yml # für .bash_aliases ├── playbook-apt-upgrade.yml # optional: apt-upgrade └── files/ ├── bash_aliases └── sudoers_rolf </pre> 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 ==

Beispiel inventory.ini (Hostnamen; /etc/hosts sorgt für Auflösung): <pre> [linux] vm1 vm2 vm3 vm4 vm5 vm6 vm8 [linux:vars] ansible_user=rolf </pre> Tipp: Wenn du IPs direkt nutzt, setze ansible_host explizit, aber vermeide mehrere Wahrheiten.


== 10. Playbook: .bash_aliases verteilen ==

Datei: playbook.yml <pre> - 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 </pre> 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) ==

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. <pre> - 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 </pre> 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 ==

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: <pre> ssh rolf@vmX </pre> Dann auf der VM (interaktiv, Passwort von rolf eingeben): <pre> 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 </pre> Kontrolle (auf Controller oder VM als rolf): <pre> ssh rolf@vmX sudo -n true && echo "sudo ohne Passwort OK" </pre> === 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.

=== 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.


== 13. Laufendes Beispiel: Ausführen der Playbooks ==

  1. Test der Verbindung (nach SSH-Key-Setup)

<pre> ansible linux -m ping -i inventory.ini </pre>

  1. Alias-Playbook ausführen

<pre> cd ~/ansible ansible-playbook -i inventory.ini playbook.yml </pre>

  1. Bootstrap (falls nötig) — siehe Abschnitt 12
  2. APT-Upgrade-Playbook (nach Bootstrap)

<pre> ansible-playbook -i inventory.ini playbook-apt-upgrade.yml </pre> Wenn beim ersten Lauf sudo-Passwort abgefragt wird (wenn gather_facts:NO nicht gesetzt war), nutze: <pre> ansible-playbook -i inventory.ini playbook-apt-upgrade.yml --ask-become-pass </pre> Aber: das funktioniert nur, wenn alle Hosts dasselbe sudo-Passwort haben.


== 14. Troubleshooting: typische Fehlermeldungen & Abhilfe ==

==== === 14.1 UNREACHABLE / Connection timed out === <pre> fatal: [vmX]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ... Connection timed out"} </pre> Ursachen & Checks: ====

  • /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 === <pre> "msg": "Failed to connect to the host via ssh: Host key verification failed." </pre> Lösung: ====

  • 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) ===

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' ===

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 ===

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) ===

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) ===

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 ==

  • 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): <pre> sudo systemctl stop patchmon # ... known_hosts reset + anlernen ... sudo systemctl start patchmon </pre>


== 16. Best Practices / Langfristige Empfehlungen ==

  • 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:

<pre> sudo rm /etc/ssh/ssh_host_* sudo dpkg-reconfigure openssh-server </pre>

  • Optional: vor risky full-upgrade Snapshots (Proxmox) automatisch erstellen.

== 17. Kurze Checkliste (Schnellreferenz) ==

<pre> 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 </pre>



[[Category: Homelab]]