← Back to Blog

#2: Terraform and Promox!

Introduction

In this blog post, I'm going to share how I set up a comprehensive Infrastructure as Code (IaC) environment for managing my homelab using Proxmox, Terraform, AzureRM, and GitHub Actions. This setup automates the deployment and management of virtual machines (VMs) on Proxmox VE, ensuring a streamlined and secure infrastructure management process.

This was interesting to setup it provided a lot of challenges and troubleshooting but eventually I got it working. The easiest part was leveraging Azure as I was the most familiar with AzureCLI and the hardest part was Terraform, but overall it was a great learning experience. The biggest push for me to do this was having to start leveraging this at work, it has also been great to use AI tools to help me learn and develop my skills.

Public Github Repo is located here: Proxmox and Terraform Repo

What I Did

Overview of the Setup

I leveraged Terraform to automate the deployment of VMs on Proxmox VE, with configurations for different VM sizes and operating systems. I used AzureRM for state management, and employed GitHub Actions to automate the deployment process, ensuring continuous integration and delivery.

Key Components

  1. Terraform Configuration:
    • Purpose: Terraform is used to define and provision infrastructure. It allows you to specify the desired state of your infrastructure and automatically manage changes.
    • Setup: Begin by installing Terraform and creating a main.tf file to define your infrastructure. You will setup the variables and provider in the next step.
    • Below is an example of one host I defined in my main.tf
resource "proxmox_vm_qemu" "docker-host" {
  name        = "ubuntu-docker-host"
  desc        = "Docker Host for my homelab."
  vmid        = 101
  os_type     = var.os_type
  target_node = var.target_node
  clone       = "ubuntu-template"
  cores       = 4
  memory      = 8192
  skip_ipv6   = true
  scsihw      = "virtio-scsi-single"
  onboot      = true

  disk {
    slot    = "scsi0"
    size    = "90G"
    type    = "disk"
    storage = "local-lvm"

  }
  network {
    model  = "virtio"
    bridge = "vmbr0"
  }
}
  1. Setup your variables and provider file
    • Purpose: This will allow you to bring in the necessary providers and variables.
    • Setup: Create variables.tf and providers.tf in the same directory as your main.tf file.
      • You will need to setup a few secrets inside your Github Repository, you can get those requirements below at the YML.
      • To create the API Token for Proxmox which will be necessary you can follow the guide located HERE

Provider.tf

terraform {
  required_providers {
    proxmox = {
      source  = "Telmate/proxmox"
      version = "3.0.1-rc4"
    }
  }

  backend "azurerm" {
    resource_group_name  = "var.rgname"
    storage_account_name = "var.storagename"
    container_name       = "var.containername"
    key                  = "var.tfstate"
  }
}

provider "proxmox" {
  pm_api_url          = var.proxmox_api_url
  pm_api_token_id     = var.proxmox_user
  pm_api_token_secret = var.proxmox_pass
  pm_tls_insecure     = true
}

Varibles.tf

variable "proxmox_api_url" {
  description = "The URL of the Proxmox API"
  type        = string
}

variable "proxmox_user" {
  description = "Proxmox API Token ID"
  type        = string
}

variable "proxmox_pass" {
  description = "Proxmox API Token Secret"
  type        = string
  sensitive   = true
}

variable "os_type" {
  description = "Typical OS Type"
  type        = string
  default     = "OS Type (ubuntu, windows, etc)"
}

variable "target_node" {
  description = "Target node"
  type        = string
  default     = "proxmox node name"
}

variable "os_template" {
  description = "Default Template to create VMs on."
  type        = string
  default     = "name of template here"
}
  1. GitHub Actions Self-Hosted Runner:

    • Purpose: This will allow you to forgo using a VPN to connect from GitHub Cloud runners and will allow you to use as many actions as you want with no limitations.

    • Setup: Follow the instructions set here: GitHub Actions Self-Hosted Runner Install

    • Usage: To connect GitHub Actions to local infrastructure to deploy.

  2. AzureRM for State Management:

    • Purpose: AzureRM is used to manage the Terraform state, ensuring it is stored securely and can be accessed by multiple users.
    • Setup: Configure the backend in Terraform to use AzureRM for state storage. You'll need an Azure Storage Account which you can setup easily via AzureCLI following instructions located here: Storage Account Creation via CLI
    • Note: you will also need to create an Service Principal for this and assign it rights to the Storage Account, more info here: Azure Service Principal Creation
    • Usage: The state file is automatically updated in Azure Storage whenever you apply changes with Terraform, providing the state of your infrastructure.
  3. GitHub Actions for CI/CD:

    • Purpose: GitHub Actions automates the deployment process, ensuring that changes to your infrastructure are automatically applied.
    • Setup: Create a workflow file in your repository to define the CI/CD pipeline. Include steps for checking out the code and running your Terraform files.
      • GitHub Repository Secrets to create (Note, Service Principal step is required)
        • ARM_CLIENT_ID
        • ARM_CLIENT_SECRET
        • ARM_SUBSCRIPTION_ID
        • ARM_TENANT_ID
        • PROXMOX_API_URL
        • PROXMOX_API_TOKEN_SECRET
        • Also create a variable named PROXMOX_NODE
name: 'Terraform Proxmox Infrastructure'

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

jobs:
  terraform:
    name: 'Terraform'
    runs-on: self-hosted

    env:
        ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
        ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
        ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
        ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
        ARM_USE_CLI: false
        TF_VAR_proxmox_api_url: ${{ secrets.PROXMOX_API_URL }}
        TF_VAR_proxmox_user: ${{ secrets.PROXMOX_API_TOKEN_ID }}
        TF_VAR_proxmox_pass: ${{ secrets.PROXMOX_API_TOKEN_SECRET }}  
    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v3

    - name: Terraform Init
      run: terraform init
      working-directory: ./proxmox

    - name: Terraform Format
      run: terraform fmt
      working-directory: ./proxmox

    - name: Terraform Plan
      id: plan
      run: terraform plan -input=false
      working-directory: ./proxmox

    - name: Terraform Apply
      run: terraform apply -auto-approve -input=false
      working-directory: ./proxmox
  • Usage: Trigger the workflow by pushing changes to the main branch or manually triggering via GitHub UI (in Actions). The workflow will automatically apply the Terraform configuration.

Conclusion

This setup provides a robust and secure way to manage a homelab environment using modern DevOps practices. By leveraging Terraform, Azure, and GitHub Actions, I automated the deployment and management of VMs on Proxmox VE, ensuring a streamlined and efficient infrastructure management process. This approach enhances security and scalability while simplifying the management of complex infrastructure setups.