Introduction
Building and maintaining a homelab manually can quickly become repetitive, error-prone, and hard to reproduce. As I spent more time experimenting with Kubernetes and self-hosted infrastructure, I wanted a way to provision virtual machines and deploy a Kubernetes cluster consistently, predictably, and with minimal manual steps.
This project β Terraform & Ansible Homelab with K3s β was created primarily as a learning exercise for myself, but I decided to share it publicly in case it helps others who are on a similar DevOps or platform engineering journey.
The goal of this setup is simple:
- Use Terraform to provision virtual machines on Proxmox
- Use Ansible to install and manage a K3s Kubernetes cluster
- Keep everything idempotent, reusable, and easy to tear down
Even though there are many similar projects out there, building this myself helped me deeply understand how these tools fit together in a real homelab environment.
What This Project Covers
By the end of this guide, you will have:
- A reproducible way to provision VMs on Proxmox
- A working K3s cluster (1 master + one or more workers)
- Ansible roles that can install, join, and uninstall the cluster
- A setup that can be safely destroyed and rebuilt for experimentation
System Requirements
Before getting started, ensure you have the following:
Proxmox Environment
- A running Proxmox VE host
- A dedicated Terraform user created with PAM authentication
- API access enabled for Terraform
Helpful references:
- Learn Linux TV (Proxmox + Terraform fundamentals) - Good tutorials here: Learn Linux TV
- Techno Tim / UntouchedWagons (Cloud-init templates) - Good tutorials here: Techno Tim or UntouchedWagons/Ubuntu-CloudInit-Docs
VM Template
- Ubuntu cloud-init image
- Cloud-init enabled
- QEMU guest agent installed
Local / Remote Tooling
- Terraform installed
- Ansible installed
- SSH access to provisioned VMs
π‘ Terraform and Ansible can be run either locally or from a remote management host.
Repository Overview
GitHub Repository:
π https://github.com/danialimransv/terraform-ansible-vm-k3s-homelab
Directory structure:
.
βββ ansible/
β βββ ansible.cfg
β βββ inventory/
β βββ playbooks/
β βββ roles/
βββ terraform/
β βββ base-vm-deploy-k3s/
β βββ main.tf
β βββ provider.tf
β βββ variables.auto.tfvars
β βββ variables.tf
βββ README.md
Each section is intentionally separated to keep infrastructure provisioning and configuration management concerns distinct.
Step 1: Provision Virtual Machines with Terraform
Navigate to the Terraform directory:
cd terraform/base-vm-deploy-k3s
Initialize Terraform:
terraform init
Review and customize variables:
- Proxmox node name
- VM resources (CPU, RAM, disk)
- Network settings
- SSH user
β οΈ It is strongly recommended to read through the Terraform files and understand which variables need to be adjusted for your environment.
Apply the configuration:
terraform apply
After completion, Terraform will provision:
- One K3s master VM
- One or more worker VMs (configurable)
Step 2: Configure Ansible
Move into the Ansible directory:
cd ../../ansible
Create or edit ansible.cfg:
[defaults]
inventory = inventory/hosts
remote_user = serveradmin
roles_path = ./roles
log_path = ./ansible.log
scp_if_ssh = True
host_key_checking = False
Ensure your inventory file contains the IPs or hostnames of:
- The K3s master node
- All worker nodes
Step 3: Install the K3s Cluster
Run the main installation playbook:
ansible-playbook playbooks/k3s-install.yml
What happens behind the scenes:
- The master node installs K3s
- The join token is dynamically retrieved
- Worker nodes automatically join the cluster
- The process is fully idempotent
Step 4: Validate the Cluster
SSH into the master node:
ssh serveradmin@<master_ip>
Check node status:
sudo kubectl get nodes
You should see:
- 1 master node
- All worker nodes in Ready state β
Step 5: Uninstall K3s (Optional)
If you want a clean slate while keeping the VMs:
ansible-playbook playbooks/k3s-uninstall.yml
This runs dedicated uninstall roles for:
- Master node
- Worker nodes
Perfect for rebuilding the cluster without reprovisioning infrastructure.
Ansible Roles Overview
Role Name Description
- k3s_master - Installs and configures K3s master node
- k3s_worker - Installs and joins K3s worker nodes
- k3s_master_uninstall - Uninstalls K3s master node
- k3s_worker_uninstall - Uninstalls K3s worker nodes
Why K3s?
I chose K3s because it is:
- Lightweight
- Production-grade
- Perfect for homelabs and edge environments
- Simple to automate
- It allows me to focus on cluster design and automation, rather than wrestling with heavy bootstrap complexity.
Lessons Learned
Some key takeaways from this project:
- Terraform and Ansible complement each other extremely well
- Idempotency is critical for confidence and repeatability
- Automation makes it much easier to experiment and break things safely
- A teardown path is just as important as a setup path
Conclusion
This project demonstrates a practical, real-world homelab workflow using Terraform, Ansible, and K3s on Proxmox. It is not meant to be the most advanced setup, but rather a solid, understandable foundation that can be extended with:
- GitOps (Argo CD)
- Secrets management (Vault)
- Observability (Prometheus, Grafana, Datadog)
- Security hardening
If youβre learning DevOps or platform engineering, I highly recommend building something similar β not by copying blindly, but by understanding and iterating on it.
Feedback and improvements are always welcome π