Files
ansible-collection-infrastr…/roles/proxmox_lxc_provision/README.md
T
patrick d5cf6f656e refactor(proxmox_lxc_provision): centralize module_defaults so tasks_from works without setup
Previously the community.proxmox.proxmox / proxmox_vm_info module_defaults
were defined inline on the outer block in main.yml. Invoking individual
task files via 'tasks_from: stop' (or delete/convert/etc.) bypassed
main.yml, leaving the API parameters unset and producing
'missing required arguments: api_host, api_user' errors. The README
worked around this by telling callers to repeat the module_defaults
block at the play level — easy to forget, and duplicated config.

Extract the defaults dict into _proxmox_module_defaults in
defaults/main.yml (using a YAML anchor to share between the two
modules), and wrap every task file that calls a Proxmox module in a
block that references it. Callers only need the proxmox_* connection
vars in scope (typically group_vars/all/) — both 'roles:' and
'tasks_from:' invocations now configure the API consistently.

Files wrapped: check-exists, create, clone, update, start, stop,
delete, convert. wait/post-clone/edit-config don't call Proxmox modules
and are unchanged. main.yml's now-redundant outer module_defaults is
removed.

README updated to drop the 'Using Standalone Tasks' workaround
boilerplate.
2026-06-28 13:42:41 -04:00

7.8 KiB
Executable File

Ansible Role: proxmox_lxc_provision

Description

This Ansible role manages the provision of LXC containers and templates on a Proxmox host. By default the role will create and start an LXC container. It allows creating a new container from a container image or cloning an existing container or template container.

It also includes tasks which may be used individually:

  • clone.yml: Creates a new LXC container by cloning another container or template
  • convert.yml: Converts an LXC container to a template
  • create.yml: Creates a new LXC container
  • delete.yml: Deletes an LXC container given its vmid or hostname
  • start.yml: Starts an LXC container
  • stop.yml: Stops an LXC container
  • update.yml: Updates an existing LXC container
  • wait.yml: Waits for SSH to be available on the container
  • check-exists.yml: Checks if an LXC exists by lxc_vmid or lxc_hostname
  • post-clone.yml: Post-clone configuration (passwords, SSH host key regeneration). Runs against the new container; depends on the system_setup role.
  • edit-config.yml: Edits /etc/pve/lxc/<vmid>.conf directly to add ID mappings and NVIDIA GPU passthrough entries. Must be delegated to the Proxmox host.

Requirements

  • Ansible 2.12 or higher
  • Python 3.6 or higher
  • requests
  • proxmoxer
  • passlib

Role Variables

Required Proxmox API Variables

Variable Description Example
proxmox_api_host The IP address or hostname of the Proxmox server 192.168.1.10
proxmox_api_user The username for Proxmox authentication, typically in format username@realm ansible@pve
proxmox_api_token_id The API token ID used for authentication token
proxmox_api_token_secret The secret key associated with the API token xxx-yyy-zzz
proxmox_node The name of the Proxmox node to target pve01

Optional Proxmox API Variables

Variable Description Default
proxmox_api_port The port on which the Proxmox API is listening 8006
proxmox_api_validate_certs Whether to validate SSL certificates false
proxmox_delegate_host Inventory hostname for delegated tasks (pct commands). Use this to inherit ansible_become_password from inventory. {{ proxmox_api_host }}

Required Container Variables

Variable Description Example
lxc_template The OS template to create the LXC from. Mutually exclusive with lxc_clone_from local:vztmpl/debian-12_amd64.tar.zst
lxc_clone_from The vmid of the container or template to clone. Mutually exclusive with lxc_template 201
lxc_hostname The hostname for the container my-container
lxc_vmid The VM ID for the container 100

Optional Container Variables

Variable Description Default
lxc_clone_type Clone type when using lxc_clone_from full
lxc_storage Target storage for the container local-zfs
lxc_size Disk size in GB 16
lxc_disk The target storage and storage size local-zfs:16
lxc_root_password Password for the root account. On creates from lxc_template it is set via the Proxmox API; on clones it is applied inside the container by post-clone.yml. -
lxc_user_name Name of an additional non-root user to manage in post-clone.yml (clone path only). admin
lxc_user_password Password for lxc_user_name. Only applied on the clone path via post-clone.yml. The user must already exist in the source template. -
lxc_cores The number of CPU cores 4
lxc_memory Memory size in MB 2048
lxc_swap Swap memory size in MB 2048
lxc_ipv4 The IPv4 address dhcp
lxc_ipv6 The IPv6 address auto
lxc_gateway The default gateway 10.0.0.1
lxc_nameserver DNS nameserver 10.0.0.7
lxc_bridge Linux bridge on the Proxmox host to attach the container to vmbr0
lxc_iface_name Interface name inside the container eth0
lxc_vlan_tag 802.1Q VLAN tag (integer 1-4094). Omitted from netif when unset. -
lxc_pubkey_file Path to SSH public key file ~/.ssh/id_ed25519.pub
lxc_features List of container features ["nesting=1"]
lxc_tags Tags for the container ["ansible-managed"]
lxc_start Start container after creation true
lxc_unprivileged Create as an unprivileged container true
lxc_mounts Dict of additional bind mounts (e.g. { mp0: "/srv/data,mp=/data" }) -
lxc_onboot Start container on Proxmox host boot false
lxc_startup Startup order string passed to Proxmox (e.g. order=1,up=30) -
lxc_timezone Timezone inside the container (e.g. Europe/Berlin) -
lxc_nvidia_gpu_mount Add NVIDIA GPU passthrough entries via edit-config.yml false
gpu_device_id Major device number for /dev/nvidia* (required when lxc_nvidia_gpu_mount is true) -
uvm_device_id Major device number for /dev/nvidia-uvm* (required when lxc_nvidia_gpu_mount is true) -
lxc_id_mappings Multi-line lxc.idmap: block written into the container config by edit-config.yml -

Example Playbook

Prerequisites

Set up your Proxmox API connection variables in group vars:

# group_vars/all.yml
proxmox_api_host: "10.0.1.1"
proxmox_api_port: 8006
proxmox_api_user: "automation@pve"
proxmox_api_token_id: "mytoken"
proxmox_api_token_secret: "{{ vault_proxmox_token }}"
proxmox_api_validate_certs: false
proxmox_node: "pve01"
proxmox_delegate_host: "proxmox_server"  # inventory hostname for become_password

Creating a new LXC from template

- name: Create and start an LXC container
  hosts: localhost
  connection: local
  vars:
    lxc_vmid: 100
    lxc_hostname: new-debian-container
    lxc_template: "local:vztmpl/debian-12_amd64.tar.zst"
    lxc_ipv4: "10.0.0.99/24"
  roles:
    - role: proxmox_lxc_provision

Creating a new LXC by cloning an existing container

- name: Clone an LXC container
  hosts: localhost
  connection: local
  vars:
    lxc_vmid: 101
    lxc_hostname: cloned-container
    lxc_clone_from: 200
    lxc_ipv4: "10.0.0.100/24"
  roles:
    - role: proxmox_lxc_provision

Idempotent Behavior

The role includes idempotency checking. If a container with the specified lxc_vmid or lxc_hostname already exists, the role will skip provisioning and exit gracefully. Sets lxc_exists fact for use in subsequent tasks.

Using Standalone Tasks

Individual task files (stop, start, delete, convert, etc.) can be invoked via tasks_from directly — each task file wraps its work in a block with the role's shared module_defaults, so the Proxmox API connection is configured automatically as long as the proxmox_* connection variables are in scope (typically from group_vars/all/).

- name: Convert container to a template
  hosts: localhost
  tasks:
    - include_role:
        name: proxmox_lxc_provision
        tasks_from: convert
      vars:
        lxc_hostname: my-container

Creating an LXC Container and Converting it to a Template

---
- name: Create and start an LXC container
  hosts: localhost
  connection: local
  vars:
    lxc_vmid: "{{ lxc_vmid }}"
    lxc_hostname: "{{ lxc_hostname }}"
    lxc_template: "local:vztmpl/debian-12_amd64.tar.zst"
    lxc_ipv4: "10.0.0.99/24"
  roles:
    - role: proxmox_lxc_provision

# Run configuration tasks on the container...

- name: Convert the created container to a template
  hosts: localhost
  tasks:
    - include_role:
        name: proxmox_lxc_provision
        tasks_from: convert
      vars:
        lxc_hostname: "{{ lxc_hostname }}"