- Shell 59.7%
- HCL 31.1%
- Go Template 8.9%
- Dockerfile 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .vibe | ||
| docker | ||
| helm-charts | ||
| proxmox | ||
| sat-receiver | ||
| scratches | ||
| scripts | ||
| .gitignore | ||
| CLAUDE.md | ||
| DEVICES.md | ||
| LICENSE | ||
| README.md | ||
| renovate.json | ||
homelab
Infrastructure, configuration, and operational scripts for my personal homelab. Public so it can serve as a working reference.
What runs here
A two-node Proxmox VE cluster (pve0, pve1). The physical hardware (these nodes, router, switch, sat box, Zigbee/Matter coordinator) is listed in DEVICES.md. On top of it:
- Talos Linux Kubernetes cluster — 1 control plane and 2 workers (one worker on each Proxmox node), dual-stack IPv4/IPv6, TPM-backed disk encryption, secure boot, Longhorn for distributed block storage. Bootstrapped end-to-end by OpenTofu (see
proxmox/talos-cluster/); day-2 driven by FluxCD against the Flux repo. - TrueNAS Scale VM — NVMe drives passed through directly. Runs Restic backups to a Hetzner Storage Box over SFTP; backup health is monitored from the host with Telegram alerts (see
proxmox/truenas/resticprofile/). - Gaming VMs — separate Linux VMs with GPU passthrough for Bazzite / CachyOS. Not part of the cluster.
- Sat receiver — Enigma2 / OSCam config for an ORF P410 smartcard. Reference docs only; it runs on a dedicated box.
- arr-stack — media acquisition and serving (arr apps, usenet, music) behind a Gluetun VPN container. Runs as
docker composeon TrueNAS (seedocker/compose/arr-stack/), not in Kubernetes. - Garage — self-hosted S3,
docker composeon TrueNAS (seedocker/compose/garage/). The S3 API is consumed by the cluster for CloudNativePG backups and Longhorn. Runs on the host, not in Kubernetes. - OpenBao — self-hosted secret store,
docker composeon TrueNAS (seedocker/compose/openbao/). The cluster's external-secrets operator pulls Kubernetes secrets from it. Runs on the host, not in Kubernetes. - Forgejo — self-hosted git forge,
docker composeon TrueNAS (seedocker/compose/forgejo/). Intended to host the Flux GitOps repo (currently on Codeberg). Runs on the host, not in Kubernetes. - Single-purpose LXCs / VM on Proxmox — Technitium DNS, Traefik (for services that live outside the cluster), Jellyfin, and Home Assistant OS. All installed via the Proxmox VE community helper scripts; the per-directory READMEs under
proxmox/record which script was used.
Inside the cluster, broadly: Linkerd for the mesh, Traefik for ingress, MetalLB for L2 LB, CloudNativePG and Longhorn for stateful workloads, Authentik for SSO, external-secrets syncing secrets from OpenBao, plus self-hosted apps (Immich, Paperless, etc.). The full list and reconciled state live in the Flux repo.
This repo vs. the Flux repo
Two repos, clean split:
- This repo (
homelab): infrastructure that has to exist before the cluster is reconcilable — Proxmox VM definitions (OpenTofu), Talos config, the cluster bootstrap, Helm chart sources I maintain, scripts, and host-level configs (TrueNAS backups, sat receiver, etc.). - Flux repo: everything inside the cluster — namespaces, HelmReleases that consume the charts published from this repo, network policies, app-level config. That repo is what FluxCD reconciles.
The bootstrap module here installs FluxCD and points it at the Flux repo; from then on, day-2 changes happen in the Flux repo.
Layout
proxmox/ Proxmox-side infra
talos-cluster/ OpenTofu config that builds the whole K8s cluster end-to-end
truenas/ TrueNAS VM + Restic backup monitoring (runs on TrueNAS)
gaming-vm/ Standalone gaming VMs (Bazzite, CachyOS) with GPU passthrough
pci-passthrough/ NVMe passthrough setup notes
wakeonlan/ Systemd unit to enable WoL on Proxmox nodes
technitium-dns/ Technitium DNS LXC (community helper script)
traefik-pve/ Traefik LXC for non-cluster services (community helper script)
jellyfin/ Jellyfin LXC (community helper script)
homeassistant/ Home Assistant OS VM (community helper script)
helm-charts/ Helm charts I maintain, published to a private OCI registry
docker/
build/ Custom container images built from this repo
compose/ docker-compose stacks running on hosts directly
scripts/ Day-2 operational scripts (Talos upgrades, rsync, yt-dlp, etc.)
sat-receiver/ OSCam config for an Enigma2 satellite receiver
Each directory has its own README with the details.
Dependency updates (Terraform providers, Helm releases) are raised automatically as PRs by Renovate (renovate.json).
On AI assistance
I use AI as a research and coding tool. The boring stuff — boilerplate YAML, looking up CLI flags, repetitive Terraform, formatting tables, and documentation (this README included) — is AI-assisted. I hate writing docs and basically never had any until AI made it cheap enough to bother. Architecture choices, the stack, debugging when things break, anything operational, and every load-bearing decision in here are mine. If something works well, I picked it on purpose. If something is wrong, that's also on me.
I'm calling it out because it's the honest thing to do.
Caveats
- It's a homelab. Things are configured for this hardware: specific GPU model, specific NVMe layout, specific network. Cloning this won't give you a working cluster.
- Some directories assume host-side state that isn't (and shouldn't be) tracked here —
.envrcfiles only containop://references, real secret material lives in 1Password. - Talos and Kubernetes versions are pinned in
proxmox/talos-cluster/talos-schematics.mdand the upgrade scripts. They drift; expect to update them.
License
MIT — see LICENSE. Lift whatever's useful, no permission needed.
Contact
matthias@webmatix.dev — or find me on Codeberg at @webmatix.