Architecture

Every layer of the homelab is described in git and applied by a pipeline. A push is the only way changes reach the machines.

The layers

Layer Tool Repo
Hypervisor Proxmox VE, 3 nodes —
Provisioning OpenTofu (bpg/proxmox) homelab_terraform
Configuration Ansible homelab_ansible
Cluster k3s + kube-vip homelab_k3s
Workloads ArgoCD + Kustomize homelab_kube-apps
Dependencies Renovate renovate-config

Source control and CI run on Gitea with Gitea Actions. Runners live both on a VM and inside the k3s cluster.

Adding a VM

  1. Add an entry to a .tfvars file: size, Proxmox node, template and tags.
  2. Push. The workflow runs tofu plan and tofu apply in the matching workspace. State is stored in a self-hosted Garage S3 bucket.
  3. OpenTofu also creates a DNS rewrite in AdGuard Home for the new VM.
  4. For new VMs only, the pipeline waits for SSH and runs the Ansible site playbook against them.

Proxmox tags become Ansible groups through the dynamic inventory, so a tag decides which roles a VM gets. Hosts that were never created by OpenTofu sit in a small static inventory next to it.

Configuration

Each Ansible role has its own Gitea Actions workflow, triggered by changes to the role or its group variables. A daily run applies the base roles (common, node_exporter, alloy) to the whole fleet to catch drift.

The cluster

k3s runs on nine VMs spread over three Proxmox nodes:

  • 3 control plane nodes behind a kube-vip virtual IP
  • 3 worker nodes
  • 3 storage nodes running Longhorn

The bundled servicelb and Traefik are disabled. kube-vip handles LoadBalancer services, and Traefik is installed through ArgoCD with my own values. See GitOps for how workloads get deployed.

Outside the cluster

Some services run on dedicated VMs, configured by Ansible:

  • Gitea + Jenkins: source control and CI
  • OpenBao: 3-node secrets cluster, see Secrets
  • Garage: 3-node S3 storage for OpenTofu state and database backups
  • Prometheus, Grafana, Loki, Alertmanager: see Monitoring
  • Media server and Home Assistant

A Synology NAS stores the backups. A Raspberry Pi acts as bastion host and VPN entry point.