homelab
Infrastructure-as-Code for a 3-machine homelab running K3s.
Status
| Phase |
Description |
Status |
| 0 |
Backup configs, init repo |
✅ Done |
| 1 |
Bootstrap Minisforum — K3s server + Traefik |
✅ Done |
| 2 |
Join Debian as K3s agent, SMB setup |
⏳ Next |
| 3 |
Deploy core infra — Gitea, Pi-hole, DDNS |
🔧 In progress |
| 4 |
Deploy app services — Jellyfin, qBittorrent, JDownloader, Dashy, Glances |
🔜 Planned |
| 5 |
Networking cutover — router, Traefik ingress, DNS |
🔜 Planned |
| 6 |
Cleanup legacy Debian services |
🔜 Planned |
Architecture
| Machine |
IP |
SSH Port |
Role |
Status |
| Minisforum UM780 XTX |
192.168.7.77 |
430 |
K3s server, main gateway |
✅ Running — K3s + Traefik |
| Debian Server (HP ProDesk) |
TBD |
— |
K3s agent, SMB storage |
⏳ Phase 2 |
| Mac Mini M2 |
TBD |
— |
Standalone (outside cluster) |
⏳ Phase 3+ |
Internal Services (Minisforum)
| Service |
URL |
Notes |
| Traefik |
— |
Ingress controller, Let's Encrypt |
| Authentik |
https://authentik.home.arpa |
SSO/identity provider |
| Gitea |
https://gitea.home.arpa |
Git + Docker registry, SSH on port 2222 |
| Pi-hole |
https://pihole.home.arpa/admin |
Primary DNS, resolves *.home.arpa → 192.168.7.77 |
| Grafana |
https://grafana.home.arpa |
Monitoring dashboards (kube-prometheus-stack) |
| Jellyfin |
https://jellyfin.home.arpa |
Media server |
| qBittorrent |
https://qbittorrent.home.arpa |
Torrent client |
| JDownloader |
https://jdownloader.home.arpa |
Download manager |
| Dashy |
https://dashy.home.arpa |
Dashboard |
| Glances |
https://glances.home.arpa |
System monitoring |
Repo Structure
ansible/
inventory.yaml # host definitions
playbooks/
bootstrap-minisforum.yaml # OS hardening, packages, UFW, /data dirs
deploy-watch-party.yaml # deploy watch-party app
join-debian-agent.yaml # join Debian as K3s agent
setup-gitea-runner.yaml # set up Gitea Actions runner
setup-glances-debian.yaml # deploy Glances on Debian host
setup-k3s.yaml # K3s server install, Helm, kubeconfig
setup-monitoring.yaml # deploy monitoring stack
setup-nfs-debian.yaml # configure NFS server on Debian
roles/
common/ # user, SSH hardening, UFW, base packages
gitea-runner/ # Gitea Actions runner setup
glances/ # Glances system monitor
k3s-agent/ # K3s agent node join
k3s-server/ # K3s server install + Helm
monitoring/ # Prometheus/Grafana monitoring
nfs-server/ # NFS server configuration
watch-party/ # Watch-party app deployment
config/
dashy/conf.yaml # Dashy dashboard config
manifests/
authentik/ # Authentik ingress, middleware, proxy outpost, secrets
cert-manager/ # ClusterIssuers and porkbun-secret.sh
core/ # Dashy, Glances, CA installer, apply-dashy-config.sh
gitea/ # Gitea PV, runner, backup, runner secret
media/ # Jellyfin, qBittorrent, JDownloader
monitoring/ # Grafana/Loki datasource, PVs, grafana-secret.sh
network/ # DDNS, Traefik dashboard, ingress routes, pihole patch
values/
authentik.yaml # Authentik SSO
cert-manager.yaml # cert-manager
gitea.yaml # Gitea
kube-prometheus-stack.yaml # Prometheus + Grafana
loki-stack.yaml # Loki log aggregation
pihole.yaml # Pi-hole (Minisforum)
pihole-debian.yaml # Pi-hole (Debian)
traefik.yaml # Traefik ingress controller
Prerequisites
- Ansible installed on your workstation:
pip install ansible
- Ansible collections:
ansible-galaxy collection install community.general ansible.posix
- SSH key at
~/.ssh/id_ed25519-nik-macbookair
Connecting
# SSH
ssh minisforum # port 430, configured via ~/.ssh/config
# Kubectl (after fetching kubeconfig)
export KUBECONFIG=/tmp/k3s-minisforum.yaml
kubectl get nodes
kubectl get pods -A
Deploying / Re-deploying
# Re-run bootstrap (idempotent)
ansible-playbook -i ansible/inventory.yaml ansible/playbooks/bootstrap-minisforum.yaml
# Re-run K3s setup (idempotent)
ansible-playbook -i ansible/inventory.yaml ansible/playbooks/setup-k3s.yaml
# Traefik
helm repo add traefik https://helm.traefik.io/traefik && helm repo update
helm upgrade --install traefik traefik/traefik \
--namespace traefik --create-namespace \
-f values/traefik.yaml
# Gitea
helm repo add gitea-charts https://dl.gitea.com/charts/ && helm repo update
helm upgrade --install gitea gitea-charts/gitea \
--namespace gitea --create-namespace \
-f values/gitea.yaml
# Pi-hole
helm repo add mojo2600 https://mojo2600.github.io/pihole-kubernetes/ && helm repo update
helm upgrade --install pihole mojo2600/pihole \
--namespace pihole --create-namespace \
-f values/pihole.yaml
# cert-manager
helm repo add jetstack https://charts.jetstack.io && helm repo update
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
-f values/cert-manager.yaml
# Authentik
helm repo add authentik https://charts.goauthentik.io && helm repo update
helm upgrade --install authentik authentik/authentik \
--namespace authentik --create-namespace \
-f values/authentik.yaml
# kube-prometheus-stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts && helm repo update
helm upgrade --install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace \
-f values/kube-prometheus-stack.yaml
# Loki
helm repo add grafana https://grafana.github.io/helm-charts && helm repo update
helm upgrade --install loki grafana/loki-stack \
--namespace monitoring --create-namespace \
-f values/loki-stack.yaml