Introduction
Proxmox VE is an open-source virtualization platform for KVM virtual machines and LXC containers. The community.general collection provides modules to automate Proxmox through its REST API — create VMs from templates, manage LXC containers, handle storage, snapshots, and cluster operations. This article covers the complete Proxmox automation workflow with Ansible.
Prerequisites
# Install the collection
ansible-galaxy collection install community.general
# Install Python dependency
pip install proxmoxer requests
Connection Variables
# group_vars/proxmox.yml (encrypt sensitive values with Vault)
proxmox_host: pve.example.com
proxmox_user: root@pam
proxmox_password: "{{ vault_proxmox_password }}"
# Or use API token (recommended)
proxmox_api_user: ansible@pve
proxmox_api_token_id: automation
proxmox_api_token_secret: "{{ vault_proxmox_token }}"
Create API Token in Proxmox
# On Proxmox host
pveum user add ansible@pve
pveum aclmod / -user ansible@pve -role PVEAdmin
pveum user token add ansible@pve automation --privsep=0
# Save the token value — shown only once
Module Reference
| Module | Description |
|---|---|
community.general.proxmox | Manage LXC containers |
community.general.proxmox_kvm | Manage KVM virtual machines |
community.general.proxmox_template | Manage VM/CT templates |
community.general.proxmox_snap | Manage snapshots |
community.general.proxmox_disk | Manage VM disks |
community.general.proxmox_nic | Manage VM network interfaces |
community.general.proxmox_storage_info | Query storage information |
community.general.proxmox_tasks_info | Query task status |
Create a KVM Virtual Machine
From Template (Clone)
---
- name: Create VM from template
hosts: localhost
gather_facts: false
vars:
proxmox_host: pve.example.com
proxmox_api_user: ansible@pve
proxmox_api_token_id: automation
proxmox_api_token_secret: "{{ vault_proxmox_token }}"
tasks:
- name: Clone VM from template
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
name: webserver-01
clone: ubuntu-2404-template
vmid: 200
full: true
storage: local-lvm
timeout: 300
register: vm_result
- name: Configure VM resources
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
vmid: 200
cores: 4
memory: 4096
balloon: 2048
onboot: true
update: true
- name: Start VM
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
vmid: 200
state: started
Create VM from ISO
- name: Create VM from scratch
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
name: db-server-01
vmid: 201
cores: 8
memory: 16384
bios: ovmf
machine: q35
scsihw: virtio-scsi-single
scsi:
scsi0: "local-lvm:64,format=raw,iothread=1"
ide:
ide2: "local:iso/ubuntu-24.04-live-server-amd64.iso,media=cdrom"
net:
net0: "virtio,bridge=vmbr0,firewall=1"
boot: order=scsi0;ide2;net0
ostype: l26
agent: 1
onboot: true
Manage LXC Containers
---
- name: Create LXC container
hosts: localhost
gather_facts: false
tasks:
- name: Create container
community.general.proxmox:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
hostname: nginx-ct
vmid: 300
ostemplate: "local:vztmpl/ubuntu-24.04-standard_24.04-1_amd64.tar.zst"
storage: local-lvm
disk: 10
cores: 2
memory: 1024
swap: 512
netif: '{"net0":"name=eth0,bridge=vmbr0,ip=dhcp,firewall=1"}'
password: "{{ vault_ct_root_password }}"
pubkey: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
onboot: true
unprivileged: true
state: present
- name: Start container
community.general.proxmox:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
vmid: 300
state: started
Bulk VM Provisioning
---
- name: Provision multiple VMs
hosts: localhost
gather_facts: false
vars:
vms:
- name: web-01
vmid: 200
cores: 2
memory: 2048
template: ubuntu-2404-template
- name: web-02
vmid: 201
cores: 2
memory: 2048
template: ubuntu-2404-template
- name: db-01
vmid: 210
cores: 4
memory: 8192
template: ubuntu-2404-template
- name: cache-01
vmid: 220
cores: 2
memory: 4096
template: ubuntu-2404-template
tasks:
- name: Clone VMs from template
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
name: "{{ item.name }}"
clone: "{{ item.template }}"
vmid: "{{ item.vmid }}"
full: true
storage: local-lvm
timeout: 300
loop: "{{ vms }}"
- name: Configure VM resources
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
vmid: "{{ item.vmid }}"
cores: "{{ item.cores }}"
memory: "{{ item.memory }}"
onboot: true
update: true
loop: "{{ vms }}"
- name: Start all VMs
community.general.proxmox_kvm:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
vmid: "{{ item.vmid }}"
state: started
loop: "{{ vms }}"
Snapshots
- name: Create VM snapshot
community.general.proxmox_snap:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
vmid: 200
hostname: webserver-01
snapname: "pre-upgrade-{{ ansible_date_time.date }}"
description: "Snapshot before system upgrade"
state: present
vmstate: true
- name: Rollback to snapshot
community.general.proxmox_snap:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
vmid: 200
hostname: webserver-01
snapname: "pre-upgrade-2026-04-25"
state: rollback
Download Templates
- name: Download container template
community.general.proxmox_template:
api_host: "{{ proxmox_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve-node1
storage: local
template: ubuntu-24.04-standard_24.04-1_amd64.tar.zst
content_type: vztmpl
state: present
Dynamic Inventory
Use the Proxmox dynamic inventory plugin to auto-discover VMs:
# proxmox.yml (inventory file)
plugin: community.general.proxmox
url: https://pve.example.com:8006
user: ansible@pve
token_id: automation
token_secret: !vault |
$ANSIBLE_VAULT;1.1;AES256
...
validate_certs: false
want_facts: true
# Group by tags
groups:
webservers: "'web' in (proxmox_tags | default(''))"
databases: "'db' in (proxmox_tags | default(''))"
# Set connection variables
compose:
ansible_host: proxmox_agent_interfaces[0].ip_addresses[0] | default(proxmox_name)
# Test inventory
ansible-inventory -i proxmox.yml --list
Troubleshooting
Authentication Failed
fatal: "500 Internal Server Error: authentication failure"
- Use API token instead of password (more reliable)
- Verify token has
PVEAdminor appropriate role - Check
privsep=0on the token
VM Clone Timeout
# Increase timeout for large disks
- community.general.proxmox_kvm:
clone: template-name
timeout: 600 # 10 minutes
full: true
"proxmoxer" Module Not Found
pip install proxmoxer requests
# Or in a virtualenv
pip install proxmoxer requests urllib3
Best Practices
- Use API tokens over passwords — more secure, no session management
- Use templates — clone from a golden image, don't install from ISO
- Snapshot before changes — automate pre-change snapshots
- Tag your VMs — enables dynamic inventory grouping
- Use
onboot: true— VMs start automatically after host reboot - Enable QEMU agent —
agent: 1gives Ansible access to guest IP addresses - Unprivileged containers — always use
unprivileged: truefor LXC
Related Articles
Conclusion
The community.general Proxmox modules automate the full VM and container lifecycle — clone from templates, configure resources, manage snapshots, and provision at scale. Use API tokens for authentication, the dynamic inventory plugin for auto-discovery, and templates for consistent provisioning. Proxmox plus Ansible gives you a fully automated, open-source virtualization platform.