| .kiro/settings | ||
| group_vars | ||
| host_vars | ||
| iso-builder | ||
| roles | ||
| .gitignore | ||
| ansible.cfg | ||
| backup.sh | ||
| base-debian.yml | ||
| borg-backup.yml | ||
| caddy | ||
| frp-client.yml | ||
| frp-server.yml | ||
| glances.yml | ||
| hawser.yml | ||
| hysteria2-cleanup.yml | ||
| id_ed25519.pub | ||
| nvidia-docker.yml | ||
| pfannkuchen.ini | ||
| pfannkuchen.sh | ||
| pihole-dns.yml | ||
| pve-gpu-passthrough.yml | ||
| pve-postinstall.yml | ||
| README.md | ||
| site.yml | ||
| sysctl-proxmox.yaml | ||
| sysctl.yaml | ||
| telegraf.yml | ||
| update.yml | ||
| wireguard.yml | ||
| wstunnel-cleanup.yml | ||
Ansible Playbooks
Ansible-Setup für Proxmox-VMs, Hetzner-Server und Borg Backup auf Hetzner Storagebox.
Quickstart
# Wrapper-Script nutzen
./pfannkuchen.sh setup emby_sascha # VM komplett einrichten
./pfannkuchen.sh backup # Borg auf allen Backup-Hosts
./pfannkuchen.sh update # Alle Hosts updaten
./pfannkuchen.sh gpu tdarr # NVIDIA Setup
./pfannkuchen.sh pve # Proxmox Post-Install
./pfannkuchen.sh passthrough # GPU Passthrough vorbereiten
./pfannkuchen.sh telegraf # Telegraf Monitoring
./pfannkuchen.sh hysteria2 node1 # Hysteria2 + WireGuard
./pfannkuchen.sh ping # Alle Hosts anpingen
./pfannkuchen.sh list # Inventory anzeigen
# Oder direkt mit Ansible
ansible-playbook site.yml -l emby_sascha
ansible-playbook borg-backup.yml -l proxmox
ansible-playbook update.yml
Infrastruktur
Proxmox Hosts
| Host | IP | GPU |
|---|---|---|
| node1 | 10.5.85.11 | – |
| node2 | 10.5.85.12 | – |
| node3 | 10.5.85.13 | – |
| node4 | 10.5.85.14 | – |
| node5 | 10.5.85.15 | A400 |
| node6 | 10.5.85.16 | A400 |
| node7 | 10.5.85.17 | A400 |
VMs / LXCs
| Name | IP | Gruppe | Zweck |
|---|---|---|---|
| emby-sascha | 10.6.1.103 | media | Emby (Sascha) |
| jellyfin | 10.5.1.112 | media | Jellyfin |
| immich | 10.4.1.107 | media | Immich Fotoverwaltung |
| emby-chris | 10.7.1.106 | media | Emby (Chris) + SMB |
| tdarr | 10.2.1.104 | arr | Tdarr Transcoding |
| arrapps | 10.2.1.100 | arr | Sonarr/Radarr etc. |
| sabnzbd | 10.2.1.119 | arr | SABnzbd |
| dockhand | 10.4.1.116 | docker | Dockhand |
| n8n | 10.4.1.113 | auto | n8n Automation |
| openclaw | 10.4.1.100 | auto | OpenClaw |
| monitoring | 10.1.1.111 | auto | Monitoring Stack |
| automation | 10.1.1.115 | auto | Automation Stack |
| matrix | 10.4.1.110 | communication | Matrix |
Hetzner
| Name | IP | Zweck |
|---|---|---|
| pfannkuchen | 159.69.245.190 | Caddy Reverse Proxy + VW |
Hetzner Storagebox
- Host:
u457772-sub3.your-storagebox.de - User:
u457772-sub3 - Port: 23
- SSH Key liegt in
roles/borg/files/und wird als/root/.ssh/id_borgdeployed
Docker Stacks
Jeder Stack hat ein eigenes Git-Repo unter ~/pfannkuchen/github/ und ein eigenes Docker-Netzwerk.
| Stack | VM | Netzwerk | Services |
|---|---|---|---|
| pfannkuchen | Hetzner VPS | proxy_network |
Caddy, Vaultwarden, Homepage |
| monitoring | 10.1.1.111 | monitoring_network |
Teslamate, Postgres, Grafana, Mosquitto, Prometheus, SNMP-Exporter, InfluxDB, Emby-Exporter, Node-Exporter |
| automation | 10.1.1.115 | auto_network |
WAHA, Semaphore UI, Patchmon (DB, Redis, Backend, Frontend) |
| n8n | 10.4.1.113 | n8n_network |
n8n, Postgres |
Caddy Reverse Proxy (Hetzner VPS)
Caddy läuft auf dem Hetzner VPS und proxied alle Services über WireGuard-IPs:
| Domain | Backend | Bemerkung |
|---|---|---|
| tv.sascha-lutz.de | host.docker.internal:18096 | Emby Sascha |
| guck.tv | host.docker.internal:28096 | Emby Chris |
| netzflix.org | host.docker.internal:38096 | Emby Jellyfin |
| vault.sascha-lutz.de | vaultwarden (Container) | Vaultwarden |
| home.sascha-lutz.de | homepage:3000 (Container) | Homepage (Basic Auth) |
| grafana.sascha-lutz.de | grafana:3000 (Container) | Grafana |
| patchmon.sascha-lutz.de | patchmon-frontend:3000 | Patchmon |
| tesla.sascha-lutz.de | teslamate:4000 (Container) | Teslamate (Basic Auth) |
| influx.sascha-lutz.de | influxdb:8086 (Container) | InfluxDB |
| status.guck.tv | 10.200.200.254:3001 | Uptime Kuma |
| n8n.sascha-lutz.de | 10.4.1.113:5678 | n8n |
| docker.sascha-lutz.de | 10.4.1.116:3000 | Dockhand |
| immich.sascha-lutz.de | 10.4.1.107:2283 | Immich |
| dl.guck.tv | 10.2.1.100:5055 | Jellyseerr |
| plappern.com | 10.4.1.110:8008 | Matrix Synapse |
| web.plappern.com | 10.4.1.110:8080 | Matrix Element |
| chat.plappern.com | 10.4.1.110:8090 | Matrix Chat |
| monitor.guck.tv | 10.5.1.102:19999 | Netdata (Basic Auth) |
Seerr → WhatsApp + Auto-Approve
Kombinierter n8n Workflow der zwei Dinge macht:
1. Auto-Approve (MEDIA_PENDING):
Jellyseerr → Webhook → n8n → TMDB Genre+FSK Lookup → Kategorisieren → Pfad+Tags setzen → Approve → 20min warten → FHD Radarr/Sonarr Suche
Genre-Logik:
| Kategorie | Bedingung | Radarr Pfad | Tag |
|---|---|---|---|
| Horror | Genre "Horror" + FSK ≥ 16 | /data/UHD/horror |
horror-4k |
| Kids | Genre "Animation"/"Family" + FSK ≤ 12 | /data/UHD/kids-video |
kids-4k |
| Normal | Alles andere | /data/UHD/video |
video-4k |
Serien:
| Kategorie | Bedingung | Sonarr Pfad | Tag |
|---|---|---|---|
| Kids | Genre "Animation" + FSK ≤ 12 | /data/UHD/kids-serien |
kids-4k |
| Streaming | Network ist Netflix/HBO/Amazon/Disney+ etc. | /data/UHD/serien |
serien-4k |
| TV | Alles andere | /data/UHD/tvshows |
tvshows-4k |
2. WhatsApp Newsletter (MEDIA_AVAILABLE):
Jellyseerr → Webhook → n8n → WAHA Session Restart → WAHA sendText → WhatsApp Newsletter
- Webhook URL:
http://10.4.1.113:5678/webhook/seerr-notify - WAHA:
http://10.1.1.115:3500(Dashboard: admin / WAHA_API_KEY) - Newsletter Channel:
120363404705299449@newsletter - n8n Workflow:
tmp/n8n-seerr-combined.json - Status: Funktioniert (Text + Bild-URL, keine eingebetteten Bilder möglich)
Semaphore UI
Web-UI für Ansible Playbook Management auf http://10.1.1.115:3000.
- Login:
admin/SEMAPHORE_ADMIN_PASSWORD(aus.env) - Projekt: Pfannkuchen
- Templates: Setup VM, Update All, Borg Backup, Base Setup, NVIDIA GPU
- Git Repo:
https://github.com/feldjaeger/ansible.git
Arr-Stack APIs
| Service | URL | API Key Datei |
|---|---|---|
| Radarr UHD | http://10.2.1.100:7878 |
tmp/radarr |
| Radarr FHD | http://10.2.1.100:7879 |
tmp/radarr1080p |
| Sonarr UHD | http://10.2.1.100:8989 |
tmp/sonarr |
| Sonarr FHD | http://10.2.1.100:8990 |
tmp/sonarr1080p |
| Jellyseerr | http://10.2.1.100:5055 |
tmp/seer |
| TMDB API | https://api.themoviedb.org/3 |
tmp/tmdb (nicht im Repo) |
ISO Builder
Baut Custom Debian ISOs mit Preseed für unattended Installation. Siehe iso-builder/README.md.
# ISO bauen + auf Proxmox Node uploaden
./iso-builder/build-iso.sh --node 4 --ip 10.4.1.120 --hostname neue-vm
# ISO bauen + VM erstellen + starten
./iso-builder/build-iso.sh --node 4 --ip 10.4.1.120 --hostname neue-vm --create-vm
Netzwerk
WireGuard Tunnel (Hysteria2)
Alle Proxmox Nodes verbinden sich über Hysteria2 (QUIC) zum VPS. Das umgeht CGNAT-Beschränkungen und versteckt den WireGuard-Traffic vor DPI (Sophos Firewall).
[Proxmox Node] → Hysteria2-Client → QUIC (UDP:8443) → Hysteria2-Server (VPS) → WireGuard
- Hysteria2 nutzt UDP:8443, Caddy behält TCP:443 + UDP:443 (HTTP/3)
- TLS: Selbstsigniertes Zertifikat auf dem VPS (10 Jahre gültig), Clients mit
insecure: true - Bandwidth-Hints konfiguriert für optimale Performance (400 Mbit/s)
| Node | WG-IP | VM-Subnetz | Bemerkung |
|---|---|---|---|
| VPS | 10.200.200.254 | – | WG Server + Hub |
| node1 | 10.200.200.2 | 10.11.1.0/24 | |
| node2 | 10.200.200.3 | 10.2.1.0/24 | Arr-Stack |
| node3 | 10.200.200.113 | 10.3.1.0/24 | |
| node4 | 10.200.200.100 | 10.4.1.0/24 | Docker/Auto |
| node5 | 10.200.200.101 | 10.5.1.0/24 | Media |
| node6 | 10.200.200.116 | 10.6.1.0/24 | A400 |
| node7 | 10.200.200.117 | 10.7.1.0/24 | A400 |
Direkte Peers (kein Hysteria2):
- embyproxy (10.200.200.1)
- Sascha (10.200.200.5), Chris (10.200.200.6), Sascha Handy (10.200.200.7)
- Fassohneboden (10.200.200.4), Marco Minecraft (10.200.200.8)
Netzwerk-Segmente
| Subnetz | Zweck | Node |
|---|---|---|
| 10.5.85.x | Proxmox Hosts | alle |
| 10.1.1.x | Monitoring/Auto | node1 |
| 10.11.1.x | VMs node1 | node1 |
| 10.2.1.x | Arr-Stack | node2 |
| 10.3.1.x | VMs node3 | node3 |
| 10.4.1.x | Docker/Auto | node4 |
| 10.5.1.x | Media VMs | node5 |
| 10.6.1.x | VMs node6 | node6 |
| 10.7.1.x | VMs node7 | node7 |
| 10.200.200.x | WireGuard | VPS |
Rollen
| Rolle | Zweck |
|---|---|
| base | Repos, Pakete, Locale, SSH Key, Sudo, QEMU Guest Agent |
| docker | Docker CE + Compose Plugin, User sascha → docker Gruppe |
| nvidia | CUDA Repo, cuda-drivers, Container Toolkit, Docker nvidia-RT |
| borg | SSH Key Deploy, Borg Repo Init, Backup-Script, Systemd Timer |
| hawser | Hawser Install + Systemd Service + Token aus Vault |
| sysctl | BBR, TCP Tuning, Buffer Sizes für Streaming-VMs |
| sysctl_proxmox | Overcommit, File Handles, IP Forward, Bridge-Tuning |
| pve_postinstall | Repos (deb822), Enterprise deaktiviert, Nag-Patch, HA aus |
| pve_gpu_passthrough | IOMMU, VFIO, Nouveau/NVIDIA Blacklist für GPU Passthrough |
| telegraf | InfluxData Repo, Telegraf Config, lm-sensors, Synology SNMP |
| hysteria2 | Hysteria2 Client, Bandwidth-Hints, WireGuard Config |
| hysteria2_server | Hysteria2 Server, selbstsigniertes TLS, systemd Service |
Playbooks
| Playbook | Wrapper-Befehl | Zweck |
|---|---|---|
site.yml |
setup <host> |
VM komplett einrichten |
base-debian.yml |
base <host> |
Grundsetup + Docker |
nvidia-docker.yml |
gpu <host> |
NVIDIA Treiber + Docker GPU Runtime |
borg-backup.yml |
backup [host] |
Borg Backup einrichten |
hawser.yml |
hawser <host> |
Hawser installieren |
update.yml |
update [host] |
Dist-Upgrade + Autoremove |
sysctl.yaml |
tune <host> |
Netzwerk-Tuning für Streaming |
sysctl-proxmox.yaml |
– | Proxmox-Host-Tuning |
pve-postinstall.yml |
pve [host] |
Proxmox Post-Install (Repos, Nag, HA) |
pve-gpu-passthrough.yml |
passthrough [host] |
GPU PCI Passthrough vorbereiten |
telegraf.yml |
telegraf [host] |
Telegraf Monitoring deployen |
hysteria2.yml |
– | Hysteria2 Client + WireGuard deployen |
hysteria2-server.yml |
– | Hysteria2 Server auf VPS deployen |
Inventory-Gruppen
| Gruppe | Hosts | Zweck |
|---|---|---|
| proxmox | node1–node7 | Alle Proxmox Hosts |
| proxmox_gpu | node2, node4, node6, node7 | Nodes mit A400 GPU |
| nvidia | tdarr, emby-sascha, emby-chris, immich | VMs mit NVIDIA GPU Runtime |
| wireguard | node1–node7 | WireGuard Clients |
| media | emby-sascha, jellyfin, immich, emby-chris | Media VMs |
| arr | tdarr, arrapps, sabnzbd | Arr-Stack |
| docker | dockhand | Docker VMs |
| auto | n8n, openclaw, monitoring, automation | Automation |
| communication | matrix | Kommunikation |
| hetzner | pfannkuchen | Hetzner Server |
| frp | emby-sascha, emby-chris, jellyfin | FRP Clients |
| backup | alle (via children) | Borg Backup |
Borg Backup
Alle Hosts in der Gruppe backup bekommen Borg Backup. Die Backup-Quellen sind pro Gruppe konfiguriert:
| Gruppe | Backup-Quellen | Quelle |
|---|---|---|
| VMs | /app-config |
roles/borg/defaults/main.yml |
| Proxmox | /etc/pve /etc/network /etc/wireguard /etc/crontab /etc/fstab /etc/systemd/system/ /etc/iptables /etc/telegraf |
group_vars/proxmox/borg.yml |
| Hetzner | /etc/wireguard /app-config |
group_vars/hetzner/borg.yml |
Backup-Script: /usr/local/bin/borg-backup.sh
Systemd Timer: täglich 03:00 Uhr (±30min Jitter)
Log: /var/log/borg-backup.log
Kompression: lz4
Retention: 7 daily, 4 weekly, 6 monthly
Telegraf Monitoring
Alle Proxmox Hosts bekommen Telegraf mit InfluxDB v2 Output.
Standard-Inputs: cpu, disk, diskio, kernel, mem, processes, swap, system, nstat, sensors
Sonderfall node2: Zusätzlich Synology NAS SNMP Monitoring (konfiguriert via host_vars/node2/telegraf.yml).
Vault
Vault-Datei: group_vars/all/vault.yml
Enthaltene Variablen:
vault_hetzner_storage_host– Storagebox Hostnamevault_hetzner_storage_user– Storagebox Uservault_borg_passphrase– Borg Verschlüsselungspasswortvault_sascha_password– SSH/Become-Passwort für User saschavault_chris_password– SSH/Become-Passwort für User chrisvault_telegraf_influx_token– InfluxDB v2 Token für Telegrafvault_snmp_sec_name– SNMP v3 Security Name (Synology)vault_snmp_auth_password– SNMP v3 Auth Passwortvault_snmp_priv_password– SNMP v3 Privacy Passwortvault_hysteria2_password– Hysteria2 Auth Passwortvault_wireguard_vps_pubkey– WireGuard Public Key des VPSvault_node[1-7]_wg_privkey– WireGuard Private Keys der Nodesvault_hawser_token– Hawser Agent Token für Dockhand
# Passwörter eintragen und verschlüsseln
ansible-vault edit group_vars/all/vault.yml
ansible-vault encrypt group_vars/all/vault.yml
Vault-Passwort liegt in .vault-password (in .gitignore).
Verzeichnisstruktur
ansible/
├── ansible.cfg
├── pfannkuchen.ini # Inventory
├── pfannkuchen.sh # Wrapper-Script
├── site.yml # Master-Playbook
├── base-debian.yml
├── borg-backup.yml
├── nvidia-docker.yml
├── hawser.yml
├── update.yml
├── sysctl.yaml
├── sysctl-proxmox.yaml
├── pve-postinstall.yml
├── pve-gpu-passthrough.yml
├── telegraf.yml
├── hysteria2.yml
├── hysteria2-server.yml
├── iso-builder/ # Custom Debian ISO Builder
│ ├── build-iso.sh # ISO Build + Upload + VM Create
│ ├── preseed.cfg.tpl # Preseed Template
│ └── output/ # Gebaute ISOs
├── group_vars/
│ ├── all/vault.yml # Vault (verschlüsselt)
│ ├── proxmox/borg.yml # Proxmox Backup-Pfade
│ └── hetzner/borg.yml # Hetzner Backup-Pfade
├── host_vars/
│ ├── node1/wireguard.yml
│ ├── node2/
│ │ ├── telegraf.yml # Synology SNMP
│ │ └── wireguard.yml
│ ├── node3–node7/wireguard.yml
│ └── emby_chris/vars.yml # User chris Credentials
├── tmp/
│ ├── n8n-seerr-combined.json # n8n Workflow: Auto-Approve + WhatsApp
│ ├── radarr, sonarr, seer # API Keys
│ ├── radarr1080p, sonarr1080p # FHD API Keys
│ └── n8n # n8n API Key
└── roles/
├── base/tasks/main.yml
├── docker/tasks/main.yml
├── nvidia/{tasks,handlers,defaults}/
├── borg/{tasks,defaults,files,templates}/
├── hawser/tasks/main.yml
├── hawser/handlers/main.yml
├── sysctl/tasks/main.yml
├── sysctl_proxmox/tasks/main.yml
├── pve_postinstall/tasks/main.yml
├── pve_gpu_passthrough/{tasks,handlers}/
├── telegraf/{tasks,handlers,defaults,templates}/
├── hysteria2/{tasks,handlers,defaults}/
└── hysteria2_server/{tasks,handlers,defaults}/