Files
terraform/README.md

4.8 KiB

Terraform

Basic Proxmox setup

Add TerraformProv role

pveum role add TerraformProv -privs "Datastore.Allocate Datastore.AllocateSpace Datastore.Audit Pool.Allocate Sys.Audit Sys.Console Sys.Modify VM.Allocate VM.Audit VM.Clone VM.Config.CDROM VM.Config.Cloudinit VM.Config.CPU VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Console VM.Migrate VM.Monitor VM.PowerMgmt SDN.Use"

Add terraform-prov user

pveum user add terraform-prov@pve --password <password>

Set terraform-prov user TerraformProv role

pveum aclmod / -user terraform-prov@pve -role TerraformProv

Create proxmox token for terraform API

pveum user token add terraform-prov@pve terraform -expire 0 -privsep 0 -comment "Terraform token"

Client Setup

Add environment variable

cp terraform.tfvars.example

fill with your secrets (do no push this file)

Usefull commands

opentofu.tofu init
opentofu.tofu plan
opentofu.tofu apply
opentofu.tofu destroy
tofu apply -target module.<module-name>

On WSL

ssh agent could be off if ssh-add -L gives

Could not open a connection to your authentication agent.

start and configure ssh agent

eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519

Add new service

Create base module

mkdir modules/apps/<module-hostname>

Example

modules/apps/bookshelf/
├── cloud-init
│   └── service.yaml
├── lib
│   ├── scripts
│   │   ├── env.sh
│   └── services
├── main.tf
├── output.tf
├── variables.tf
├── .env.example
└── .env

main.tf

module "vm" {
  source      = "../../vm"
  name        = var.name
  hostname    = var.hostname
  domain      = var.domain
  vm_id       = var.vm_id
  node_name   = var.node_name
  vm_ip_address = var.vm_ip_address

  template_id = var.template_id

  cores       = var.cores
  memory      = var.memory
  disk_size   = var.disk_size

  ssh_public_key  = var.ssh_public_key
  proxmox_host_ip = var.proxmox_host_ip
  cloudinit_config = templatefile(
      "${path.module}/cloud-init/service.yaml",
      {
        hostname        = var.hostname
        domain          = var.domain
        ssh_key         = var.ssh_public_key
        proxmox_host_ip = var.proxmox_host_ip
        environment-setup-script = indent(6, file("${path.module}/lib/scripts/env.sh"))
        env-file-content = indent(6, file("${path.module}/.env"))
      }
    )
}

Add inside templatefile object scripts content to upload with cloud-init.

variables.tf

variable "name" {
  type = string
}

variable "vm_id" {
  type = number
}

variable "node_name" {
  type    = string
  default = "mop"
}

variable "cores" {
  type    = number
  default = 2
}

variable "memory" {
  type    = number
  default = 2048
}

variable "balloon" {
  description = "Minimum vm memory, using ballooning devide to reach Proxmox node memory target."
  type = number
  default = 1024
}

variable "template_id" {
  type = number
}

variable "ssh_public_key" {
  type        = string
  description = "Public SSH key for cloud-init user"
}

variable "hostname" {
  description = "VM hostname"
  type        = string
  default     = "test"
}

variable "domain" {
  description = "VM domain"
  type        = string
  default     = ""
}

variable "disk_size" {
  type    = number
  default = 10
}

variable "proxmox_host_ip" {
  type = string
}

variable "vm_ip_address" {
  type = string
}

output.tf

output "traefik_service" {
    value = [{
        domain = var.domain
        name = var.name
        host = "${var.hostname}"
        ip = var.vm_ip_address
        port = 80
    }]
}

This output supports multiple service for one vm.

cloud-init/service.yaml

#cloud-config
hostname: ${hostname}
local-hostname: ${hostname}
fqdn: ${hostname}.${domain}
manage_etc_hosts: true

users:
  - default
  - name: ${hostname}
    groups: sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh_authorized_keys:
      - ${ssh_key}

disable_root: true

package_update: true
package_upgrade: false

packages:
  - git
  - nfs-common

mounts:
  - [ "192.168.1.12:/main/backups", "/backups", "nfs", "defaults,_netdev,x-systemd.requires=network-online.target", "0", "0" ]

write_files:
  - path: /opt/bookshelf/env.sh
    permissions: "0644"
    content: |
      ${environment-setup-script}
  - path: /opt/bookshelf/bookshelf.env
    permissions: "0644"
    content: |
      ${env-file-content}

runcmd:
    - ls /

final_message: |
  Base system ready for ${hostname}