Back to skills
SKILL.md
Ansible Proxmox
ASecurityExpert Proxmox VE automation using the community.proxmox Ansible collection for VM provisioning, template management, and cluster operations with minimal CLI usage.
- 2 stars
- 0 votes
- 0 copies
- 2 views
- Added September 11, 2026
Works with
Security analysis
100/100Pro scans all 5 files and shows the line behind each finding
npx -y skills add jcasnellie69/homelab-config --skill ansible-proxmox --agent claude-codeAre you the author of Ansible Proxmox?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/jcasnellie69-ansible-proxmox)---
name: ansible-proxmox
description: >
Expert Proxmox VE automation using the community.proxmox Ansible collection for
VM provisioning, template management, and cluster operations with minimal CLI usage.
when_to_use: >
Use when automating Proxmox VE with Ansible, creating VMs or templates, managing
Proxmox clusters, using the community.proxmox collection, or deciding between native
modules and CLI commands (pvecm, pveceph, qm).
---
# Ansible Proxmox Integration
Expert Proxmox automation using community.proxmox collection with minimal CLI usage.
## Module Selection
### Prefer Native Modules
Use `community.proxmox` modules when available:
| Operation | Use Module | NOT CLI |
|-----------|------------|---------|
| Create VM | `community.proxmox.proxmox_kvm` | `qm create` |
| Clone VM | `community.proxmox.proxmox_kvm` | `qm clone` |
| Manage users | `community.proxmox.proxmox_user` | `pveum user` |
| Manage groups | `community.proxmox.proxmox_group` | `pveum group` |
| Manage pools | `community.proxmox.proxmox_pool` | `pveum pool` |
| Manage ACLs | `community.proxmox.proxmox_acl` | `pveum acl` |
| Storage | `community.proxmox.proxmox_storage` | `pvesm` |
### When CLI is Required
Some operations lack native modules:
| Operation | Requires CLI | Reason |
|-----------|--------------|--------|
| Cluster create | `pvecm create` | No module exists |
| Cluster join | `pvecm add` | No module exists |
| CEPH init | `pveceph init` | Complex workflow |
| CEPH OSD | `pveceph osd create` | Complex workflow |
## Native Module Examples
### Create VM from Template
```yaml
- name: Create VM from template
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_token_id }}"
api_token_secret: "{{ proxmox_token_secret }}"
node: "{{ proxmox_node }}"
vmid: "{{ vm_id }}"
name: "{{ vm_name }}"
clone: "{{ template_name }}"
full: true
storage: local-lvm
memory: "{{ vm_memory | default(4096) }}"
cores: "{{ vm_cores | default(2) }}"
state: present
delegate_to: localhost
```
### Manage Proxmox User
```yaml
- name: Create Terraform user
community.proxmox.proxmox_user:
api_host: "{{ proxmox_api_host }}"
api_user: "root@pam"
api_password: "{{ proxmox_root_password }}"
userid: "terraform@pve"
comment: "Terraform automation user"
groups:
- automation
state: present
no_log: true
delegate_to: localhost
```
### Configure ACLs
```yaml
- name: Grant terraform permissions
community.proxmox.proxmox_acl:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_token_id }}"
api_token_secret: "{{ proxmox_token_secret }}"
path: "/"
users:
- terraform@pve
roles:
- Administrator
state: present
delegate_to: localhost
```
## CLI with Idempotency
When CLI is required, add proper idempotency controls:
### Cluster Formation
```yaml
- name: Check existing cluster status
ansible.builtin.command: pvecm status
register: cluster_status
failed_when: false
changed_when: false
- name: Set cluster facts
ansible.builtin.set_fact:
is_cluster_member: "{{ cluster_status.rc == 0 }}"
in_target_cluster: "{{ cluster_name in cluster_status.stdout }}"
- name: Create cluster on primary node
ansible.builtin.command: pvecm create {{ cluster_name }}
when:
- inventory_hostname == groups['proxmox'][0]
- not in_target_cluster
register: cluster_create
changed_when: cluster_create.rc == 0
- name: Join cluster on secondary nodes
ansible.builtin.command: pvecm add {{ hostvars[groups['proxmox'][0]].ansible_host }}
when:
- inventory_hostname != groups['proxmox'][0]
- not is_cluster_member
register: cluster_join
changed_when: cluster_join.rc == 0
```
### API Token Creation
```yaml
- name: Create API token
ansible.builtin.command: >
pveum user token add {{ username }}@pam {{ token_name }}
--privsep 0
register: token_result
changed_when: "'already exists' not in token_result.stderr"
failed_when:
- token_result.rc != 0
- "'already exists' not in token_result.stderr"
no_log: true
```
## Authentication Patterns
### API Token (Recommended)
```yaml
# Store token in variables or Infisical
proxmox_api_host: "192.168.1.10"
proxmox_api_user: "terraform@pve"
proxmox_token_id: "automation"
proxmox_token_secret: "{{ lookup('infisical', 'PROXMOX_TOKEN_SECRET') }}"
- name: Create VM
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_token_id }}"
api_token_secret: "{{ proxmox_token_secret }}"
# ... rest of config
```
### Root Password (Local Operations)
For operations on Proxmox nodes themselves:
```yaml
- name: Retrieve root password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'PROXMOX_ROOT_PASSWORD'
secret_var_name: 'proxmox_root_password'
- name: Configure via API
community.proxmox.proxmox_user:
api_host: "{{ inventory_hostname }}"
api_user: "root@pam"
api_password: "{{ proxmox_root_password }}"
# ... config
no_log: true
```
## Cluster Operations
### Idempotent Cluster Status Check
```yaml
- name: Get cluster status
ansible.builtin.command: pvecm status
register: cluster_status
changed_when: false
failed_when: false
- name: Get cluster nodes
ansible.builtin.command: pvecm nodes
register: cluster_nodes
changed_when: false
failed_when: false
when: cluster_status.rc == 0
- name: Set cluster facts
ansible.builtin.set_fact:
cluster_exists: "{{ cluster_status.rc == 0 }}"
cluster_node_count: "{{ cluster_nodes.stdout_lines | length | default(0) }}"
is_quorate: "{{ 'Quorate: Yes' in cluster_status.stdout | default('') }}"
```
### Verify Cluster Health
```yaml
- name: Verify cluster quorum
ansible.builtin.command: pvecm status
register: cluster_health
changed_when: false
failed_when: "'Quorate: Yes' not in cluster_health.stdout"
- name: Verify expected node count
ansible.builtin.command: pvecm nodes
register: nodes_check
changed_when: false
failed_when: nodes_check.stdout_lines | length != groups['proxmox'] | length
```
## CEPH Integration
### Initialize CEPH
```yaml
- name: Check if CEPH is initialized
ansible.builtin.command: pveceph status
register: ceph_status
changed_when: false
failed_when: false
- name: Initialize CEPH
ansible.builtin.command: >
pveceph init --network {{ ceph_network }}
when:
- inventory_hostname == groups['proxmox'][0]
- ceph_status.rc != 0
register: ceph_init
changed_when: ceph_init.rc == 0
```
### Create OSD
```yaml
- name: Check if OSD exists on device
ansible.builtin.command: >
pveceph osd list
register: osd_list
changed_when: false
- name: Create OSD
ansible.builtin.command: >
pveceph osd create {{ item }}
loop: "{{ ceph_osd_devices }}"
when: item not in osd_list.stdout
register: osd_create
changed_when: osd_create.rc == 0
```
## Network Configuration
Use `community.general.interfaces_file` for network config:
```yaml
- name: Configure VLAN-aware bridge
community.general.interfaces_file:
iface: vmbr1
option: bridge-vlan-aware
value: "yes"
backup: true
state: present
notify: reload network
- name: Set bridge ports
community.general.interfaces_file:
iface: vmbr1
option: bridge-ports
value: "bond0"
backup: true
state: present
notify: reload network
```
## Anti-Patterns
### Using CLI When Module Exists
```yaml
# BAD - Module exists for this
- name: Create user
ansible.builtin.command: pveum user add terraform@pve
# GOOD
- name: Create user
community.proxmox.proxmox_user:
api_host: "{{ proxmox_api_host }}"
api_user: "root@pam"
api_password: "{{ password }}"
userid: "terraform@pve"
state: present
```
### Missing Idempotency on CLI
```yaml
# BAD - Will fail on second run
- name: Create cluster
ansible.builtin.command: pvecm create MyCluster
# GOOD
- name: Check cluster status
ansible.builtin.command: pvecm status
register: cluster_check
changed_when: false
failed_when: false
- name: Create cluster
ansible.builtin.command: pvecm create MyCluster
when: cluster_check.rc != 0
```
### Running on Wrong Host
```yaml
# BAD - API calls from managed node
- name: Create VM
community.proxmox.proxmox_kvm:
api_host: "{{ inventory_hostname }}" # Calling itself
# ...
# GOOD - Delegate API calls to localhost
- name: Create VM
community.proxmox.proxmox_kvm:
api_host: "{{ proxmox_api_host }}"
# ...
delegate_to: localhost
```
## Installing the Collection
```bash
# Install community.proxmox
uv run ansible-galaxy collection install community.proxmox
# Or via requirements.yml
cd ansible
uv run ansible-galaxy collection install -r requirements.yml
```
## Additional Resources
For detailed Proxmox automation patterns, consult:
- **`references/ceph-automation.md`** - CEPH storage deployment and OSD management
- **`references/cluster-automation.md`** - Proxmox cluster creation and node joining
- **`references/network-automation.md`** - VLAN-aware bridges and network configuration
- **`references/community-proxmox-plugin-index.md`** - Complete community.proxmox module reference
## Related Skills
- **ansible-fundamentals** - Core module selection patterns
- **ansible-idempotency** - Making CLI commands idempotent
- **ansible-error-handling** - Error recovery for cluster operations
Files in this skill
- SKILL.md
- references/ceph-automation.md
- references/cluster-automation.md
- references/community-proxmox-plugin-index.md
- references/network-automation.md
Attribution
Comments
Loading comments…