wahaha
Published on 2026-05-08 / 60 Visits
0
0

Cara Membuat Multi VM di Proxmox dengan Terraform

Berawal dari rasa kesal karena melakukan task repetitif ketika membuat VM (Virtual Machine) dalam Proxmox, sehingga saya penasaran dengan cara bagaimana bila kerjaan tersebut dijadikan otomatis? Lalu, lahir lah postingan ini. Hal pertama yang saya lakukan ialah dengan mencari referensi tools apa yang akan digunakan dan saya menemukan tools bernama Terraform.

Terraform adalah tools open-source buatan Hashicorp yang dapat mengelola Infrastructure as Code (IaC) atau mungkin apabila diterjemahkan kedalam Bahasa Indonesia menjadi "Infrastruktur Berbasis Kode", terdengar kurang nyambung ya? Maka dari itu pengigat IT lebih sering menggunakan istilah aslinya.

Tools ini menggunakan bahasa HCL (HashiCorp Configuration Language). Karena alat ini bersifat open-source, maka banyak orang/komunitas yang dapat berkontribusi di project ini. Salah satunya Proxmox. Oh iya, provider terraform itu sendiri adalah jembatan penghubung dari konfigurasi yang kita buat ke endpoint infrastruktur, tanpa itu kita tidak akan bisa membuat atau mengatur resource dari infrastruktur tujuan. Oke, cukup ceritanya sekarang lanjut ke pengerjaan.

1. Lab Environment

  • Proxmox v9.1.1

  • Terraform v1.14.8

  • Terraform provider (bpg/proxmox) v0.103.0

  • Ubuntu 24.04 noble

  • yaml parsing 'yq' (https://github.com/mikefarah/yq/) v4.49.2

  • envsubt 'gettext-base' v0.21

2. Setup API di Proxmox untuk Terraform

Ada 2 setup yang akan dilakukan untuk integrasi terrafom di proxmox yaitu setup API Connection dan Deploy Terraform. Detailnya saya jabarkan pada penjelasan dibawah ini.

2.1 Create Group and Roles

Sebelum setup API, saya membuat grup yang akan dipakai terraform. Grup di proxmox berguna untuk menandakan workdir dan environment terraform saya. Grup ini juga berfungsi untuk isolate permission, jadi kita bisa membuat rule atau aturan untuk grup ini terkait alokasi datastore, audit, dll. Untuk pembuatan grup bisa akses ke dashboard proxmox lalu pada sidebar, klik Datacenter > Permissions > Groups kemudian Create new group.

Setelah itu, kembali ke Permissions > Roles > Create new role

Untuk privileges saya menggunakan beberapa rules berikut:

untuk privileges nya bisa kasih ini

#Storage privileges
Datastore.AllocateSpace
Datastore.Audit

#Network privilege
SDN.Use

#VM privileges
VM.Allocate
VM.Audit
VM.Clone
VM.Config.CDROM
VM.Config.CPU
VM.Config.Cloudinit
VM.Config.Disk
VM.Config.HWType
VM.Config.Memory
VM.Config.Network
VM.Config.Options
VM.Console
VM.GuestAgent.Audit
VM.GuestAgent.Unrestricted
VM.PowerMgmt

2.2 Memasukkan Permission Roles kedalam Group

Klik Datacenter > Permissions. Selanjutnya klik add > group permissions.

Pada opsi Path, kita pilih root dir (/), karena provisioning memerlukan akses ke beberapa resource. Untuk itu saya berikan permission akses ke direktori root, agar grup terraform dapat full akses terhadap resouce proxmox sendiri. Kemudian ceklis Propogate agar direktori dibawah root bisa diakses dan memudahkan semua pemanggilan API ke proxmox.

2.3 Create user

Klik Datacenter > Permissions > Users, lalu pilih Add. Buat user baru dan masukkan ke dalam grup terraform yang telah dibuat sebelumnya. Pada bagian Realm, pilih Linux PAM standard authentication. Opsi ini memastikan user yang dibuat terintegrasi langsung dengan sistem autentikasi OS host, yang nantinya mempermudah manajemen akses dan sinkronisasi permission pada VM dengan single key.

2.4 Create token

Navigasi ke Datacenter > Permissions > API Token, klik Add, lalu pilih user yang telah dibuat sebelumnya.

Token ID: Merupakan identitas unik untuk token ini. ID ini bersifat permanen, wajib dicatat, dan akan digunakan dalam konfigurasi Terraform.

Privilege Separation: Fitur ini digunakan jika kita ingin membatasi hak akses spesifik pada token tersebut. Karena kita akan menggunakan permission role yang sudah diatur pada level Group/User, bagian ini tidak perlu diceklis agar token otomatis ikut permission yang sebelumnya kita buat.

Karena token hanya bisa dilihat sekali, maka dari itu setelah buat simpan baik baik token tersebut, apabila hilang, kita harus generate ulang token.

2.5 Cek Token

Untuk melihat API yang sudah kita buat sebelumnya, kita bisa cek di Datacenter > Permissions > API token , lalu klik token yang telah dibuat, selanjutnya klik show permission.

List permission generated for user and group terraform.

3. Membuat VM Template

Setelah proses pembuatan API untuk Terraform selesai, selanjutnya kita harus membuat template atau master vm untuk terrafom. Pada step ini saya menggunakan CLI (Command Line Interface), alasannya karena pengerjaan ini lebih mudah dan cepat apabila menggunakan CLI. Perintah dan penjelasannya bisa dibaca pada poin-poin berikut

3.1 Buat workdir dan download image

Image yang didownload diutamakan image yang sudah ada cloud-init didalamnya. Image-image yang sudah ada cloud-init biasanya mengandung kata cloud pada nama imagenya. Misalnya, jammy-server-cloudimg.img atau CentOS-7-x86_64-GenericCloud.qcow2. Agar mempermudah untuk pembuatan template, image yang disarankanpun berformat img,qcow2 dan raw. Berikut contohnya

mkdir tes-tfgen
cd tes-tfgen
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img -O jammy.img

3.2 Buat VM template

Agar size template image tidak terlalu besar, disarankan gunakan size disk secukupnya. Sebisa mungkin, seminimal mungkin untuk efisiensi utilisasi server kita. Apabil ingin menambahkan disk, bisa ditambah setelah template sudah jadi. Plan template image dan vm template sebagai berikut:

  • Nama image: jammy

  • Image OS: Ubuntu 20

  • Extend Disk: 10G

# Buat VM template tanpa disk
qm create 6969 --name jammy --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-pci

Jika sebelumnya sudah ada volume, bisa diattach kedalam vm template tersebut

qm importdisk 6969 jammy.img local-lvm
qm set 6969 --scsi0 local-lvm:6969/vm-6969-disk-0.raw

Apabila tidak ingin pakai volume, bisa dijalankan perintah berikut

qm set 6969 --scsi0 local-lvm:0,import-from=/root/tes-tfgen/jammy.img

Tambah properties untuk image. Tambah yang dibutuhkan saja

# lokasi boot order
qm set 6969 --boot order=scsi0

# opsional apabila ingin extend vm storage
qm resize 6969 scsi0 10G

# IDE0 adalah lokasi cloud-init yang diset untuk local-lvm
qm set 6969 --ide0 local-lvm:cloudinit

# Serial0 sebagai output display (CLI)
qm set 6969 --serial0 socket --vga serial0

# Aktifkan QEMU guest agent
qm set 6969 --agent enabled=1

Setup cloud-init

# User vm
qm set 6969 --ciuser ubuntu

# Set password (wajib)
qm set 6969 --cipassword 123 ##necessary on ubuntu cloudimg 

# IP diset dhcp client
qm set 6969 --ipconfig0 ip=dhcp

Lalu start vm template.

# Start VM
qm start 6969

3.3 Install cloud-init

Tahapan diatas belum selesai, karena kita harus memastikan beberapa hal berikut

  • Cloud-init service: pastikan cloud-init sudah autorun pada systemd. Karena jika tidak, metadata yang dimasukkan proxmox (vm name, ip, network, dll) tidak akan terpasang (terinject).

    sudo systemctl status cloud-init
  • Qemu agent: qemu agent harus dipasang untuk sinkronisasi data dari proxmox ke vm tersebut. Misal: sinkron jam ataupun perintah untuk shutdown dari dashboard proxmox.

    sudo apt install qemu-guest-agent -y
    sudo systemctl enable qemu-guest-agent
  • Hapus machine-id: Machine-id harus dihapus karena kita akan membuat vm yang lebih dari 1, jadi machine-id tidak boleh sama. Jika sama, vm tersebut akan mempunyai data yang sama. Misal: ip dari dhcp server akan sama karena machine-id yang sama.

    sudo truncate -s 0 /etc/machine-id
    sudo rm /var/lib/dbus/machine-id
    sudo ln -s /etc/machine-id /var/lib/dbus/machine-id

Selanjutnya template bisa di shutoff untuk mengambil snapshot vm-nya. Perintahnya bisa menggunakan sudo shutdown now.

4. Generate VM Template

Setelah vm template sudah dibuat dan di shutoff, Selanjutnya kita masuk ke tahapan generate vm template didalam proxmox. Tahapan ini wajib dijalankan karena Terraform memerlukan unit dengan status Template untuk melakukan proses cloning secara otomatis. Jika tidak diubah menjadi template, Terraform tidak akan mengenali ID tersebut sebagai source image yang valid.

4.1 Generating VM with terrafrom template (workaround)

Disini saya menggunakan template yang saya buat sendiri, apabila ingin menggunakannya silakan fork repository saya. Penjelasan template tersebut saya sertakan di repo tersebut. Karena jika saya masukkan kedalam artikel ini, akan terlalu panjang. Di sini saya hanya memberikan workaround untuk penggunaanya. Untuk host-nya sendiri saya pakai ubuntu noble.

  • Install package: Pada dasarnya, tidak ada OS yang bundling dengan package terraform, kecuali custom OS. Jadi kita harus memasang terraform di proxmox sebelum deploy multi vm.

    ## tambah repository terraform
    sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
    
    wget -O- https://apt.releases.hashicorp.com/gpg | \
    gpg --dearmor | \
    sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
    
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
    
    sudo apt update -y ; sudo apt install terraform -y
    
    ## install yaml parsing dan envsubt 
    sudo apt-get install gettext-base
    sudo snap install yq
  • Clone repository: Saya menggunakan template yang sebelumnya saya buat dan saya publish di github.

    ## Clone github repository 
    git clone https://github.com/fareisa/Spawn-VM-banyak-di-Proxmox
    cd Spawn-VM-banyak-di-Proxmox
    
    ## copy dan edit vm.yaml
    cp vm.yaml tes.yml
    nano tes.yml

Sedikit penjelasan, kenapa make yaml parsing dari luar, kenapa gk json parsing.
saya milih yaml karena emang enak aja kalau buat dijadiin template, sama kenapa yaml parsing dari luar, bukan dari package ubuntu nya?
'yq' dari ubuntu sama kayak 'jq' cuman beda depannya make y :v (https://unix.stackexchange.com/questions/774082/executing-yq-but-jq-gets-executed) makanya make yang rilll 'yq' (https://github.com/mikefarah/yq/)

4.2 Edit template

Apabila konfigurasi dan template yang kalian pakai sama dengan artikel ini, tidak perlu diedit apapun. Tapi apabila ada modifikasi yang kalian lakukan, bisa diubah sesuai yang kalian modif. Berikut contoh file konfig yang saya pakai

project_name: tes-wahaha

proxmox:
  endpoint: "https://192.168.11.254:8006/api2/json"
  api_token: "terraform@pam!tes=<token>"
  node: "pve-core"
  template_id: 6969

vms:
  - name: tes-1
    cores: 2
    memory: 2048
    user: ubuntu
    password: ubuntu
    ssh_keys:
      - <ssh pubkey> 

    disks:
      - datastore: local-lvm
        interface: scsi0
        size: 20

      - datastore: shared-disk
        interface: scsi1
        size: 40

    network:
      - bridge: vmbr0
        ip: 192.168.11.22/24

      - bridge: vmbr1
        ip: dhcp

  - name: tes-2
    cores: 2
    memory: 2048
    user: ubuntu
    password: ubuntu
    ssh_keys:
      - <ssh pubkey> 

    disks:
      - datastore: local-lvm
        interface: scsi0
        size: 20

      - datastore: local-zfs
        interface: scsi2
        size: 40

    network:
      - bridge: vmbr0
        ip: 192.168.11.45/24
        gateway: 192.168.11.1

      - bridge: vmbr1

4.3 Deploy dengan terraform

Setelah semuanya beres, saat yang kita tunggu-tunggu, yaitu buat multi vm di proxmox dengan terraform. Jalankan sesuai tahapan dibawah

  • Berikan akses execute untuk bash script tfgen-1.sh agar terraform dapat menjalankan script tersebut. lalu jalankan perintah terraform. Pastikan semua validasi statusnya OK

    chmod +x tfgen-1.sh
    
    # Execute terraform template
    ./tfgen-1.sh -i tes.yml
    
    # Terraform akan validasi config
    Validating YAML...
    Validation OK
    Replace ./tes-wahaha? [y/N]: y
    Rendering Terraform...
    Done → ./tes-wahaha/main.tf
  • Setelah semua validasi ok, lanjut inisasi dan apply konfigurasi terraform.

    cd ./tes-wahaha/
    
    terraform init
    terraform apply

5. Testing

Untuk proses testing, saya menggunakan 2 metode. Yaitu ping dan ssh. Jika 2 metode itu sudah berhasil, kemungkinan besar vm sudah berhasil di deploy

Ping

wahaha@wahaha-thinkpad:~/Spawn-VM-banyak-di-Proxmox/tes-wahaha$ ping 192.168.11.22
PING 192.168.11.22 (192.168.11.22) 56(84) bytes of data.
64 bytes from 192.168.11.22: icmp_seq=1 ttl=62 time=9.19 ms
64 bytes from 192.168.11.22: icmp_seq=2 ttl=62 time=9.82 ms
^C
--- 192.168.11.22 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 9.187/9.501/9.815/0.314 ms
wahaha@wahaha-thinkpad:~/Spawn-VM-banyak-di-Proxmox/tes-wahaha$ ping 192.168.11.45
PING 192.168.11.45 (192.168.11.45) 56(84) bytes of data.
64 bytes from 192.168.11.45: icmp_seq=1 ttl=62 time=9.03 ms
^C
--- 192.168.11.45 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 9.031/9.031/9.031/0.000 ms

SSH

wahaha@wahaha-thinkpad:~/Spawn-VM-banyak-di-Proxmox/tes-wahaha$ ssh 192.168.11.22 -l ubuntu ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether bc:24:11:3d:e3:73 brd ff:ff:ff:ff:ff:ff
    altname enp0s18
    altname ens18
    inet 192.168.11.22/24 brd 192.168.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::be24:11ff:fe3d:e373/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether bc:24:11:46:b3:f2 brd ff:ff:ff:ff:ff:ff
    altname enp0s19
    altname ens19
    inet 192.168.12.252/24 metric 100 brd 192.168.12.255 scope global dynamic eth1
       valid_lft 1356sec preferred_lft 1356sec
    inet6 fe80::be24:11ff:fe46:b3f2/64 scope link
       valid_lft forever preferred_lft forever
wahaha@wahaha-thinkpad:~/Spawn-VM-banyak-di-Proxmox/tes-wahaha$ ssh 192.168.11.45 -l ubuntu ip a
The authenticity of host '192.168.11.45 (192.168.11.45)' can't be established.
ED25519 key fingerprint is SHA256:s5JY5d7B6xRwC8elj/e7wDLw2zOC9lhiRS7wIj4F3hM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.11.45' (ED25519) to the list of known hosts.
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether bc:24:11:e9:cb:9a brd ff:ff:ff:ff:ff:ff
    altname enp0s18
    altname ens18
    inet 192.168.11.45/24 brd 192.168.11.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::be24:11ff:fee9:cb9a/64 scope link
       valid_lft forever preferred_lft forever
3: ens19: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether bc:24:11:05:79:5f brd ff:ff:ff:ff:ff:ff
    altname enp0s19

Penutup

Mengotomatisasi pembuatan VM di Proxmox menggunakan terraform dapat mengefisiensi waktu dan mengantisipasi human error saat deploy vm yang banyak. Meskipun tahapannya panjang, tapi untuk kedepannya kita akan dipermudah saat deploy banyak vm sekaligus. Semoga postingan ini bermanfaat buat kalian yang ingin mulai terjun ke dunia Infrastructure as Code. Jika ada kendala saat mencoba workaround di atas, silakan mampir ke repository github saya atau tulis pertanyaan di kolom komentar.

Referensi

  • https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

  • https://manjit28.medium.com/automating-vm-creation-in-proxmox-a-complete-guide-18652f346db5

  • https://registry.terraform.io/providers/bpg/proxmox/latest/docs

  • https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks

  • https://medium.com/@DatBoyBlu3/provisioning-proxmox-virtual-machines-with-terraform-d9e9c549f947

  • https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425?permalink_comment_id=3799230

  • https://gist.github.com/zidenis/dfc05d9fa150ae55d7c87d870a0306c5

  • chatGPT gratis


Comment