Ansible on Proxmox VE 8 Automation Complete Guide
By Luca Berton · Published 2024-01-01 · Category: installation
Automate Proxmox VE 8 with Ansible and the community.proxmox collection: KVM/LXC, cloud-init clones, clusters, backups, dynamic inventory.
Proxmox VE 8 (latest 8.4) is the open-source enterprise hypervisor that combines KVM virtual machines and LXC containers on a Debian 12 base. Ansible automates the cluster, nodes, VMs, containers, storage, and backups through the Proxmox REST API (port 8006).
> Collection update (2026): the Proxmox modules have moved out of community.general into a dedicated community.proxmox collection. The old community.general.proxmox names still resolve as deprecated redirects but are scheduled for removal in community.general 15.0.0 — use community.proxmox. going forward.
Proxmox VE 8 release facts
| Item | Value | |---|---| | Base OS | Debian 12 Bookworm | | Kernel | 6.8 (6.11 opt-in) | | QEMU | 9.x | | LXC | 6.x | | Latest point release | 8.4 | | API | Proxmox REST API (port 8006) |
See also: Ansible for Proxmox: Automate VM and Container Management Complete Guide
Install the collection and Python deps
The community.proxmox modules talk to the API through the proxmoxer Python library:
ansible-galaxy collection install community.proxmox
pip install proxmoxer requests
Use ansible-core 2.15 or newer on the control node.
Authenticate with an API token
Create a dedicated API token in Proxmox (Datacenter → Permissions → API Tokens) with a scoped role instead of using root@pam. Store the secret in Ansible Vault and reference the token in every task. Keep the connection details in inventory:
# inventory/pve.ini
[pve_api]
localhost ansible_connection=local
[pve_api:vars]
proxmox_api_host=pve01.lab.example.com
proxmox_api_user=automation@pve
proxmox_api_token_id=ansible
proxmox_api_token_secret='{{ vault_pve_token }}'
See also: How to Add a Disk to a VMware VM Using Ansible Playbook
Create a KVM virtual machine
- name: Provision a Proxmox KVM VM
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Create the VM
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
validate_certs: false
node: pve01
name: app-01
vmid: 110
cores: 4
memory: 8192
scsihw: virtio-scsi-pci
scsi:
scsi0: "local-lvm:32"
net:
net0: "virtio,bridge=vmbr0,tag=100"
ide:
ide2: "local:iso/ubuntu-24.04.iso,media=cdrom"
ostype: l26
state: present
- name: Start it
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve01
name: app-01
state: started
proxmox_kvm is idempotent on vmid/name: re-running the create task reports changed=false once the VM exists.
Clone a template and seed it with cloud-init
In practice you rarely install from ISO every time — you keep a cloud-init-enabled template and clone it. This is the most common real Proxmox + Ansible workflow:
- name: Clone the golden template
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve01
clone: ubuntu-2404-cloudinit # source template name
name: web-01
vmid: 0 # 0 = allocate the next free VMID
full: true
storage: local-lvm
state: present
- name: Apply cloud-init user, SSH key and static IP
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve01
name: web-01
ciuser: deploy
sshkeys: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
ipconfig:
ipconfig0: "ip=10.0.0.50/24,gw=10.0.0.1"
update: true
state: present
The guest boots fully configured — no console step. From here you switch to a normal SSH-based play (via the dynamic inventory below) to configure the OS inside the VM.
See also: Configure Ansible Dynamic Inventory for VMware in Simple Steps
Create an LXC container
- name: Create a Debian 12 LXC container
community.proxmox.proxmox:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
node: pve02
hostname: ct-runner-01
ostemplate: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
cores: 2
memory: 1024
swap: 512
disk: "local-lvm:8"
netif:
net0: "name=eth0,bridge=vmbr0,ip=dhcp"
password: "{{ vault_ct_password }}"
state: present
Trigger a backup
The proxmox_backup module starts a vzdump backup. Note its options: mode: include with a vmids list (not vmid), and backup_mode for the vzdump mode. It is not idempotent — each run starts a new backup, so drive it from a scheduled job rather than every play:
- name: Back up VMID 110 to Proxmox Backup Server
community.proxmox.proxmox_backup:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
mode: include
vmids: [110]
storage: pbs01
backup_mode: snapshot
compress: zstd
Dynamic inventory
Stop hand-maintaining host lists — the community.proxmox.proxmox inventory plugin discovers VMs and containers straight from the API:
# inventory.proxmox.yml
plugin: community.proxmox.proxmox
url: https://pve01.lab.example.com:8006
user: automation@pve
token_id: ansible
token_secret: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN') }}"
validate_certs: false
want_facts: true
Run it with ansible-inventory -i inventory.proxmox.yml --graph.
Best practices
• Use scoped API tokens, neverroot@pam, and keep the secret in Ansible Vault.
• Separate layers: community.proxmox tasks for hypervisor operations; an SSH-based play (driven by the dynamic inventory) for in-guest configuration.
• Let vmid: 0 allocate the next free ID, or keep deterministic per-environment ID blocks in inventory.
• Pair backups with Proxmox Backup Server for deduplicated daily incrementals.
FAQ
Q. Which collection provides the Proxmox modules now?
community.proxmox — install it with ansible-galaxy collection install community.proxmox. The older community.general.proxmox* names are deprecated redirects and will be removed in community.general 15.0.0.
Q. Should I use API tokens or a password?
API tokens. They are scoped to specific privileges, don't ride on a user's login session, and keep root@pam out of your playbooks.
Q. Do the modules run on the Proxmox node or the control node?
On the control node with connection: local — they call the Proxmox REST API (port 8006) over the network through proxmoxer. You don't install Ansible on the PVE host.
Q. Can I manage a whole Proxmox cluster?
Yes. Target each operation at a node with the node parameter; one control node can drive VMs and containers across every node in the cluster.
Q. How do I configure the OS inside a VM after provisioning? Clone with cloud-init (above) for the first-boot user, SSH key, and network, then run a normal SSH play against the new guest using the Proxmox dynamic inventory.
Related Articles
• Proxmox VM and container management deep-dive • build dynamic inventories (cloud and API plugins) • encrypt the API token with Ansible Vault • how Ansible inventory worksConclusion
Proxmox VE 8 is fully API-driven, and the community.proxmox collection turns that API into idempotent Ansible tasks: provision KVM VMs, clone cloud-init templates, create LXC containers, trigger backups, and discover everything with dynamic inventory. Use scoped API tokens in Vault, keep hypervisor and in-guest configuration in separate layers, and you have a repeatable, version-controlled Proxmox automation stack — on the current community.proxmox modules, not the deprecated community.general ones.
Category: installation