Mein Homelab: 25 Dienste, sechs Hosts und kein einziger Handgriff auf dem Server

July 25, 2026

HomelabAnsibleDockerNixOSDevOps

Beruflich betreue ich rund 60 Linux-Server und zwei HA-Kubernetes-Cluster. Privat läuft bei mir zu Hause eine deutlich kleinere, aber überraschend ähnlich gebaute Infrastruktur: sechs Hosts, etwa 25 Docker-Dienste, ein VPN und ein Ansible-Projekt, das alles zusammenhält.

Ich werde immer wieder gefragt, wozu man privat so etwas braucht. Die kurze Antwort: weil ich meine Daten selbst in der Hand haben will und weil ein Homelab der ehrlichste Übungsplatz ist, den man bekommen kann. Wenn etwas kaputtgeht, gibt es keinen Kollegen, der es repariert. Die lange Antwort ist dieser Artikel.

Mein Homelab

Die Topologie

Fangen wir mit dem an, was man anfassen kann. Wer bei „Homelab“ an ein Rack im Keller denkt, wird bei mir enttäuscht: Hier stehen drei kleine Rechner und ein NAS, zusammen kaum größer als ein Schuhkarton.

  • Ein Geekom Mini Air12 als stärkste Maschine
  • Zwei ZimaBoards (Gen 1 und Gen 2), beide komplett lüfterlos, wobei die zweite Generation der ersten leistungsmäßig deutlich davonzieht, ohne nennenswert mehr Strom zu brauchen
  • Ein Ugreen DXP2800 als NAS

Das ist eine bewusste Entscheidung. Das Ganze läuft rund um die Uhr, niedriger Stromverbrauch war deshalb das wichtigste Auswahlkriterium, noch vor der Rechenleistung. Ausgemusterte Server-Hardware bekommt man günstig hinterhergeworfen, aber man bezahlt sie zwölf Monate im Jahr über die Stromrechnung nach. Der angenehme Nebeneffekt der kleinen, teils lüfterlosen Geräte: Man hört das Homelab nicht. Es steht nicht im Keller, sondern einfach da, wo Platz ist.

Zwei der drei Rechner, der Geekom und das neuere ZimaBoard, laufen unter Proxmox, aber bewusst nicht als Cluster. Die beiden Nodes sind eigenständig. Ein Cluster würde mir Live-Migration und ein gemeinsames Web-Interface bringen, dafür aber Quorum, geteilten Storage und eine Menge Probleme einhandeln, die ich zu Hause nicht haben will. Fällt eine Maschine aus, fehlen mir die Dienste darauf. Das ist verkraftbar und deutlich einfacher zu reparieren als ein Cluster, der sich verschluckt hat. Das erste ZimaBoard braucht diese Ebene gar nicht, dort läuft Docker direkt auf dem Betriebssystem.

Auf den beiden Proxmox-Nodes laufen LXC-Container statt vollwertiger VMs, auf jedem Node einer, beide unter NixOS. Für Dienste, die am Ende sowieso nur Docker starten, ist eine komplette VM Verschwendung, und gerade bei dieser Hardwareklasse zählt jedes eingesparte Gigabyte RAM. Docker in LXC ist nicht die Variante, die alle empfehlen, läuft bei mir aber seit Jahren stabil.

Die Hosts teilen sich in zwei Betriebssystem-Welten:

Gruppe Hosts
Debian jabasoft-zb, jabasoft-zb-02, jabasoft-pve-03, jabasoft-ug
NixOS jabasoft-nixos-lxc-01, jabasoft-nixos-lxc-11

Interessant ist die Mischung: Die beiden NixOS-Container sind bei sich selbst schon vollständig deklarativ, Betriebssystem, Pakete und Firewall liegen in einem Git-Repo. Ansible kümmert sich dort nicht um das System, sondern nur um die Ebene darüber, also die Docker-Workloads. Bei den Debian-Hosts macht Ansible etwas mehr. NixOS macht das, was NixOS besser kann, Ansible den Rest.

Ein Detail, das mir wichtig ist: Die drei Hosts, auf denen Docker-Dienste laufen, bilden eine eigene Inventory-Gruppe, die die Betriebssystem-Gruppen absichtlich kreuzt. Dienste landen dort, wo Platz und Ressourcen sind, nicht dort, wo ein bestimmtes Betriebssystem läuft.

Was da eigentlich läuft

Etwa 25 Dienste, alle als Docker-Compose-Stacks. Die interessantesten:

Infrastruktur und Zugriff

  • Forgejo – meine eigene Git-Forge inklusive Container-Registry. Meine selbstgebauten Images liegen unter forgejo.home.janbaer.de/jan/... und werden von dort direkt auf die Hosts gezogen. Kein Docker Hub, kein Rate-Limit, keine fremde Abhängigkeit.
  • nginx-proxy-manager – terminiert TLS und legt jeden Dienst unter einem eigenen Hostnamen ab (paperless.home.janbaer.de, vikunja.home.janbaer.de und so weiter).
  • Uptime Kuma und Beszel – Erreichbarkeits- und Host-Monitoring. Beszel läuft mit einem Agenten auf jedem Host.
  • ntfy – Push-Benachrichtigungen aufs Handy. Backups, Monitoring und n8n-Workflows melden sich alle dort.

Meine Daten

  • Seafile für Dateisynchronisation, Paperless-ngx für den kompletten Papierkram, Vaultwarden als Passwortmanager, Readeck als Read-it-later-Archiv, Vikunja für Aufgaben, dazu WebDAV und RustFS als S3-kompatibler Objektspeicher.

Automatisierung und KI

  • n8n für Workflows, unter anderem läuft darüber ein selbstgebautes Code-Review für meine Merge-Requests.
  • llama.cpp als CPU-only-Inferenzserver, hauptsächlich für Embeddings, dazu ein OpenAI-kompatibles Gateway und Odysseus, ein selbst gehosteter KI-Workspace. Odysseus ist ein gutes Beispiel dafür, wie so ein Stack in der Praxis aussieht: drei Container (App, Vektordatenbank, Websuche), aber nur die App veröffentlicht einen Port, die anderen zwei bleiben im internen Compose-Netzwerk.

Kleinkram, der überraschend oft nützlich ist

  • it-tools, Stirling PDF, MicroBin, MeTube. Alles Dinge, für die man sonst irgendeine Website mit fragwürdigem Datenschutz benutzt.

Und schließlich meine eigenen Projekte: HowCanI (meine Wissensdatenbank) und ein Worktime-Logger, beide in Bun geschrieben, beide als Image in der eigenen Registry.

Ein flaches Netz reicht nicht

Angefangen hat das mit dem Umzug in meine jetzige Wohnung. Seitdem ist die Zahl der IoT-Geräte im Netz Stück für Stück gewachsen, inzwischen sind es über zwanzig: Steckdosen, Sensoren, Lampen, Lautsprecher. Aus dem Job weiß ich ganz gut, wie es um diese Geräteklasse bestellt ist. Die Firmware wird selten gepatcht, oft nie, und einsehen kann man sie ohnehin nicht. Solche Geräte im selben Netz zu haben wie meinen Arbeitsrechner und meinen Passwortmanager, wollte ich nicht.

Genau das ist übrigens der häufigste Fehler im Heimnetz, und er passiert nicht an der Firewall nach draußen, sondern innen: Alles hängt in einem einzigen flachen Netz. Die smarte Steckdose mit ihrer Firmware von 2019 steht dann im selben Segment wie der Rechner, auf dem man arbeitet.

Die Fritzbox kann keine VLANs. Ich habe deshalb eine ganze Weile überlegt, welche Hardware das übernehmen soll, und bin bei einem UniFi-Router von Ubiquiti gelandet. Die Fritzbox ist seitdem nur noch das Modem am Kabelanschluss, die eigentliche Netzwerkarbeit macht der UniFi dahinter. Darauf laufen drei getrennte WLANs, jedes auf einem eigenen VLAN:

  • Office: die Geräte, mit denen ich tatsächlich arbeite.
  • IoT: Smart-Home-Geräte und Sensoren.
  • Sonstige Geräte: alles, was ins Internet darf, aber im Arbeitsnetz nichts verloren hat.

Die Regel zwischen den Segmenten ist bewusst einfach gehalten: IoT darf ins Internet, aber nicht ins Office-Netz. Die Isolation gilt also nur in eine Richtung, und das reicht völlig. Entscheidend ist dabei weniger die Anzahl der Netze als die Annahme dahinter: Ich gehe davon aus, dass IoT-Geräte kompromittiert sind. Nicht, weil ich weiß, dass sie es sind, sondern weil ich es nicht ausschließen kann. Ein übernommenes Gerät soll dann keinen Weg zu den Diensten finden, in denen meine Dokumente und Passwörter liegen.

Der Umbau selbst lief ohne Zwischenfälle, was ich fairerweise nicht der Hardware zuschreibe: Netzsegmentierung ist ziemlich genau das, was ich beruflich mache. Gedauert hat vor allem die Entscheidung, welcher Router es werden soll. Die Einrichtung im Controller war dann an einem Abend erledigt und kostet mich seitdem nichts mehr.

Im Alltag merke ich von der Trennung fast nichts. Die Geräte sind bei Alexa und Google Home registriert, gesteuert wird also über deren Apps, und die brauchen keine direkte Verbindung ins IoT-Netz. Einzig zum Einrichten eines neuen Geräts muss ich mit Tablet oder Handy kurz ins IoT-WLAN wechseln. Zweimal im Jahr dreißig Sekunden Umstand, dafür eine Grenze, die dauerhaft steht.

Gemessen am Aufwand ist das die wirksamste Maßnahme im ganzen Homelab.

Zugriff von außen: das VPN

Der wichtigste Punkt vorweg: Kein einziger Dienst meines Homelabs ist aus dem Internet erreichbar. Nach außen offen ist genau ein UDP-Port, der WireGuard-Endpunkt. Alles andere geht ausschließlich durch den Tunnel. Ein Dienst, der nicht öffentlich erreichbar ist, kann auch nicht von außen angegriffen werden, und Komfort kostet das praktisch keinen: Der Tunnel steht auf allen Geräten mit zwei Klicks.

Dafür braucht es erstaunlich wenig. Keinen Cloud-Reverse-Proxy, keinen VPS als Sprungbrett, keinen Tunnel-Dienst eines Drittanbieters, dem ich meinen Datenverkehr anvertrauen müsste. Drei Bausteine, von denen zwei sowieso schon im Haus stehen:

Der VPN-Server steckt im Router. Ich benutze einen Ubiquiti UniFi Express, und der bringt einen WireGuard-Server von Haus aus mit. Kein zusätzlicher Container, kein Dienst, den ich selbst patchen und überwachen muss. Für mich der eigentliche Vorteil: Der Fernzugriff hängt damit an keinem der Hosts, die ich per Ansible umbaue. Ich kann das komplette Homelab durchprovisionieren, ohne mir dabei den Weg nach draußen abzusägen.

Ein DynDNS-Name statt einer festen IP. Mein Vodafone-Anschluss hat eine echte, öffentliche IPv4-Adresse, aber keine statische. Damit die Clients trotzdem immer wissen, wohin sie sich verbinden sollen, läuft die Adresse bei ipv64.net auf einen festen Hostnamen. Ein deutscher DynDNS-Dienst, der genau das tut, was man an einem Privatanschluss braucht, inklusive automatischer Wildcard-Records und einer TTL, die kurz genug ist, dass ein Adresswechsel nicht wehtut.

Eine einzige Portfreigabe. Die Fritzbox reicht genau eine Freigabe weiter, den WireGuard-Port per UDP an den UniFi, der den Tunnel terminiert. Die Angriffsfläche ist damit ein einzelner UDP-Port, der auf ein falsches Paket nicht einmal antwortet. Das ist einer der Gründe, warum ich WireGuard einem offengelegten Reverse-Proxy vorziehe: Ein Port-Scan von außen sieht dort schlicht nichts.

Einen Tipp aus der Praxis gebe ich trotzdem mit, ohne konkrete Zahlen: Es lohnt sich, bei der Wahl des Ports kurz nachzudenken, statt einfach den Standard zu nehmen. In stark gefilterten Netzen kommt längst nicht jeder UDP-Port nach draußen. Wer den Port passend wählt, kann den Tunnel auch von dort aufbauen, wo sonst nichts durchgeht.

Vom Notebook, Tablet und Handy komme ich damit an alles: Paperless, Seafile, Vaultwarden, Vikunja und eben auch an meine eigenen Anwendungen wie HowCanI, genau so, als wäre ich zu Hause im Netz. Dafür brauche ich keinen einzigen externen Anbieter.

Eine Ausnahme gibt es: diese Homepage hier. Die soll ja jeder erreichen können, und sie läuft deshalb bewusst nicht im Homelab, sondern als statische Seite auf GitHub Pages. Öffentlich ist, was statisch und harmlos ist. Alles, wo Daten drinstecken, liegt zu Hause hinter dem Tunnel.

Alles ist Code: das Ansible-Projekt

Angefangen hat das nicht als Konzept, sondern aus Ärger. Solange nur ein Server mit ein paar Diensten lief, reichte eine Handvoll Compose-Dateien in einem Git-Repo völlig aus. Mit jedem weiteren Server kamen Kopien dazu, und irgendwann pflegte ich dieselbe Konfiguration an mehreren Stellen parallel und musste sie überall einzeln aktuell halten. Noch mehr gestört hat mich die Mischung: teils automatisiert deployt, teils zwischendurch von Hand auf dem Host geändert. Beruflich wäre mir das nicht durchgegangen, privat habe ich es mir eine Weile erlaubt.

Seitdem gilt bei mir eine Regel, an die ich mich ziemlich streng halte: Nichts wird auf dem Host manuell konfiguriert. Alles liegt in einem einzigen Ansible-Projekt, und der Alltag besteht aus genau einem Kommando:

./provision.sh                       # alles, auf allen Hosts
./provision.sh -t paperless-ngx      # nur diesen einen Dienst
./provision.sh -l nixos --check      # Dry-Run auf einer Gruppe

Der Kern dahinter ist eine einzige Idee: Es gibt nicht 25 Rollen für 25 Dienste, sondern eine generische Rolle, die einen Docker-Compose-Stack ausrollt. Die Unterschiede zwischen den Diensten sind reine Daten. Jeder Dienst ist ein Verzeichnis mit seinen Defaults und seinem Compose-Template, und jeder Host hat eine Liste, in der steht, was er davon ausführen soll:

services:
  paperless-ngx:
    enabled: true
  vaultwarden:
    enabled: true
  webdav:
    enabled: false

Ein neuer Dienst ist damit ein neues Verzeichnis und ein Boolean, kein neues Stück Ansible-Logik. Secrets liegen ansible-vault-verschlüsselt neben dem jeweiligen Dienst, das Vault-Passwort selbst liegt nirgends auf der Platte, sondern wird bei jedem Aufruf aus meinem Passwortmanager geholt.

Dieser Teil ist der, an dem ich am meisten Spaß hatte, und er füllt einen eigenen Artikel, inklusive der Frage, wie ein Host eine Einstellung überschreibt, ohne dass die Konfiguration doppelt gepflegt wird. Den Deep Dive gibt es deshalb separat: 25 Docker-Dienste, eine Ansible-Rolle.

Backup: zwei Stufen, zwei Orte

Ein Homelab ist erst dann eines, wenn man es wiederherstellen kann. Alles bisher Beschriebene, die Provisionierung, die Netztrennung, der Tunnel, schützt gegen Ausfall und Angriff. Gegen die wahrscheinlichsten Katastrophen, nämlich eine sterbende Platte, ein versehentliches rm oder einen Verschlüsselungstrojaner, hilft nur eines. Deshalb ist Backup für mich der wichtigste Teil des ganzen Setups.

Mein Konzept hat zwei Stufen:

Stufe 1: alles auf das NAS. Jeder Server sichert seinen Stand einmal täglich auf das NAS, meine Arbeitsrechner tun das stündlich. Das läuft über rsync, angestoßen von systemd-Timern, und die kommen passend zum Rest dieses Artikels aus der cron_jobs-Rolle im Ansible-Repository. Damit ein Host seinen Backup-Timer bekommt, gebe ich ihm in seinen Host-Variablen ein paar Zeilen YAML. Von Hand eingerichtet wird da nichts.

Stufe 2: das komplette NAS in die Cloud. Einmal täglich sichert sich das NAS als Ganzes mit BorgBackup in eine Storage Box bei Hetzner. Borg ist für diesen Zweck fast ideal: Es dedupliziert auf Blockebene, überträgt also nur das, was sich tatsächlich geändert hat, und es verschlüsselt clientseitig. Beim Hoster liegt damit ein Datenhaufen, mit dem niemand etwas anfangen kann, der Schlüssel verlässt mein Haus nie.

Damit liegen alle meine Daten immer an zwei voneinander unabhängigen Orten, und der zweite ist außer Haus. Ein Wasserschaden oder ein Einbruch nimmt mir zwar die Hardware, aber nicht die Daten.

Wichtig ist dabei die Aufbewahrung, denn ein Backup, das nur den letzten Stand kennt, repliziert einen Fehler bloß zuverlässig. Deshalb dünnt Borg die Archive gestaffelt aus:

  • Jeden Tag ein Backup, sieben Tage lang
  • Ein Backup pro Woche, vier Wochen lang
  • Ein Backup pro Monat, drei Monate lang

Ein Datenverlust, den ich erst nach zwei Wochen bemerke, die gelöschte Datei oder das kaputt migrierte Postfach, ist damit immer noch reparabel. Zusätzlich prüft Borg regelmäßig auf Integrität: wöchentlich das Repository selbst, monatlich die Archive.

Zurückgeholt habe ich aus diesem Backup auch schon etwas. Einmal bewusst als Test, weil ich wissen wollte, ob ich an ein Archiv bei Hetzner im Ernstfall überhaupt wieder herankomme, und einmal, weil ich tatsächlich etwas daraus gebraucht habe. Beides hat funktioniert. Das ist mir wichtig, denn ein Backup, das man noch nie zurückgespielt hat, ist nur eine Vermutung.

Was ehrlich noch fehlt

Ich mag es nicht, wenn solche Artikel nur die Hochglanzversion zeigen, also hier die offenen Punkte:

  • Der Restore-Test läuft nicht automatisch. Beruflich habe ich das anders gelöst: Dort wird jede Nacht ein Backup eingelesen und der Restore einzelner Dateien automatisch verifiziert. Zu Hause habe ich diesen Aufwand bisher gescheut und teste von Hand, wenn ich daran denke. Von allen Punkten auf dieser Liste stört mich der am meisten.
  • Einige Images laufen auf latest. Bei Diensten, wo ein kaputter Upstream-Tag mich abends eine Stunde kosten würde, pinne ich inzwischen, aber nicht überall konsequent.
  • Mein Smart Home hängt an fremden Clouds. Ich hoste Dokumente, Passwörter und Notizen selbst, steuere meine IoT-Geräte aber über Alexa und Google Home. Das ist der eine Widerspruch in diesem Setup, der mir bewusst ist, und der nächste Kandidat für einen Container im Lab.

Fazit

Wenn mich jemand fragt, was an diesem Setup das Wertvollste ist, dann ist es weder die Anzahl der Dienste noch die Hardware. Es ist, dass ich einen Host komplett neu aufsetzen und ihn mit einem Kommando wieder in den Zustand bringen kann, in dem er vorher war. Das macht den Unterschied zwischen einem Homelab, das man pflegt, und einem, vor dem man Angst hat.

Der Nebeneffekt ist nicht zu unterschätzen: Fast alles, was ich hier privat ausprobiere, Ansible-Patterns, deklarative Konfiguration, ein selbst gehosteter Registry-Workflow, wandert früher oder später in abgewandelter Form in meine Arbeit. Und umgekehrt genauso, die Netztrennung weiter oben kam direkt aus dem Job. Ein Homelab ist die günstigste Weiterbildung, die man bekommen kann.