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
Description
No description provided
Readme 220 KiB
Languages
HTML 78.3%
Shell 20.5%
Jinja 1.2%