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:

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 πŸ™‚