My Home Lab
Home/Blog

My Home Lab

7 min read1265 words
InfrastructureKubernetesSelf-Hosted

A homelab is more than just servers in a closet - it's a playground for learning, a production environment for self-hosted services, and a way to take control of your own data. Here's a comprehensive tour of my setup.

For details on the physical machines, check out Homelab Hardware.

The Hardware

My cluster runs on compact, power-efficient mini PCs:

NodeRoleCPURAMPurpose
intel-c-firewallControl Plane4 cores8 GBKubernetes API, etcd (no workloads)
amd-w-minipcWorker16 cores13 GBPrimary workloads
intel-w-acemagicWorker4 cores16 GBStorage-heavy workloads

The intel-c-firewall node runs as a VM on Proxmox, hosted on a Glovary mini PC that also runs an OPNsense VM (firewall) and Pi-hole DNS. The other two nodes (amd-w-minipc and intel-w-acemagic) are bare metal mini PCs.

Total Resources: 24 CPU cores, ~35 GB RAM, ~2.1 TB storage

All nodes are connected via an unmanaged switch - no VLANs or fancy network segmentation, just simple flat networking that gets the job done.

The beauty of mini PCs is their power efficiency - the entire cluster runs on about 50W idle, making it practical to run 24/7 without destroying the electricity bill.

The Operating System: Talos Linux

Instead of traditional Linux distributions, I run Talos Linux - an immutable, API-managed operating system designed specifically for Kubernetes.

Why Talos?

  • Immutable: No SSH, no shell. The entire OS is read-only and managed via API
  • Secure: Minimal attack surface with only essential components
  • Declarative: Configuration is defined in YAML and applied via talosctl
  • Automatic updates: Rolling upgrades without downtime

Current versions:

  • Talos: v1.11.5
  • Kubernetes: v1.34.1
  • containerd: v2.1.5

GitOps with Flux

Everything in my cluster is managed through Git. I use Flux v2 for GitOps, which means:

  1. All manifests live in a Git repository
  2. Flux watches the repo and automatically applies changes
  3. Secrets are encrypted with SOPS + age, with some stored in 1Password
cluster/
├── apps/           # Application deployments
├── networking/     # Ingress, DNS, load balancing
├── storage/        # Longhorn configuration
├── cert-manager/   # TLS certificates
├── monitoring/     # Prometheus stack
└── flux-system/    # Flux controllers

When I want to deploy something new, I commit YAML to the repo and push. Flux handles the rest.

Networking Stack

Load Balancing: MetalLB

Since this is bare metal (no cloud load balancers), I use MetalLB in Layer 2 mode to assign external IPs to services:

  • IP Pool: 10.0.0.53-10.0.0.60
  • Ingress Controller: 10.0.0.54
  • Pi-hole DNS: 10.0.0.55

Ingress: nginx

All HTTP traffic flows through ingress-nginx running as a DaemonSet. Every service gets:

  • HTTPS with auto-provisioned Let's Encrypt certificates
  • A subdomain under *.eduuh.com
  • Proper headers and timeouts for large file uploads

DNS: Pi-hole + CoreDNS

I run a split DNS setup:

Client → Pi-hole (10.0.0.55) → CoreDNS (10.0.0.53) for *.eduuh.com
                             → Cloudflare (1.1.1.1) for public domains

Pi-hole blocks ads and tracking at the DNS level, while CoreDNS resolves internal services.

Storage: Longhorn

My homelab philosophy prioritizes data-recovery over reliability - services can go down, but data must be recoverable. Longhorn fits this perfectly, providing distributed block storage across the cluster:

  • Replication: 2-3 copies of each volume spread across nodes
  • Snapshots: Automated backups
  • Access modes: Both ReadWriteOnce and ReadWriteMany supported

This gives me resilience - if a node dies, the data is still available on other nodes. I still need to spend time learning Longhorn's periodic backup features for off-cluster disaster recovery.

What I Self-Host

Media Stack

The crown jewel of any homelab - a complete media management system:

All services share a 200GB volume with organized directories:

/media/
├── downloads/
├── tv/
└── movies/

This enables hardlinks - when Sonarr moves a completed download, it's instant with no extra disk space used.

Productivity

  • Immich: Self-hosted Google Photos replacement (100GB library)
  • Nextcloud: File sync and collaboration
  • Vaultwarden: Bitwarden-compatible password manager
  • n8n: Workflow automation platform
  • Memos: Lightweight note-taking

Utilities

Observability

You can't manage what you can't measure. My monitoring stack includes:

Prometheus + Grafana

The kube-prometheus-stack provides:

  • Prometheus for metrics collection (30-day retention)
  • Grafana for visualization
  • AlertManager for notifications
  • Pre-configured dashboards for Kubernetes metrics

Custom Exporters

  • OPNsense Exporter: Pulls metrics from my firewall (CPU, memory, interface traffic, WAN latency)
  • Speedtest Tracker: Hourly internet speed tests with historical data

I have custom Grafana dashboards showing:

  • Internet bandwidth usage
  • Download/upload speeds over time
  • Per-interface traffic on the firewall

The Service Map

ServiceURLPurpose
Jellyfinjellyfin.eduuh.comMedia streaming
qBittorrentqbittorrent.eduuh.comDownloads
Sonarrsonarr.eduuh.comTV automation
Radarrradarr.eduuh.comMovie automation
Prowlarrprowlarr.eduuh.comIndexers
Immichimages.eduuh.comPhotos
Nextcloudnextcloud.eduuh.comFiles
Vaultwardenbitwarden.eduuh.comPasswords
n8nn8n.eduuh.comAutomation
Memosmemos.eduuh.comNotes
Glanceglance.eduuh.comDashboard
Grafanagrafana.eduuh.comMetrics
Pi-holepihole.eduuh.comDNS admin
Longhornlonghorn.eduuh.comStorage UI

Lessons Learned

Start simple, iterate. My first attempt was over-engineered with Ansible, Terraform, and multiple VMs. The current setup with Talos + Flux is far simpler and more reliable.

GitOps is worth it. Having everything in Git means I can rebuild the entire cluster from scratch. When things break, git log shows exactly what changed.

Shared storage matters. The media stack only works smoothly because all services see the same filesystem. Planning storage architecture upfront saves pain later.

Monitoring from day one. Adding observability after the fact is painful. Bake it in from the start.

Data-recovery over reliability. It's just me and my wife using these services - if something goes down, it's not the end of the world. What matters is that data can be recovered. This mindset simplifies infrastructure decisions significantly.

Hardware Roadmap

The current storage setup works, but there's room to grow:

  • NAS: A dedicated NAS for large-scale storage and off-cluster backups
  • SSD upgrades: 2x 4TB 2.5" SSDs available for expanding cluster storage
  • OS storage: 1TB dedicated for OS-level operations
  • Jellyfin node: An old laptop with Intel Core i7 (8th gen) would be ideal for Jellyfin - plenty of compute for hardware transcoding
  • Repurpose intel-w-acemagic: This node has low compute power, so I'm planning to replace it with the laptop and find a new role for it

This would separate bulk media storage from application data, improving both performance and backup strategies. With more storage capacity, I could also explore self-hosting smart home camera feeds.

What's Next

  • Learning more about homelabbing and infrastructure patterns
  • Hardware transcoding for Jellyfin (Intel QuickSync)
  • Automated backups to off-site storage
  • Home Assistant for smart home integration
  • More automation with n8n workflows

The homelab is never "done" - and that's the fun of it.

📝 I'll be writing more in-depth posts about each service as I learn and refine my setup.

Last updated on January 13th, 2026