- Python 98.8%
- Jinja 1.2%
| changelogs | ||
| meta | ||
| playbooks | ||
| plugins/lookup | ||
| roles | ||
| .gitignore | ||
| AGENT.md | ||
| galaxy.yml | ||
| README.md | ||
| requirements.yml | ||
silvarion.provision
Ansible collection for declarative, parallelized infrastructure provisioning on Proxmox.
The collection uses a two-role pipeline:
prepare— reads a structured infrastructure repository (local or git), resolves a 4-layer variable hierarchy, and builds a flat deployment plan with dynamically-registered inventory hosts.apply— executes that plan across three scopes: image downloads, container/VM lifecycle, and technology-stack configuration.
Requirements
| Requirement | Version |
|---|---|
| Ansible | >= 2.14 |
community.proxmox |
>= 1.0.0 |
Installation
From a git repository
# Install directly from git
ansible-galaxy collection install \
git+https://git.silvarion.org/ansible-collections/silvarion.provision.git
# Install a specific branch or tag
ansible-galaxy collection install \
git+https://git.silvarion.org/ansible-collections/silvarion.provision.git,main
From a local clone
git clone https://git.silvarion.org/ansible-collections/silvarion.provision.git
ansible-galaxy collection install ./silvarion.provision/ --force
Via requirements.yml (recommended)
Create a requirements.yml in your project:
collections:
- name: https://git.silvarion.org/ansible-collections/silvarion.provision.git
type: git
version: main
- name: community.proxmox
version: ">=1.0.0"
Then install:
ansible-galaxy collection install -r requirements.yml
Infrastructure Repository Structure
The prepare role expects a structured YAML repository that serves as the single source of truth for your infrastructure. The prepare_env_source variable points to the root of an environment directory (e.g., infra/testlab/).
<env_dir>/
<platform>/ # e.g., proxmox
metadata.yml # Layer 1: provider-wide defaults
defaults/
<tech>.yml # Layer 2: per-tech resource profiles
<node>/ # e.g., pve01
metadata.yml # Layer 3: node-specific overrides
<category>/ # e.g., base | monitoring | comms
<server_type>/ # e.g., ct | vm
<tech>/ # e.g., mysql | redis | netbox
all.yml # Layer 4: leaf instance variables (REQUIRED)
Variable Precedence (lowest → highest)
| Layer | File | Purpose |
|---|---|---|
| 1 | <platform>/metadata.yml |
Provider-wide defaults (subnet, VMID range, SSH keys) |
| 2 | <platform>/defaults/<tech>.yml |
Per-tech resource profile (cores, memory, disk) |
| 3 | <platform>/<node>/metadata.yml |
Node-specific overrides |
| 4 | <platform>/<node>/<category>/<server_type>/<tech>/all.yml |
Instance variables |
Higher layers override lower layers via recursive merge. All merged variables — plus computed fields (hostname, VMID, IP) — are stored as provision_unit on each guest host.
Example all.yml (leaf)
# proxmox/pve01/base/ct/mysql/all.yml
instances: 2
vmid_start: 200
ip_octet_start: 110
ansible_roles_list:
- role: my_namespace.mysql
mysql_port: 3306
mysql_root_pswd: "{{ vault_mysql_root_pswd }}"
Example metadata.yml (platform level)
# proxmox/metadata.yml
proxmox_node: pve01
proxmox_api_host: 192.168.1.10
proxmox_api_user: root@pam
proxmox_api_token_id: ansible
proxmox_default_subnet_prefix: "10.0.0"
proxmox_default_gateway: "10.0.0.1"
proxmox_default_bridge: vmbr0
Usage
Running the main playbook
# Deploy everything in testlab on all nodes
ansible-playbook silvarion.provision.main \
-e prepare_env_source=/opt/infra/testlab \
-e prepare_platform=proxmox \
-e prepare_node=all \
-e prepare_category=all \
-e prepare_server_type=all \
-e prepare_tech=all
# Deploy only MySQL containers on pvetest, base category (from git)
ansible-playbook silvarion.provision.main \
-e prepare_env_source=https://git.example.com/infra/testlab \
-e prepare_env_branch=staging \
-e prepare_platform=proxmox \
-e prepare_node=pvetest \
-e prepare_category=base \
-e prepare_server_type=ct \
-e prepare_tech=mysql
# Delete all base containers on pvetest (requires explicit confirmation)
ansible-playbook silvarion.provision.main \
-e prepare_env_source=/opt/infra/testlab \
-e prepare_platform=proxmox \
-e prepare_node=pvetest \
-e prepare_category=base \
-e prepare_server_type=ct \
-e prepare_tech=all \
-e apply_action=delete \
-e apply_confirm_delete=true
# Run only the images phase
ansible-playbook silvarion.provision.main \
-e prepare_env_source=/opt/infra/testlab \
--tags images
# Run only the tech configuration phase (assumes hosts already exist)
ansible-playbook silvarion.provision.main \
-e prepare_env_source=/opt/infra/testlab \
--tags tech
Using roles individually
# In your own playbook
- name: Build provision plan
hosts: localhost
gather_facts: false
roles:
- role: silvarion.provision.prepare
vars:
prepare_env_source: /opt/infra/testlab
prepare_platform: proxmox
prepare_node: pve01
prepare_category: base
prepare_server_type: ct
prepare_tech: mysql
Variables Reference
prepare role
| Variable | Default | Required | Description |
|---|---|---|---|
prepare_env_source |
"" |
Yes | Local path or git URL to the environment directory |
prepare_env_branch |
main |
No | Git branch (only used when env_source is a URL) |
prepare_env_workdir |
/tmp/provision/envs |
No | Local directory for git clones |
prepare_platform |
proxmox |
No | Scope filter: platform subdirectory name |
prepare_node |
all |
No | Scope filter: node name or all |
prepare_category |
all |
No | Scope filter: category name or all |
prepare_server_type |
all |
No | Scope filter: ct, vm, or all |
prepare_tech |
all |
No | Scope filter: tech stack name or all |
prepare_proxmox_group |
provision_proxmox_nodes |
No | Inventory group for Proxmox API nodes |
prepare_guests_group |
provision_guests |
No | Inventory group for guest hosts |
prepare_guest_user |
sysadmin |
No | SSH user for guest connections |
apply role
| Variable | Default | Required | Description |
|---|---|---|---|
apply_action |
create |
No | create or delete |
apply_scope |
infra |
No | images, infra, or tech (set per-play) |
apply_parallel_creates |
true |
No | Use async for container/VM shell creation |
apply_async_timeout |
600 |
No | Timeout (seconds) for async create operations |
apply_async_poll |
10 |
No | Polling interval (seconds) for async jobs |
apply_confirm_delete |
false |
No | Must be true to allow apply_action=delete |
proxmox_api_token_secret |
— | Yes | Proxmox API token secret (use vault) |
proxmox_ssh_root_key |
— | Yes | Root SSH public key for containers/VMs |
proxmox_ssh_sysadmin_key |
— | Yes | Sysadmin SSH public key |
Playbook Tags
| Tag | Phase | What it runs |
|---|---|---|
images |
Phase 2a | Download OS templates and cloud images |
infra |
Phase 2b | Create or delete LXC containers and VMs |
lxc |
Phase 2b | LXC container operations only |
vm |
Phase 2b | VM operations only |
tech |
Phase 3 | Run ansible_roles_list on guest hosts |
Computed Instance Variables
The prepare role auto-computes the following for each instance:
| Variable | Formula | Example |
|---|---|---|
hostname |
srv-<server_type>-<category>-<tech>-<NN> |
srv-ct-base-mysql-01 |
vmid |
vmid_start + (instance_index - 1) |
200 |
ip_address |
<subnet_prefix>.<ip_octet_start + idx> |
10.0.0.110 |
ip_cidr |
ip_address/<netmask> |
10.0.0.110/24 |
Sensitive Variables
Never store these in plaintext. Use ansible-vault or environment variables:
# Via ansible-vault encrypted group_vars
ansible-vault encrypt_string 'my-api-secret' --name proxmox_api_token_secret
# Or export as environment variables (picked up via lookup('env', ...))
export PROXMOX_API_TOKEN_SECRET=my-api-secret
Collection Structure
silvarion.provision/
├── galaxy.yml # Collection metadata and dependencies
├── meta/
│ └── runtime.yml # Ansible version requirement
├── playbooks/
│ └── main.yml # Main 3-phase orchestration playbook
├── requirements.yml # Dependency installation shortcut
└── roles/
├── prepare/ # Phase 1: planning and variable resolution
│ ├── defaults/main/
│ │ └── options.yml
│ ├── meta/main.yml
│ └── tasks/
│ ├── main.yml # Orchestrator
│ ├── env.yml # Resolve env source (local or git clone)
│ ├── discover.yml # Walk tree, apply scope filters
│ ├── load_vars.yml # Load 4-layer hierarchy per leaf
│ └── build_plan.yml # Expand instances, register inventory
└── apply/ # Phase 2: execution
├── defaults/main/
│ └── options.yml
├── meta/main.yml
└── tasks/
├── main.yml # Dispatcher (scope router)
├── images.yml # Download OS templates
├── lxc.yml # LXC container lifecycle
├── vm.yml # VM lifecycle
└── tech.yml # Technology stack configuration
License
MIT
Author
Jesus Alejandro Sanchez Davila jsanchez.consultant@gmail.com