Multi environment homelab setup for deploying Kubernetes from infrastructure as code.
[Deployment] | [Documentation] | [Contributing]
[Deployment]: #get-started [Documentation]: https://homelab.samuel.computer [Contributing]: CONTRIBUTING.md
Homelab Infrastructure as Code
A complete infrastructure-as-code solution for managing a home server environment running on Proxmox VMs. This repository contains automation for the entire lifecycle โ from VM template creation with Packer, to VM provisioning with Terraform, to service deployment with Ansible and Docker Compose.
Multi-Environment Support
This repository supports multiple environments with location-based naming:
- WIL: Development/testing environment
- NYC: Production environment
Network Structure
๐๏ธ WIL Development Environment ๐ข NYC Production Environment
UDM Pro WIL - 10.2.x.x Network UDM Pro NYC - 10.1.x.x Network
โโโ ๐ต VLAN 1 - Infrastructure (10.2.0.0/24) โโโ ๐ต VLAN 1 - Infrastructure (10.1.0.0/24)
โโโ ๐ข VLAN 10 - Storage (10.2.10.0/24) โโโ ๐ข VLAN 10 - Storage (10.1.10.0/24)
โโโ ๐ด VLAN 20 - Virtual Machines (10.2.20.0/24) โโโ ๐ด VLAN 20 - Virtual Machines (10.1.20.0/24)
โโโ ๐ VLAN 30 - Servers Misc (10.2.30.0/24) โโโ ๐ VLAN 30 - PTP Devices (10.1.50.0/24)
โโโ ๐ฃ VLAN 200 - Wired Devices (10.2.200.0/24) โโโ ๐ฃ VLAN 200 - Wired Devices (10.1.200.0/24)
โโโ ๐ฃ VLAN 230 - Wireless Devices (10.2.230.0/24) โโโ ๐ฃ VLAN 230 - Wireless Devices (10.1.230.0/24)
โโโ ๐ฃ VLAN 245 - IoT Devices (10.2.245.0/24)
Services
๐บ Media
Plex, Sonarr, Radarr, Prowlarr, Sabnzbd, Bazarr, Tunarr, Pulsarr, Cleanuparr, Tdarr, Frigate
๐ Monitoring
Prometheus, Grafana, Homepage, Uptime Kuma (external VPS)
๐ง Infrastructure
DNS (BIND9 with DDNS), Reverse Proxy (Caddy), Tailscale subnet router
๐ Applications
Personal website, Birdle (bird identification game), Terraria game server
Domains
| Domain | Purpose | |--------|---------| | 5am.video | Media services | | wil.5am.cloud | Internal infrastructure (WIL) | | ext.5am.cloud | External services | | sfc.al | Personal projects |
DNS is split-horizon โ internal clients resolve to local IPs via BIND9, external clients use Cloudflare.
Deployment - Zero to Hero
There are 5 steps to fully deploy this homelab from scratch.
๐ Step 0: Prerequisites
Before starting, ensure you have the following:
Software Requirements
- Docker and Docker Compose
- Git
- SSH key pair for VM access
- Task (Taskfile runner) - Installation instructions
Initial Setup
# Clone the repository
git clone https://github.com/sfcal/homelab.git
cd homelab
Verify Taskfile is installed
task --version
View available tasks
task --list
๐ณ Step 1: Build Execution Environment
Create a containerized environment with all necessary tools:
# Build the homelab execution container
task docker:exe
Create a convenient alias for running commands
Add to .bashrc
alias hl='docker run -it --rm \
-v "$HOME/.ssh:/home/devops/.ssh" \
-v "$HOME/.kube:/home/devops/.kube" \
-v "$PWD:/workspace" \
-v "$HOME/.home:/home/devops/.home" \
-v "$HOME/.gitconfig:/home/devops/.gitconfig" \
-e ENV=dev \
homelab-exe'
๐ฆ Step 2: Create VM Templates with Packer
Generate Ubuntu VM templates for your infrastructure:
Configure Packer Variables
- Create credentials file:
cd packer/environments/dev
cp credentials.dev.pkrvars.hcl.example credentials.dev.pkrvars.hcl
- Review environment variables:
# Check dev environment settings
cat environments/dev/ubuntu-variables.pkrvars.hcl
Important variables: These need to reflect if you are using local storage, ceph, or nfs
iso_file = "local:iso/ubuntu-24.04.2-live-server-amd64.iso"
isostoragepool = "ISOs-Templates"
storage_pool = "vm-disks" storagepooltype = "rbm" cloudinitstorage_pool = "vm-disks"
Build Templates
Choose your template and environment
# Build base Ubuntu template
hl task packer:build TEMPLATE=base ENV=dev
Build other templates as needed
hl task packer:build-ubuntu ENV=dev
hl task packer:build-debian ENV=dev
hl task packer:build-netboot ENV=dev
๐๏ธ Step 3: Provision VMs with Terraform
Deploy your VM infrastructure on Proxmox:
Configure Terraform Variables
- Create terraform variables:
cd terraform/environments/dev
cp terraform.tfvars.example terraform.tfvars
- Edit terraform.tfvars:
proxmoxapiurl = "https://pve-01.home.example.com:8006/api2/json"
proxmoxapitoken_id = "root@pam!terraform"
proxmoxapitoken_secret = "your-secret-here"
sshpublickey = "ssh-ed25519 AAAA..."
vms = { "dns-server" = { name = "dns-server" proxmox_node = "pve-01" vmid = 201 template_name = "ubuntu-server-base" ip_address = "10.2.20.53/24" gateway = "10.2.20.1" nameserver = "10.2.20.1" cores = 2 memory = 2048 disk_size = "20G" storage_pool = "vm-disks" ssh_user = "devops" } # Add more VMs: media-stack, monitoring, reverse-proxy, etc. }
Deploy Infrastructure
# Deploy all VMs
hl task terraform:deploy ENV=dev
Or deploy a specific VM
hl task terraform:deploy-vm ENV=dev VM=dns-server
โ๏ธ Step 4: Deploy Services with Ansible
Install Docker and deploy services to your VMs:
Configure Ansible Variables
- Review inventory:
cd ansible
cat environments/dev/hosts.ini
- Configure environment settings:
# Global settings (domains, timezone, deploy path)
cat environments/dev/group_vars/all.yml
Unified services list (shared between DNS and reverse proxy)
cat environments/dev/group_vars/services.yml
The services.yml file is the single source of truth โ it defines every service's subdomain, backend host/port, and whether it's proxied through Caddy.
Deploy Everything
# Deploy entire infrastructure in order
hl task ansible:deploy-all ENV=dev
Or Deploy Individual Stacks
# Infrastructure
hl task ansible:deploy-networking ENV=dev # DNS + reverse proxy + Tailscale
hl task ansible:deploy-monitoring ENV=dev # Prometheus, Grafana, Homepage
hl task ansible:deploy-external-monitoring ENV=dev # Uptime Kuma (external VPS)
Applications
hl task ansible:deploy-media ENV=dev # Full media stack
hl task ansible:deploy-website ENV=dev # Personal website
hl task ansible:deploy-birdle ENV=dev # Birdle game
hl task ansible:deploy-games ENV=dev # Terraria server
Utilities
hl task ansible:ping ENV=dev # Test connectivity
hl task ansible:backup-media ENV=dev # Backup media configs
hl task ansible:restore-media ENV=dev # Restore from backup
Verify Deployment
# Test connectivity to all hosts
hl task ansible:ping ENV=dev
Troubleshooting
Adding a new service? Update ansible/environments/<env>/group_vars/services.yml then run:
hl task ansible:deploy-networking ENV=dev This regenerates both DNS records (BIND9) and reverse proxy config (Caddy) from the unified services list.
Related Projects
These projects have been an inspiration to my homelab
- onedr0p/cluster-template - template for deploying a Talos Kubernetes cluster including Flux for GitOps_
- ChristianLempa/homelab - This is my entire homelab documentation files. Here you'll find notes, setups, and configurations for infrastructure, applications, networking, and more._
- khuedoan/homelab - Fully automated homelab from empty disk to running services with a single command._
- ricsanfre/pi-cluster - Pi Kubernetes Cluster. Homelab kubernetes cluster automated with Ansible and FluxCD_
- techno-tim/k3s-ansible - The easiest way to bootstrap a self-hosted High Availability Kubernetes cluster. A fully automated HA k3s etcd install with kube-vip, MetalLB, and more. Build. Destroy. Repeat._
Other Resources
- Dotfiles - My personal configuration files
License
This project is licensed under the GPLv3 License - see the LICENSE file for details.