Skip to content

Module Machine

📸 Summary

tofu modules allow us to reuse common code in a more manageable way. The module picks up a Template Machine and adds customization on top of it. Using the pre-built image gives us a starting point for small tweaks to each type of machine we intend to deploy. GitLab allows us to store these modules in a hosted repository and there is an included gitlab yaml workflow to publish the module.

🗃️ Repo

git clone git@gitlab.com:loganmancuso_public/infrastructure/proxmox/module-machine.git

📜 Dependencies

📃 Sample Main.tf

since this is a module testing will not be done against the root module but instead will be run within the env folders. This will also only have a main.tf

## Provider ##
terraform {
  backend "http" {
    address = "https://gitlab.com/api/v4/projects/XXXXXXXX/terraform/state/env-module-machine"
  }
}

locals {
  config = {
    env = "env" # datacenter env to deploy the machine to 
  }

  instance = {
    network  = "mgmt"
    ip_start = "XXX.XXX.XXX.XXX"
    version  = "stable" # this is the version schema from template-machine
  }
}

# resource "proxmox_virtual_environment_vm" "data" {
#   for_each  = { for idx, key in keys(local.nodes) : key => idx }
#   node_name = local.nodes[each.key].name
#   started   = false
#   on_boot   = false
#   vm_id     = 110 + each.value

#   disk {
#     datastore_id = "local-lvm"
#     file_format  = "raw"
#     interface    = "scsi0"
#     size         = 32
#     backup       = true
#   }

#   # this also prevents deletion
#   protection = true

#   lifecycle {
#     prevent_destroy = true
#     ignore_changes  = [cpu]
#   }
# }

module "machine" {
  # depends_on = [ proxmox_virtual_environment_vm.data ]
  for_each = { for idx, key in keys(local.nodes) : key => idx }
  source   = "../"

  config = {
    env = local.config.env
    # node = "primary"
    node = each.key
  }

  instance = {
    # single, only deploy a module to a single node useful for testing 
    # name = "module-0"
    # id   = 10
    # ip   = local.instance.ip_start
    # dynamic, one per node
    name          = "module-${each.key}"
    id            = 10 + each.value
    ip            = "${split(".", local.instance.ip_start)[0]}.${split(".", local.instance.ip_start)[1]}.${split(".", local.instance.ip_start)[2]}.${split(".", local.instance.ip_start)[3] + each.value}"
    start_on_boot = true
    description   = "module machine"
    template      = "ubuntu-noble-2404-${local.instance.version}"
    network       = local.instance.network

    cpu_cores = 2
    memory    = 2048
    disk_size = 32
    tags      = ["module-test"]
  }

  devices = {
    usb = []
    disks = []
    # disks = ["${proxmox_virtual_environment_vm.data[each.key].disk[0].datastore_id}:vm-${proxmox_virtual_environment_vm.data[each.key].id}-disk-0"]
    pci   = []
  }

  bootstrap = {
    path = "./scripts/bootstrap.sh"
    tokens = {
      new = "test"
    }
  }

}

output "module" {
  # value = module.machine
  value = { for idx, key in keys(local.nodes) : key => module.machine[key] }
}


⚙️ Deployment Instructions

🛑 Pre-Deployment

set the secret values for communicating with the gitlab api. this is responsible for storing the module in the remote gitlab storage.

export TF_TOKEN_gitlab_com=gplat-XXX

testing this workflow locally is best before publishing the module. Since this is a module we do not deploy the root folder but instead use the env folder to test the deployment.

cd env/
tofu init .
tofu plan
tofu apply

🟢 Deployment

  1. navigate to gitlab and open the project
  2. under build open pipelines here
  3. run the pipeline providing the variable CI_COMMIT_TAG with the value being the version you intend to deploy X.Y.Z (1.0.0)
  4. you can see the published module here

🏁 Post-Deployment


📝 Notes

base64 /var/lib/vz/snippets/module-primary-bootstrap.sh | qm guest exec 2110 -- bash -c "base64 -d > /opt/tofu/bootstrap.sh" file="$(base64 /var/lib/vz/snippets/module-primary-bootstrap.sh)" encoded_content=$(base64 /var/lib/vz/snippets/module-primary-bootstrap.sh) encoded_content=$(base64 /var/lib/vz/snippets/module-primary-bootstrap.sh | tr -d '\n') echo "$encoded_content" echo "$encoded_content" | base64 -d qm guest exec 2110 -- bash -c base64 -d $encoded_content > /opt/tofu/bootstrap.sh qm guest exec 2110 -- bash -c "base64 -di $file > /opt/tofu/bootstrap.sh" < base64 /var/lib/vz/snippets/module-primary-bootstrap.sh echo $file | base64 -di > /tmp/out

📅 Tasks

👎 Known Issues

  • .