Featured image of post Terraform-Driven Homelab Architecture

Terraform-Driven Homelab Architecture

A mature Terraform architecture for homelab: module hierarchy, design principles, and production clusters.

The Problem Space

Homelabs evolve. You start with one Docker container, add some LXCs, then Kubernetes, and suddenly your infrastructure is a house of cards held together by scripts you wrote two years ago and don’t remember.

This architecture solves that through:

  1. Everything in code — from VM provisioning to Kubernetes bootstrap
  2. Versioned modules — each update is a code review opportunity
  3. Self-service via Backstage — templated provisioning, no Slack threads

Numbers: 3 Proxmox nodes, 2 production clusters (Docker Swarm + Talos K8s), ~50 resources defined across 24+ YAML configurations.

Running in production:

  • 3 Proxmox nodes (alpha, charlie, foxtrot)
  • Docker Swarm clusters with Keepalived HA
  • Talos Kubernetes clusters with Flux GitOps
  • GPU passthrough for hardware acceleration
  • Multi-network topology (dmz + vmbr1)
  • Private container registry (Harbor)
  • Private Terraform registry (Cloudflare Workers)
Start with the basic template. All custom modules derive from it — maintaining consistency across the infrastructure.

Module Hierarchy

  graph TB
    subgraph "Root Module"
        A[tf-infra-homelab]
    end
    
    subgraph "Compute Modules"
        B[tf-module-proxmox-lxc]
        C[tf-module-proxmox-vm]
        D[tf-module-proxmox-talos]
        E[tf-module-proxmox-docker]
    end
    
    subgraph "Application Layer"
        F[applications-homelab]
    end
    
    subgraph "Platform"
        G[Proxmox VE]
    end
    
    A --> B
    A --> C
    A --> D
    A --> E
    D --> F
    E --> F
    B --> G
    C --> G
    D --> G
    E --> G
Module Purpose
terraform-basic-template Foundation for all modules
tf-module-proxmox-lxc LXC container provisioning
tf-module-proxmox-vm Full VM provisioning
tf-module-proxmox-docker Docker Swarm clusters
tf-module-proxmox-talos Talos Kubernetes clusters
tf-infra-homelab Root orchestration
applications-homelab Kustomize deployments
github-management-plane GitHub org management

The Dependency Graph

  graph TB
    T[terraform-basic-template]
    L[tf-module-proxmox-lxc]
    V[tf-module-proxmox-vm]
    DT[tf-module-proxmox-docker]
    TT[tf-module-proxmox-talos]
    RH[tf-infra-homelab]
    AH[applications-homelab]
    P[ProxmoxVE]
    
    T --> L
    T --> V
    L --> DT
    V --> DT
    L --> TT
    V --> TT
    DT --> RH
    TT --> RH
    RH --> P
    DT --> AH
    TT --> AH

Key observations:

  1. Template is foundational — all modules derive from the same template
  2. LXC and VM are leaf modules — no dependencies on other custom modules
  3. Docker and Talos are composite — build on LXC/VM modules
  4. Root module is orchestrational — composes modules based on configurations
  5. Applications deploy post-provisioning — GitOps ties into Docker/Talos clusters

Configuration-Driven

All infrastructure is defined in YAML configurations, not ad-hoc Terraform runs:

configurations/
├── docker/
│   ├── dev-docker-lxc.yaml
│   └── prod-docker-lxc.yaml
├── kubernetes/
│   ├── dev-k8s.yaml
│   └── prod-k8s.yaml
└── virtual_machine/
    └── ...

Each config has an enabled flag for gradual rollout:

name: prod-k8s
enabled: true  # Set to false to disable without deletion

cluster:
  name: prod-k8s
  datastore:
    id: nas
    node: alpha

What’s Running

Cluster Type Nodes VIP Purpose
prod-docker-lxc Docker Swarm 3x medium (8vCPU/32GB) 192.168.61.20 Container workloads
prod-k8s Talos K8s 3x CP (4vCPU/8GB) + 3x worker (10vCPU/48GB) 192.168.62.20 Kubernetes workloads

Both clusters span all 3 Proxmox nodes for high availability.

Design Principles

This architecture follows specific principles:

Principle Implementation
Single configuration object All modules use unified configuration input
Host pools Resilience through multi-node distribution
Versioned modules Each module has explicit versions
YAML configurations Infrastructure as data, not ad-hoc apply
Private registry Distribution without Terraform Cloud cost
Secrets integration Bitwarden for credential storage
GitOps Flux bootstrapped during cluster creation
Multi-network Separate DMZ and backend networks
GPU passthrough Device mapping in host pool

What Most People Get Wrong

  1. “More modules = better architecture” — I started with 10+ modules. Consolidated to 5. Over-modularization creates maintenance overhead.

  2. “YAML = Terraform” — Terraform is the engine, YAML is the fuel. Don’t embed YAML in .tf files; load from external files.

  3. “GitOps replaces Terraform” — They work together: Terraform provisions, Flux manages apps. Both are declarative.

Each component has its own detailed post:

Post Focus
Talos Kubernetes on Proxmox tf-module-proxmox-talos deep dive — image factory, machine config, bootstrap
Docker Swarm on Proxmox tf-module-proxmox-docker deep dive — Keepalived HA, provisioning
LXC & VM Modules tf-module-proxmox-lxc + tf-module-proxmox-vm basics
Backstage Integration Catalog generation, software templates
Private Terraform Registry Module distribution via Cloudflare Workers
GitHub Management Plane Managing GitHub org via Terraform