Ansible im Homelab: Server automatisieren wie ein Profi

Ansible im Homelab einrichten und Server automatisieren. Best Practices für Inventory, Playbooks, Rollen und Vault. Praxis-Beispiele für Proxmox, Docker und Linux.

Warum Ansible im Homelab?#

Hand aufs Herz: Wer hat schon Lust, die gleichen Befehle auf fünf verschiedenen Servern auszuführen? Oder bei jedem neuen Proxmox-Host wieder von vorne anzufangen mit der Konfiguration?

Genau hier kommt Ansible ins Spiel. Stell dir vor, du könntest mit einem einzigen Befehl:

  • Alle Server auf einmal updaten
  • Docker auf mehreren Hosts gleichzeitig ausrollen
  • User-Accounts zentral verwalten
  • Monitoring-Agents überall installieren
  • Backup-Jobs einheitlich konfigurieren

Das Beste: Ansible ist agentless – du brauchst nur SSH-Zugriff. Keine zusätzlichen Daemons, keine komplizierte Infrastruktur. Perfekt für’s Homelab.

In diesem Tutorial zeige ich dir, wie du Ansible richtig aufsetzt – mit der Struktur, die auch Profis verwenden. Keine Quick-Hacks, sondern ein Setup, das mit deinem Homelab mitwächst.

Installation und erste Schritte#

Ansible installieren#

Auf deinem Control Node (der Maschine, von der aus du alles steuerst – kann auch dein Laptop sein):

Debian/Ubuntu:

sudo apt update
sudo apt install ansible sshpass

RHEL/Rocky/AlmaLinux:

sudo dnf install ansible

MacOS:

brew install ansible

Version prüfen:

ansible --version
# ansible [core 2.16.3] oder neuer

SSH-Keys einrichten (wichtig!)#

Damit Ansible auf deine Server zugreifen kann, brauchst du SSH-Key-Authentication:

# SSH-Key generieren (falls noch nicht vorhanden)
ssh-keygen -t ed25519 -C "ansible@homelab"

# Key auf alle Server verteilen
ssh-copy-id root@server1.local
ssh-copy-id root@server2.local
# usw.

Tipp: Nutze einen separaten User (z.B. ansible) mit sudo-Rechten statt root. Sicherer und professioneller!

Schnelltest#

Prüfen, ob Ansible deine Server erreicht:

ansible all -i "server1.local," -m ping
# server1.local | SUCCESS => 

Das Komma nach dem Hostnamen ist wichtig – es signalisiert Ansible, dass es sich um eine Inline-Liste handelt.

Inventory richtig aufbauen#

Das Inventory ist deine Server-Liste. Hier definierst du, welche Hosts existieren und wie sie gruppiert sind.

Statisches Inventory#

Erstelle eine Datei inventory/production:

# Webserver
[webservers]
web01.local ansible_host=192.168.66.11
web02.local ansible_host=192.168.66.12

# Docker-Hosts
[docker]
docker01.local ansible_host=192.168.66.21
docker02.local ansible_host=192.168.66.22

# Proxmox-Hosts
[proxmox]
pve01.local ansible_host=192.168.66.31
pve02.local ansible_host=192.168.66.32

# Datenbanken
[databases]
db01.local ansible_host=192.168.66.41

# Gruppen zusammenfassen
[production:children]
webservers
docker
proxmox
databases

Warum Gruppen?

  • Du kannst Befehle gezielt auf bestimmte Server-Typen anwenden
  • Variablen können pro Gruppe definiert werden
  • Übersichtlichkeit bei wachsender Infrastruktur

Variablen pro Gruppe#

Erstelle group_vars/docker.yml:

---
# Variablen für alle Docker-Hosts
ansible_user: ansible
ansible_become: yes
docker_version: "24.0"
docker_compose_version: "2.23.0"

Und group_vars/all.yml für globale Werte:

---
# Gilt für ALLE Server
ntp_server: "192.168.66.1"
timezone: "Europe/Berlin"
monitoring_server: "monitor.local"

Host-spezifische Variablen#

Für einzelne Server mit besonderen Einstellungen: host_vars/web01.local.yml:

---
nginx_worker_processes: 4
max_upload_size: "100M"

Dynamisches Inventory für Proxmox#

Wenn du viele VMs hast und diese automatisch erfassen willst, nutze dynamisches Inventory. Für Proxmox gibt es fertige Plugins:

ansible-galaxy collection install community.general

Erstelle inventory/proxmox.yml:

plugin: community.general.proxmox
url: https://pve01.local:8006
user: ansible@pam
password: !vault |
  $ANSIBLE_VAULT;1.1;AES256...
validate_certs: false

Mehr dazu später unter Ansible Vault!

Erstes Playbook: System-Updates auf allen Servern#

Jetzt wird’s praktisch. Ein Playbook beschreibt, was auf welchen Hosts passieren soll.

Erstelle playbooks/update-systems.yml:

---
- name: System-Updates auf allen Servern ausführen
  hosts: all
  become: yes
  
  tasks:
    - name: Paketliste aktualisieren (Debian/Ubuntu)
      apt:
        update_cache: yes
        cache_valid_time: 3600
      when: ansible_os_family == "Debian"
    
    - name: Alle Pakete updaten (Debian/Ubuntu)
      apt:
        upgrade: dist
        autoremove: yes
      when: ansible_os_family == "Debian"
    
    - name: Alle Pakete updaten (RHEL/Rocky)
      dnf:
        name: "*"
        state: latest
      when: ansible_os_family == "RedHat"
    
    - name: Prüfen ob Reboot nötig ist
      stat:
        path: /var/run/reboot-required
      register: reboot_required
      when: ansible_os_family == "Debian"
    
    - name: Warnung ausgeben wenn Reboot nötig
      debug:
        msg: "⚠️  } benötigt einen Neustart!"
      when: 
        - ansible_os_family == "Debian"
        - reboot_required.stat.exists

Ausführen:

ansible-playbook -i inventory/production playbooks/update-systems.yml

Was passiert hier?

  • hosts: all → Läuft auf allen Servern im Inventory
  • become: yes → Nutzt sudo für root-Rechte
  • when: → Conditional – nur ausführen wenn Bedingung erfüllt
  • Module wie apt, dnf, stat erledigen die eigentliche Arbeit

Rollen-Struktur: So organisieren Profis#

Sobald deine Playbooks komplexer werden, wirds unübersichtlich. Rollen sind die Lösung – wiederverwendbare, modulare Komponenten.

Die perfekte Directory-Struktur#

So sollte dein Ansible-Projekt aussehen:

ansible/
├── inventory/
│   ├── production          # Produktiv-Server
│   └── staging             # Test-Umgebung
├── group_vars/
│   ├── all.yml            # Globale Variablen
│   ├── docker.yml         # Docker-Host-Variablen
│   └── webservers.yml
├── host_vars/
│   └── web01.local.yml    # Host-spezifisch
├── roles/
│   ├── common/            # Basis-Setup für alle Server
│   │   ├── tasks/
│   │   │   └── main.yml
│   │   ├── handlers/
│   │   │   └── main.yml
│   │   ├── templates/
│   │   ├── files/
│   │   └── defaults/
│   │       └── main.yml
│   ├── docker/            # Docker-Installation
│   ├── monitoring/        # Monitoring-Agent
│   └── nginx/             # Webserver-Setup
├── playbooks/
│   ├── site.yml           # Master-Playbook
│   ├── webservers.yml
│   └── docker-hosts.yml
└── ansible.cfg            # Ansible-Konfiguration

Beispiel: Common-Rolle#

Die common-Rolle macht Basis-Setup auf allen Servern. Erstelle roles/common/tasks/main.yml:

---
- name: Timezone setzen
  timezone:
    name: "}"

- name: Wichtige Basis-Pakete installieren
  apt:
    name:
      - vim
      - htop
      - curl
      - wget
      - git
      - python3
      - python3-pip
    state: present
    update_cache: yes
  when: ansible_os_family == "Debian"

- name: NTP konfigurieren
  template:
    src: ntp.conf.j2
    dest: /etc/ntp.conf
  notify: restart ntp

- name: NTP-Dienst aktivieren
  service:
    name: ntp
    state: started
    enabled: yes

Template roles/common/templates/ntp.conf.j2:

# NTP-Konfiguration für }
driftfile /var/lib/ntp/ntp.drift

server } prefer iburst
server 0.de.pool.ntp.org iburst
server 1.de.pool.ntp.org iburst

Handler roles/common/handlers/main.yml:

---
- name: restart ntp
  service:
    name: ntp
    state: restarted

Master-Playbook#

Das site.yml Playbook orchestriert alles:

---
- name: Basis-Konfiguration für alle Server
  hosts: all
  roles:
    - common

- name: Docker-Hosts provisionieren
  hosts: docker
  roles:
    - docker
    - monitoring

- name: Webserver konfigurieren
  hosts: webservers
  roles:
    - nginx
    - monitoring

Ausführen:

# Alles
ansible-playbook -i inventory/production playbooks/site.yml

# Nur Webserver
ansible-playbook -i inventory/production playbooks/site.yml --limit webservers

# Nur common-Rolle auf allen Servern
ansible-playbook -i inventory/production playbooks/site.yml --tags common

Ansible Vault: Secrets sicher verwalten#

Passwörter und API-Keys gehören nicht im Klartext ins Git-Repo!

Vault-File erstellen#

ansible-vault create group_vars/all/vault.yml
# Editor öffnet sich, Passwort wird abgefragt

Inhalt von vault.yml:

---
vault_mysql_root_password: "SuperSecret123!"
vault_api_token: "abc123xyz"
vault_proxmox_password: "ProxmoxPass"

Best Practice: Indirection Layer#

Nutze niemals vault_* Variablen direkt in Playbooks! Lege stattdessen eine vars.yml an:

group_vars/all/vars.yml:

---
mysql_root_password: "}"
api_token: "}"
proxmox_password: "}"

Warum? Du kannst mit grep nach Variablen suchen, ohne verschlüsselte Files zu durchsuchen.

Vault-File bearbeiten#

# Anzeigen
ansible-vault view group_vars/all/vault.yml

# Editieren
ansible-vault edit group_vars/all/vault.yml

# Passwort ändern
ansible-vault rekey group_vars/all/vault.yml

Playbook mit Vault ausführen#

ansible-playbook -i inventory/production playbooks/site.yml --ask-vault-pass

Oder nutze ein Passwort-File:

echo "DeinVaultPasswort" > ~/.ansible_vault_pass
chmod 600 ~/.ansible_vault_pass

# In ansible.cfg
[defaults]
vault_password_file = ~/.ansible_vault_pass

Praxis-Beispiele#

1. Docker-Host provisionieren#

Rolle roles/docker/tasks/main.yml:

---
- name: Docker GPG-Key hinzufügen
  apt_key:
    url: https://download.docker.com/linux/ubuntu/gpg
    state: present

- name: Docker Repository hinzufügen
  apt_repository:
    repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu } stable"
    state: present

- name: Docker und Docker Compose installieren
  apt:
    name:
      - docker-ce
      - docker-ce-cli
      - containerd.io
      - docker-compose-plugin
    state: present
    update_cache: yes

- name: Docker-Dienst aktivieren
  service:
    name: docker
    state: started
    enabled: yes

- name: Docker-Gruppe für User anlegen
  user:
    name: "}"
    groups: docker
    append: yes

- name: Docker-Daemon konfigurieren
  template:
    src: daemon.json.j2
    dest: /etc/docker/daemon.json
  notify: restart docker

Mehr Details findest du in unserem Docker auf Proxmox Tutorial.

2. User-Management über alle Server#

Playbook playbooks/manage-users.yml:

---
- name: Zentrale User-Verwaltung
  hosts: all
  become: yes
  
  vars:
    admin_users:
      - username: max
        ssh_key: "ssh-ed25519 AAAAC3..."
        sudo: yes
      - username: lisa
        ssh_key: "ssh-ed25519 AAAAC3..."
        sudo: no
  
  tasks:
    - name: Admin-User anlegen
      user:
        name: "}"
        shell: /bin/bash
        groups: "}"
        append: yes
      loop: "}"
    
    - name: SSH-Keys hinterlegen
      authorized_key:
        user: "}"
        key: "}"
        state: present
      loop: "}"
    
    - name: Sudoers-Rechte ohne Passwort
      lineinfile:
        path: /etc/sudoers.d/}
        line: "} ALL=(ALL) NOPASSWD:ALL"
        create: yes
        mode: '0440'
      when: item.sudo
      loop: "}"

Einmal ausführen, überall angelegt!

3. Monitoring-Agent ausrollen#

Rolle roles/monitoring/tasks/main.yml:

---
- name: Zabbix Agent Repository hinzufügen
  apt:
    deb: "https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_6.4-1+ubuntu22.04_all.deb"

- name: Zabbix Agent installieren
  apt:
    name: zabbix-agent2
    state: present
    update_cache: yes

- name: Zabbix Agent konfigurieren
  template:
    src: zabbix_agent2.conf.j2
    dest: /etc/zabbix/zabbix_agent2.conf
  notify: restart zabbix-agent2

- name: Zabbix Agent aktivieren
  service:
    name: zabbix-agent2
    state: started
    enabled: yes

Template roles/monitoring/templates/zabbix_agent2.conf.j2:

Server=}
ServerActive=}
Hostname=}

Ein Befehl, alle Server werden überwacht:

ansible-playbook -i inventory/production playbooks/site.yml --tags monitoring

Tipps für Fortgeschrittene#

1. Tags clever nutzen#

- name: Nginx installieren
  apt:
    name: nginx
    state: present
  tags:
    - nginx
    - webserver
    - install

- name: Nginx konfigurieren
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  tags:
    - nginx
    - webserver
    - config

Ausführung:

# Nur Installation
ansible-playbook site.yml --tags install

# Nur Konfiguration
ansible-playbook site.yml --tags config

# Alles für Nginx
ansible-playbook site.yml --tags nginx

2. Check Mode (Dry Run)#

Testen, was passieren würde – ohne Änderungen:

ansible-playbook site.yml --check --diff

--diff zeigt dabei die geplanten Änderungen an Config-Dateien.

3. Serial Updates (Rolling Updates)#

Bei kritischen Servern nicht alle gleichzeitig updaten:

- name: Webserver-Update mit Rollout
  hosts: webservers
  serial: 2  # Immer nur 2 gleichzeitig
  
  tasks:
    - name: Server aus Load Balancer nehmen
      # ...
    
    - name: Updates installieren
      # ...
    
    - name: Reboot durchführen
      reboot:
    
    - name: Server wieder in Load Balancer
      # ...

4. Fact Caching#

Ansible sammelt bei jedem Lauf “Facts” (System-Infos). Das dauert. Aktiviere Caching:

ansible.cfg:

[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400

5. Roles aus Ansible Galaxy nutzen#

Warum das Rad neu erfinden?

# Beispiel: geerlingguy's Docker-Rolle
ansible-galaxy install geerlingguy.docker

# In requirements.yml definieren
cat > requirements.yml <<EOF
roles:
  - name: geerlingguy.docker
  - name: geerlingguy.postgresql
EOF

# Installieren
ansible-galaxy install -r requirements.yml

6. Molecule für Rolle-Tests#

Teste deine Rollen mit Molecule bevor du sie produktiv einsetzt:

pip3 install molecule molecule-docker

cd roles/docker
molecule init scenario
molecule test

🛒 Empfohlene Tools & Services#

🖥️

Hetzner Cloud für Ansible-Labs

Ansible-Playbooks in der Cloud testen? Hetzner Cloud Server kannst du in Sekunden erstellen und zerstören — perfekt zum Üben. Hetzner ausprobieren →

Zusammenfassung#

Du hast jetzt gelernt:

Warum Ansible perfekt für’s Homelab ist (agentless, einfach, mächtig)
Installation & SSH-Setup für sichere Automatisierung
Inventory-Struktur mit Gruppen und Variablen
Playbooks schreiben für System-Updates und mehr
Rollen-Organisation wie die Profis
Ansible Vault für sichere Secret-Verwaltung
Praxis-Beispiele für Docker, User-Management und Monitoring
Profi-Tipps für Tags, Check Mode, Rolling Updates & mehr

Nächste Schritte#

  1. Starte klein: Beginne mit einem Update-Playbook für alle Server
  2. Wachse organisch: Füge Rollen hinzu wenn du sie brauchst
  3. Nutze Git: Versioniere dein Ansible-Repo (ohne Vault-Passwörter!)
  4. Teste erst: Nutze --check oder eine Staging-Umgebung
  5. Dokumentiere: Schreibe README-Dateien in deine Rollen

Ressourcen#

Viel Erfolg mit deiner Homelab-Automatisierung! 🚀

Hast du Fragen oder Probleme? Schreib’s in die Kommentare! Und wenn dir dieser Guide geholfen hat, teile ihn gerne mit anderen Homelab-Enthusiasten.


Dieser Artikel ist Teil der Serie “Homelab aufbauen”. Schau dir auch unsere anderen Tutorials an:


Einige Links auf dieser Seite sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision — für dich ändert sich am Preis nichts. So unterstützt du diesen Blog und ermöglichst weitere kostenlose Tutorials. Danke! 🙏

[« Vorherige]
Keycloak: Passkey Auto-Login mit Passwort-Fallback