Vollständig automatisierter, GitOps-getriebener Home-Server auf einer einzigen Maschine.
Ein einziger Ansible-Run liefert einen gehärteten Ubuntu-Host, einen schlanken Kubernetes-Cluster (k3s), Continuous Delivery aus Git (ArgoCD) und Zero-Config-Remote-Access (Tailscale).
# 1) Repo klonen
git clone https://github.com/pkr-lab/capulus-core.git && cd capulus-core
# 2) Eigene Details eintragen (Server-IP, Repo-URL, Tailscale-Key)
$EDITOR ansible/inventory/hosts.yml
$EDITOR ansible/group_vars/all.yml
# 3) Collections installieren und Playbook laufen lassen
make install
# oder:
# ansible-galaxy collection install -r ansible/requirements.yml
# ansible-playbook -i ansible/inventory/hosts.yml ansible/site.yml --ask-vault-passAm Ende druckt das Playbook die ArgoCD-URL und das Admin-Passwort. Fertig.
| Schicht | Komponente | Hinweis |
|---|---|---|
| Betriebssystem | Ubuntu Server 26.04 LTS | Gehärtet, UFW-Firewall, NTP-synced, Swap off |
| Kubernetes | k3s (latest stable) | Single-Node, Traefik, CoreDNS, local-path, metrics-server |
| GitOps | ArgoCD + ApplicationSets | Verzeichnis unter argocd/apps/ anlegen → pushen → deployed |
| Split-DNS | dnsmasq auf tailscale0 | *.homeserver aus LAN und Tailnet auflösbar |
| Web-Ansible | Semaphore UI | Ein-Klick-git pull && ansible-playbook gegen das eigene LAN |
| Monitoring | VictoriaMetrics + Grafana | Single-Node TSDB, vmagent, vmalert, Alertmanager, Dashboards |
| Kubernetes-UI | Headlamp | Browser-Dashboard für den Cluster |
| Secrets | Sealed Secrets + kubeseal-webgui | Verschlüsselte Secrets in Git, nur im Cluster entschlüsselbar |
| Notifications | Gotify + ntfy | Self-hosted Push — Gotify (Android), ntfy (iOS + Android) |
| Remote-Access | Tailscale | WireGuard-Mesh-VPN — keine Portfreigaben, keine öffentliche IP |
| CI/CD intern | Argo Workflows + MinIO | Private CI/CD-Pipeline + S3-Artifact-Store im Cluster |
| Ingress | Traefik v2 (k3s bundled) | HTTP/HTTPS-Routing in den Cluster |
| SSO | Authentik | Zentraler Identity Provider für alle Dienste via OIDC |
| Provisioning | Ansible (≥ 2.14) | Vollständig idempotent, Role-per-Concern, Vault für Secrets |
Ziel-Hardware: kleine Box mit ≥ 4 GB RAM und ≥ 20 GB Disk. Referenz-Build: Intel i5, 32 GB RAM, 512 GB NVMe.
Auto-Upgrade-Details
auto_upgrade: true (Default) hält bei jedem Playbook-Run den gesamten Stack aktuell:
| Komponente | Mechanismus |
|---|---|
| APT-Pakete | apt dist-upgrade + unattended-upgrades für tägliche Sicherheits-Patches |
| Tailscale | state: latest für das tailscale-Paket |
| k3s | Folgt k3s_channel (Default stable), pin via k3s_version |
| Helm | Re-Run des offiziellen Installers bei neuem Release |
| ArgoCD | helm upgrade --install ohne --version, pin via argocd_version |
| Reboot | Auto-Reboot wenn APT /var/run/reboot-required setzt (togglebar via auto_reboot_if_required) |
Für reproduzierbare Builds: auto_upgrade: false in ansible/group_vars/all.yml.
Erstmalig auf der Maschine? Start mit Ubuntu-Server-Installation. Komplette Voraussetzungen: docs/02-prerequisites.md.
Schritt-für-Schritt aufklappen
1. Repo klonen
git clone https://github.com/pkr-lab/capulus-core.git
cd capulus-core2. Inventory auf den eigenen Server zeigen
$EDITOR ansible/inventory/hosts.yml
# ansible_host (Server-IP) und ggf. ansible_ssh_private_key_file anpassen.3. Variablen setzen
$EDITOR ansible/group_vars/all.yml
# Pflicht: argocd_repo_url, local_subnet, timezone.
# Tailscale-Key muss vault-encrypted sein (nächster Schritt).4. Tailscale-Auth-Key verschlüsseln
ansible-vault encrypt_string 'tskey-auth-DEIN_KEY' --name 'tailscale_auth_key'
# Den !vault-Block in all.yml über den bestehenden tailscale_auth_key-Wert pasten.5. Playbook ausführen
make install
# oder ohne make:
ansible-galaxy collection install -r ansible/requirements.yml
ansible-playbook -i ansible/inventory/hosts.yml ansible/site.yml --ask-vault-passErgebnis:
ArgoCD UI: http://<server-ip>:30080
Username: admin
Password: <auto-generiert>
Verzeichnisstruktur anzeigen
capulus-core/
├── README.md
├── Makefile # Convenience-Targets: install, lint, ping, check, …
├── docs/
│ ├── 00-ubuntu-server-install.md # Bare-Metal-Ubuntu-Installation
│ ├── 01-overview.md # Architektur-Diagramme
│ ├── 02-prerequisites.md # Voraussetzungen & Pre-flight
│ ├── 03-installation.md # Step-by-Step-Setup
│ ├── 04-k3s.md # k3s + kubectl-Referenz
│ ├── 05-argocd.md # GitOps-Nutzung
│ ├── 06-tailscale.md # VPN-Setup
│ ├── 07-troubleshooting.md # Häufige Probleme
│ ├── 08-semaphore.md # Semaphore-Web-UI für Ansible
│ ├── 09-dns-architecture.md # Split-DNS-Design & Ausfallsicherheit
│ ├── 10-gotify.md # Push-Notifications via Gotify
│ ├── 11-ntfy.md # iOS Push-Notifications via ntfy
│ ├── 12-argo-workflows.md # Private CI/CD mit Argo Workflows + MinIO
│ ├── 13-sso-authentik.md # Single-Sign-On via Authentik
│ ├── 14-cert-login.md # Zertifikats-Authentifizierung via Traefik mTLS
│ ├── 15-sso-alle-dienste.md # SSO-Konfiguration für alle Dienste
│ ├── 16-hdd-storage.md # HDD-StorageClass auf worker-0
│ ├── 17-zammad.md # Zammad Helpdesk/Ticket-System
│ ├── 18-windows-deployment.md # Windows-PC-Deployment (PXE/USB/Ansible)
│ └── assets/banner.svg
├── ansible/
│ ├── site.yml # Entry-Point
│ ├── requirements.yml # Galaxy-Collections
│ ├── ansible.cfg # Defaults
│ ├── inventory/hosts.yml # Eigener Server (+ semaphore_targets)
│ ├── group_vars/all.yml # Alle Knobs (vault-verschlüsselte Secrets)
│ └── roles/
│ ├── common/ # Base-OS, Firewall, Pakete
│ ├── dnsmasq/ # Split-DNS für *.homeserver
│ ├── tailscale/ # VPN (WireGuard-Mesh)
│ ├── k3s/ # Kubernetes Control-Plane + Helm
│ ├── k3s_agent/ # Kubernetes Worker-Node
│ ├── argocd/ # GitOps-Controller via Helm
│ ├── semaphore_secrets/ # Bootstrap-Secret für den Semaphore-Pod
│ ├── semaphore_targets/ # SSH-Pubkey auf Managed-Hosts pushen
│ └── semaphore_bootstrap/ # Projects/Inventories/Templates per API
└── argocd/
├── bootstrap/root-applicationset.yaml # Erkennt jedes Verzeichnis darunter
└── apps/ # Ein Ordner pro ArgoCD-Application
├── example-whoami/
├── gotify/ # Push-Notifications (Android)
├── gotify-bridge/ # Alertmanager → Gotify Webhook-Bridge
├── ntfy/ # Push-Notifications (iOS + Android)
├── ntfy-bridge/ # Alertmanager → ntfy Webhook-Bridge
├── headlamp/ # Kubernetes-Web-Dashboard
├── kubeseal-webgui/ # Sealed-Secrets-Verschlüsselungs-UI
├── monitoring/ # VictoriaMetrics + Grafana
├── argo-workflows/ # Private CI/CD-Pipeline
├── minio/ # S3-Artifact-Store für Argo Workflows
├── coredns-custom/ # Zusätzliche CoreDNS-Zonen
├── sealed-secrets/ # SealedSecrets-Controller
├── authentik/ # Authentik Single-Sign-On
└── semaphore/ # Ansible-Web-UI
Ein schlanker VictoriaMetrics-+-Grafana-Stack lebt unter argocd/apps/monitoring/ und wird automatisch von ArgoCD ausgerollt.
Stack-Details
| Komponente | Detail |
|---|---|
| TSDB | VMSingle — 15 Tage Retention, 10 Gi local-path-PVC |
| Scrapers | VMAgent scrapet alle VMServiceScrape/VMPodScrape + Prometheus ServiceMonitor-CRDs |
| Host-Metriken | prometheus-node-exporter als DaemonSet auf dem Ubuntu-Host |
| Cluster-Metriken | kubelet/cAdvisor, kube-apiserver, kube-state-metrics, CoreDNS |
| Alerts | Default-kube-prometheus-Rules; Gotify- und ntfy-Alertmanager-Bridges |
| Dashboards | Node Exporter Full, VictoriaMetrics + Kubernetes Views von grafana.com |
Grafana öffnen unter http://grafana.homeserver — Admin-Passwort abfragen:
kubectl -n monitoring get secret monitoring-grafana \
-o jsonpath='{.data.admin-password}' | base64 -d; echomkdir -p argocd/apps/my-app
# Plain Kubernetes-YAML, kustomization.yaml oder ein Helm-Chart hineinlegen.
git add argocd/apps/my-app && git commit -m "feat(apps): add my-app" && git pushInnerhalb von ~3 Minuten erkennt ArgoCD das neue Verzeichnis, erstellt eine
Applicationnamensmy-appim Namespacemy-appund synct sie. Details: docs/05-argocd.md
| Service | URL |
|---|---|
| Grafana | http://grafana.homeserver |
| ArgoCD | http://<server-ip>:30080 |
| Headlamp | http://headlamp.homeserver |
| Semaphore | http://semaphore.homeserver |
| Authentik | http://authentik.homeserver |
| Gotify | http://gotify.homeserver |
| ntfy | http://ntfy.homeserver |
| Argo Workflows | http://argo-workflows.homeserver |
| MinIO Console | http://minio.homeserver |
| kubeseal-webgui | http://kubeseal-webgui.homeserver |
| Prinzip | Umsetzung |
|---|---|
| Keine öffentlichen Ports | Zugriff ausschließlich über LAN oder Tailscale-VPN |
| UFW-Firewall | Erlaubt nur SSH, HTTP/HTTPS, k3s-API, ArgoCD-NodePort, Flannel, Tailscale-UDP |
| Ansible-Vault | Sensitive Secrets verschlüsselt at rest |
| ArgoCD Read-only | Hat ausschließlich Read-Access auf das Git-Repo |
Firewall-Ports
| Port | Protokoll | Scope | Zweck |
|---|---|---|---|
| 22 | TCP | LAN + Tailnet | SSH |
| 53 | UDP+TCP | LAN + Tailnet | dnsmasq Split-DNS für *.homeserver |
| 80 | TCP | LAN + Tailnet | Traefik HTTP |
| 443 | TCP | LAN + Tailnet | Traefik HTTPS |
| 6443 | TCP | LAN + Tailnet | k3s-API |
| 30080 | TCP | LAN + Tailnet | ArgoCD-UI (HTTP) |
| 30443 | TCP | LAN + Tailnet | ArgoCD-UI (HTTPS) |
| 41641 | UDP | Internet | Tailscale-WireGuard |
Vollständige Architektur: docs/01-overview.md
| Dokument | Inhalt |
|---|---|
| Ubuntu-Server-Installation | ISO, USB-Stick, Installer, erster Boot |
| Architektur-Überblick | Komponenten und Traffic-Flows |
| Voraussetzungen | Was vor dem Ansible-Run nötig ist |
| Installationsleitfaden | Vollständiger Step-by-Step-Walkthrough |
| k3s-Referenz | Config, kubectl-Cheatsheet, Upgrades |
| ArgoCD-GitOps | App-Workflow, CLI, Sync-Policies |
| Tailscale-VPN | Auth-Keys, MagicDNS, Subnet-Routes |
| Troubleshooting | Diagnose-Playbook für häufige Probleme |
| Semaphore-UI | Web-UI zum Ausführen von Playbooks |
| DNS-Architektur | Warum der Home-Server NICHT dein LAN-DNS ist |
| Gotify-Push | Self-hosted Push-Notifications aus dem Stack |
| ntfy iOS-Push | Self-hosted ntfy mit iOS APNs-Relay |
| Argo Workflows | Private CI/CD-Pipeline mit MinIO-Artifact-Store |
| SSO via Authentik | Authentik als zentraler Identity Provider |
| Zertifikats-Auth | Traefik mTLS Client-Zertifikate |
| SSO alle Dienste | Headlamp, Argo Workflows, MinIO via OIDC |
| HDD-Storage | StorageClass hdd auf worker-0 für große Datenmengen |
| Zammad Helpdesk | Ticket-System mit optionalem SAML-SSO |
| Windows-PC Deployment | Automatisierte Windows-Einrichtung per PXE/USB/Ansible |
MIT — siehe LICENSE · Made with ☕ & GitOps