Skip to content

pkr-lab/capulus-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

220 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

capulus-core — GitOps Home Lab on k3s, ArgoCD, Tailscale

Ubuntu  k3s  ArgoCD  Tailscale  Ansible

Lizenz  GitOps  Self-hosted  Single Node


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



⚡ TL;DR

# 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-pass

Am Ende druckt das Playbook die ArgoCD-URL und das Admin-Passwort. Fertig.


Was du bekommst

Schicht Komponente Hinweis
BetriebssystemUbuntu Server 26.04 LTSGehärtet, UFW-Firewall, NTP-synced, Swap off
Kubernetesk3s (latest stable)Single-Node, Traefik, CoreDNS, local-path, metrics-server
GitOpsArgoCD + ApplicationSetsVerzeichnis unter argocd/apps/ anlegen → pushen → deployed
Split-DNSdnsmasq auf tailscale0*.homeserver aus LAN und Tailnet auflösbar
Web-AnsibleSemaphore UIEin-Klick-git pull && ansible-playbook gegen das eigene LAN
MonitoringVictoriaMetrics + GrafanaSingle-Node TSDB, vmagent, vmalert, Alertmanager, Dashboards
Kubernetes-UIHeadlampBrowser-Dashboard für den Cluster
SecretsSealed Secrets + kubeseal-webguiVerschlüsselte Secrets in Git, nur im Cluster entschlüsselbar
NotificationsGotify + ntfySelf-hosted Push — Gotify (Android), ntfy (iOS + Android)
Remote-AccessTailscaleWireGuard-Mesh-VPN — keine Portfreigaben, keine öffentliche IP
CI/CD internArgo Workflows + MinIOPrivate CI/CD-Pipeline + S3-Artifact-Store im Cluster
IngressTraefik v2 (k3s bundled)HTTP/HTTPS-Routing in den Cluster
SSOAuthentikZentraler Identity Provider für alle Dienste via OIDC
ProvisioningAnsible (≥ 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.


Quickstart (5 Schritte)

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

2. 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-pass

Ergebnis:

ArgoCD UI:  http://<server-ip>:30080
Username:   admin
Password:   <auto-generiert>

Repository-Layout

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

Monitoring

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; echo

Application hinzufügen (GitOps-Weg)

mkdir -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 push

Innerhalb von ~3 Minuten erkennt ArgoCD das neue Verzeichnis, erstellt eine Application namens my-app im Namespace my-app und synct sie. Details: docs/05-argocd.md


Service-URLs

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

Networking & Security

PrinzipUmsetzung
Keine öffentlichen PortsZugriff ausschließlich über LAN oder Tailscale-VPN
UFW-FirewallErlaubt nur SSH, HTTP/HTTPS, k3s-API, ArgoCD-NodePort, Flannel, Tailscale-UDP
Ansible-VaultSensitive Secrets verschlüsselt at rest
ArgoCD Read-onlyHat 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


Dokumentation

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

About

Fully automated, GitOps-driven single-node home server on k3s, ArgoCD & Tailscale — one Ansible run, zero open ports.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors