CODECAVE
surovtsev.png

Pavel Surovtsev

DevOps Engineer

Все статьи эксперта
Ещё по темам
Поделиться
Время чтения: 2 мин.

How to Automate Proxmox VM Deployments with Pulumi

Deploy Proxmox VMs in Minutes Using Pulumi & Python

Infrastructure Automation is the key component of fast, efficient, predictable, and reproducible environment deployment. Most Proxmox + Pulumi guides out there are frustratingly superficial. They throw around buzzwords but leave you hanging without real-world examples or step-by-step breakdowns. We know that you need more than theory. You need a guide that dives deep, reveals the tricky details, and hands you working code you can deploy immediately.

In our previous Proxmox article, we demonstrated how Proxmox VM templates combined with Cloud-Init can dramatically accelerate your deployment workflow. That foundation is solid, but there's a more powerful approach waiting for you.

To achieve true "one-command" automation and eliminate manual configuration drift, you need a tool that lets you define infrastructure the same way you write application code. Unlike legacy tools with proprietary languages, Pulumi lets you define infrastructure using the programming languages you already know: Python, Go, C#, Java, and TypeScript. This means leveraging your existing coding skills, applying software engineering best practices, and integrating seamlessly with CI/CD pipelines. In this hands-on guide, we'll show you exactly how to implement Pulumi with Proxmox. From installation to a working Python example, you can adapt immediately. This practical walkthrough will give you the knowledge and confidence to transform your infrastructure management. Ready to level up your skills? Let's get started.

What is Pulumi?

Pulumi is an open-source tool for cloud infrastructure management. Its key features include:

  • uses universal programming languages instead of DSL (unlike Terraform);
  • works with major cloud platforms used by most companies - supporting AWS, Azure, Google Cloud;
  • flexible state management - infrastructure state can be stored locally for development, in S3 for team collaboration or in Pulumi Cloud for enterprise features;
  • full programming capabilities (logic, loops, conditions).

For Proxmox, the pulumi-proxmoxve provider enables management of:

  • Virtual machines (VMs);
  • templates;
  • disks;
  • network interfaces;
  • Cloud-init parameters.

Step 1: Installing Pulumi

Pulumi can be installed on all popular operating systems:

Installation on macOS

brew install pulumi/tap/pulumi

Installation on Windows

You can install from the official website Pulumi

Installation on Linux

curl -fsSL https://get.pulumi.com | sh

After installation, Pulumi is added to ~/.pulumi/bin.

If for some reason the PATH variable was not updated:

export PATH=$PATH:$HOME/.pulumi/bin
echo 'export PATH=$PATH:$HOME/.pulumi/bin' >> ~/.bashrc
source ~/.bashrc

Verify installation

pulumi version

If the command displays the Pulumi version number, installation is complete.

Step 2: Set up Pulumi to integrate with Proxmox

For Pulumi to manage Proxmox, it needs API access.

2.1 Enable API Access in Proxmox

1. Open Proxmox Web UI
2. Navigate to API Tokens. Go to: Datacenter Permissions API Tokens
3. Create a Token, for instance root@pam
4. Set "Privilege Separation" to false (for full access). Click "Add"
5. Copy:
- Token ID
- Secret
6. Assign Permissions: Datacenter Permissions Add Api token:
Path /
Api token Token name
Role Administrator

Step 3: Creating a Pulumi Project

mkdir pulumi-proxmox
cd pulumi-proxmox
pulumi new python

After initialization, you'll have:

Pulumi.yaml
__main__.py
requirements.txt

Set up a provider:

pip install pulumi-proxmoxve

Pulumi provides its own built-in config, which we will work with

pulumi config set proxmox:endpoint https://192.168.0.128:8016/
pulumi config set proxmox:api-name root@pam!pulumi
pulumi config set proxmox:public-key: "ssh-key"
pulumi config set proxmox:api-token "api token" --plaintext

Step 4. Code Example: Creating a VM from Template

Now for the most interesting part - we'll create a VM from the template we prepared earlier.

Import the Provider

# python
import pulumi
from pulumi_proxmoxve import Provider
from pulumi_proxmoxve.vm import VirtualMachine

Load Pulumi Configuration

# python
config = pulumi.Config("proxmox")
endpoint = config.require("endpoint")
public_key = config.require("public-key")
api_token = config.require_secret("api-token")
api_name = config.require("api-name")

Connect to Proxmox API

# python
provider = proxmoxve.Provider(
    "proxmoxve",
    endpoint=endpoint,
    api_token=f"{api_name}={api_token}",
    insecure=True
)

Create VM from Template

vm = proxmoxve.vm.VirtualMachine(
       resource_name="vm-test",
       node_name="srv0",        
       vm_id=9875,               
       name="pulumi-vm-test",
       agent=proxmoxve.vm.VirtualMachineAgentArgs(
           enabled=False,
           trim=True,
           type="virtio"
       ),
       bios="seabios",
       memory=proxmoxve.vm.VirtualMachineMemoryArgs(
           dedicated=4096
       ),
       cpu=proxmoxve.vm.VirtualMachineCpuArgs(
           cores=2,
           sockets=1
       ),
       clone=proxmoxve.vm.VirtualMachineCloneArgs(
           node_name="srv0",
           vm_id=9000,
           full=True
       ),
       disks=[
           proxmoxve.vm.VirtualMachineDiskArgs(
               interface="scsi0",
               datastore_id="local-lvm",
               size=20,              
               file_format="qcow2"
           )
       ],
       cdrom=proxmoxve.vm.VirtualMachineCdromArgs(
           interface="ide2",
           file_id="none"
       ),
       network_devices=[
           proxmoxve.vm.VirtualMachineNetworkDeviceArgs(
               bridge="vmbr0",
               model="virtio"
           )
       ],
       on_boot=True,
       operating_system=proxmoxve.vm.VirtualMachineOperatingSystemArgs(type="other"),
       initialization=proxmoxve.vm.VirtualMachineInitializationArgs(
           type="nocloud",
           datastore_id="local-lvm",
           dns=proxmoxve.vm.VirtualMachineInitializationDnsArgs(
               domain="example.com",
               servers=["1.1.1.1", "8.8.8.8"]
           ),
           ip_configs=[
               proxmoxve.vm.VirtualMachineInitializationIpConfigArgs(
                   ipv4=proxmoxve.vm.VirtualMachineInitializationIpConfigIpv4Args(
                       address="192.168.0.140/24",
                       gateway="192.168.0.1"
                   )
               )
           ],
           user_account=proxmoxve.vm.VirtualMachineInitializationUserAccountArgs(
               username="user",
               password="password123",
               keys=[public_key]
           )
       ),
       opts=pulumi.ResourceOptions(provider=prov

Step 5. Running

Preview the Plan:

pulumi preview

Apply:

pulumi up

Pulumi will show what VM will be created and ask for confirmation. After confirmation, the VM will appear in Proxmox.

Step 6. Delete VM

If the VM is no longer needed:

pulumi destroy

What we achieve?

  • Fully automated VM creation process
  • Template usage + Cloud-Init
  • Management through Python code
  • Ability to create dozens of VMs with a single command

This approach scales easily: you can generate VMs in a loop, create resource pools, automatically connect them to networks, and integrate all of this into CI/CD.

For a more detailed study, we recommend reviewing the official Proxmox documentation and following updates to our articles. We provide services around Azure, Proxmox, secure VM templates and CI/CD hardening.