Homelab Infrastructure Platform

Homelab Overview

I built this homelab as a private, production-style infrastructure platform for practicing provisioning, configuration, Kubernetes operations, and CI/CD inside my own environment.

  • Proxmox provides the virtualization layer.
  • Terraform provisions infrastructure and manages Kubernetes services.
  • Ansible bootstraps the operating system and installs k3s.
  • PostgreSQL stores internal services data and Terraform remote state.
  • Traefik provides the ingress foundation for future services.
  • NetBird provides VPN access without exposing private infrastructure.
  • GitHub Actions runs automation on a self-hosted runner inside the cluster.

Virtualization Layer: Proxmox

Proxmox hosts the reusable Ubuntu cloud-init template and the virtual machines provisioned by Terraform.

Proxmox GUI showing the k8s-control-01 virtual machine
  • The screenshot shows k8s-control-01, the VM created for the Kubernetes control-plane node.
  • The same layer also supports infrastructure hosts such as the NetBird gateway.

Infrastructure as Code: Terraform for Proxmox

Terraform owns the Proxmox VM lifecycle, including the k3s control-plane node and the NetBird gateway host.

Terraform state list for Proxmox-managed homelab resources
  • The Proxmox Terraform state tracks VM resources, initialization data, networking, disks, tags, and lifecycle options.
  • The VM module handles CPU, memory, cloud-init users, SSH key injection, static or DHCP networking, and DNS configuration.

Kubernetes Layer: k3s

After Terraform provisions the VM, Ansible bootstraps the node and installs k3s.

k3s cluster pods and namespaces running in the homelab
  • Ansible installs required OS packages, disables swap, configures kernel modules, and applies Kubernetes sysctl settings.
  • The cluster runs platform components across namespaces inside the private homelab environment.
  • kubeconfig is exported for local operations and CI workflows.

Cluster Services

Terraform also manages the Kubernetes resources and platform services running inside k3s.

Terraform state list for Kubernetes-managed homelab services
  • PostgreSQL runs as an internal StatefulSet with a Kubernetes Secret and ClusterIP Service.
  • Traefik is deployed as the ingress controller and exposed through NodePorts.
  • GitHub Actions Runner Controller and the runner scale set are deployed into the cluster.

Remote Terraform State

Terraform state was moved from local files into PostgreSQL using Terraform pg backend schemas for separate environments.

  • The Proxmox state list tracks virtualization resources.
  • The Kubernetes state list tracks cluster workloads and platform services.
  • Centralized state avoids relying on local terraform.tfstate files.

CI/CD with Self-Hosted GitHub Runner

GitHub Actions jobs run on my own k3s-based self-hosted runner instead of GitHub-hosted runners.

GitHub Actions runner history for homelab CI/CD jobs
  • GitHub Actions Runner Controller registers the runner scale set with GitHub.
  • The runner is inside the homelab network, so workflows can reach private services such as Proxmox, k3s, and PostgreSQL.
  • The runner label is used by workflows with runs-on: homelab.

Terraform Automation Workflow

The automation workflows run Terraform plan and apply operations against the homelab using repository-level GitHub Secrets.

Terraform plan output executed by the homelab self-hosted runner
  • Terraform plan/apply workflows for Proxmox and Kubernetes.
  • Manual approval-style workflow inputs for apply operations.
  • Ansible workflow dispatch for selected playbooks.
  • Sensitive values such as backend connection strings, Proxmox credentials, kubeconfig, SSH keys, and runner tokens are injected through GitHub Secrets.

Security and Remote Access

Secrets are kept out of Git, and remote access is routed through NetBird instead of exposing infrastructure directly to the internet.

  • GitHub repository secrets store CI/CD variables and credentials.
  • Ansible Vault stores sensitive Ansible role variables.
  • Terraform sensitive variables handle provider and service credentials.
  • .gitignore excludes local state, tfvars, kubeconfig artifacts, SSH material, and vault password files.

Next Steps

  • Add more Kubernetes applications behind Traefik.
  • Add backup automation for PostgreSQL and Terraform state.
  • Add monitoring and alerting.
  • Improve runner isolation and job-specific permissions.
  • Add environment protection rules around production apply workflows.