No description
  • Python 98.9%
  • Jinja 1.1%
Find a file
Jesus Alejandro Sanchez Davila 685880ba5e Updates and improvements
2026-08-29 22:07:37 +02:00
changelogs Updates and improvements 2026-08-29 22:07:37 +02:00
meta Initial commit 2026-05-19 23:16:43 +02:00
playbooks Multiple improvements 2026-07-20 10:09:23 +02:00
plugins/lookup Updates and improvements 2026-08-29 22:07:37 +02:00
roles Updates and improvements 2026-08-29 22:07:37 +02:00
.gitignore Initial commit 2026-05-19 23:16:43 +02:00
AGENT.md Updates and improvements 2026-08-29 22:07:37 +02:00
galaxy.yml Updates and improvements 2026-08-29 22:07:37 +02:00
README.md Multiple improvements 2026-07-20 10:09:23 +02:00
requirements.yml Updates and improvements 2026-08-29 22:07:37 +02:00

silvarion.provision

Ansible collection for declarative, parallelized infrastructure provisioning on Proxmox.

The collection reads a structured infrastructure repository (local path or git URL), dynamically registers matching hosts, and runs a three-play pipeline:

  1. Provision — for each registered host, run its silvarion.provision.* roles (e.g. proxmox) with connection: local to create the LXC container/VM.
  2. Prepare the controller — install (via ansible-galaxy) any tech role or collection referenced by a created host that isn't already installed.
  3. Configure — SSH into each created container/VM and run the rest of its ansible_roles_list (the tech roles: mysql, redis, etc.).

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

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 inventory role (via the env_parser lookup plugin) expects a structured YAML repository that serves as the single source of truth for your infrastructure. playbook_env_source (or inventory_env_source when using the role directly) 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., lxc | vms
          <tech>/                        # e.g., mysql | redis | netbox
            <purpose>/                   # e.g., main | dev | public
              group_vars/
                all.yml                  # Layer 4: leaf instance variables (REQUIRED)

Legacy leaves (all.yml directly under <tech>/, with no <purpose> level) are still recognized — purpose defaults to main for those.

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>/<purpose>/group_vars/all.yml Instance variables

Higher layers override lower layers via recursive merge. The fully merged variable dict is stored as provision_unit on each registered host.

Example all.yml (leaf)

# proxmox/pve01/base/lxc/mysql/main/group_vars/all.yml
ansible_host: 10.0.0.110
proxmox_node: pve01
ansible_roles_list:
  - name: my_namespace.mysql
    mysql_port: 3306
    mysql_root_pswd: "{{ vault_mysql_root_pswd }}"

silvarion.provision.proxmox (the platform provisioning role) is prepended to ansible_roles_list automatically — via inventory_default_provision_roles — so leaf files only need to list their tech roles.

To run only a subset of a host's ansible_roles_list for a given invocation (e.g. re-configuring just one tech role without touching the leaf all.yml), set ansible_target_roles_list to an allowlist of role names/roles as a host var or extra-var. It only affects the tech configuration play (roles applied on the target hosts via SSH); leaving it unset or empty runs every role in ansible_roles_list as before.

ansible-playbook silvarion.provision.main \
  -e playbook_env_source=/opt/infra/testlab \
  -e '{"ansible_target_roles_list": ["my_namespace.mysql"]}' \
  --tags tech

Example metadata.yml (platform level)

# proxmox/metadata.yml
proxmox_api_host: 192.168.1.10
proxmox_api_user: root@pam
proxmox_api_token_id: ansible
proxmox_subnet_prefix: "10.0.0"
proxmox_gateway: "10.0.0.1"
proxmox_bridge: vmbr0

Usage

Running the main playbook

# Deploy everything in testlab on all nodes
ansible-playbook silvarion.provision.main \
  -e playbook_env_source=/opt/infra/testlab \
  -e playbook_platform=proxmox \
  -e playbook_node=all \
  -e playbook_category=all \
  -e playbook_server_type=all \
  -e playbook_tech=all

# Deploy only MySQL containers on pvetest, base category
ansible-playbook silvarion.provision.main \
  -e playbook_env_source=/opt/infra/testlab \
  -e playbook_platform=proxmox \
  -e playbook_node=pvetest \
  -e playbook_category=base \
  -e playbook_server_type=lxc \
  -e playbook_tech=mysql

# Delete all base containers on pvetest (requires explicit confirmation)
ansible-playbook silvarion.provision.main \
  -e playbook_env_source=/opt/infra/testlab \
  -e playbook_platform=proxmox \
  -e playbook_node=pvetest \
  -e playbook_category=base \
  -e playbook_server_type=lxc \
  -e playbook_tech=all \
  -e playbook_action=delete \
  -e playbook_confirm_delete=true

# Run only the tech configuration phase (assumes containers/VMs already exist)
ansible-playbook silvarion.provision.main \
  -e playbook_env_source=/opt/infra/testlab \
  --tags tech

Using the inventory role individually

# In your own playbook
- name: Build inventory from an environment directory
  hosts: localhost
  gather_facts: false
  roles:
    - role: silvarion.provision.inventory
      vars:
        inventory_env_source: /opt/infra/testlab
        inventory_platform: proxmox
        inventory_node: pvetest
        inventory_category: base
        inventory_server_type: lxc
        inventory_tech: mysql

See roles/inventory/README.md and roles/proxmox/README.md for each role's full variable reference — kept there, next to the code, instead of duplicated here where it drifts out of sync.


Playbook Structure

File What it does
playbooks/main.yml Entry point — imports dynamic_inventory.yml then infra_work.yml
playbooks/dynamic_inventory.yml Runs the inventory role to parse the env dir and register hosts
playbooks/infra_work.yml 3 plays: provision (Play 1), install missing tech roles on the controller (Play 2, tag tech), configure via SSH (Play 3, tag tech)
playbooks/tech/run_role.yml Shared include_tasks — promotes one ansible_roles_list entry's vars, then include_role

Run only the tech-configuration phase (Play 2 + Play 3) with --tags tech, which assumes the containers/VMs from Play 1 already exist.


Playbook-level Variables (playbook_*)

Set as -e on silvarion.provision.main; each maps to the underlying role variable for that play.

Variable Default Description
playbook_env_source (required) Local path or git URL to the environment directory
playbook_domain "" Domain suffix passed to the inventory role
playbook_platform proxmox Scope filter: platform subdirectory name, or all
playbook_node all Scope filter: node name, or all
playbook_category all Scope filter: category name, or all
playbook_server_type all Scope filter: lxc, vms, or all
playbook_tech all Scope filter: tech stack name, or all
playbook_purpose all Scope filter: purpose name, or all
playbook_action create create or delete
playbook_confirm_delete false Must be true to allow playbook_action=delete
playbook_throttle 1 Max concurrent provisioning operations
playbook_bootstrap true Run the proxmox role's LXC bootstrap steps
playbook_secure_logging true no_log on tasks handling secrets
playbook_debug false Verbose debug output

ansible_roles_list and ansible_target_roles_list are set per-host (leaf all.yml / host vars / -e), not as playbook_* vars — see Infrastructure Repository Structure above.


Sensitive Variables

Never store these in plaintext. Use ansible-vault, environment variables, or a secrets lookup (silvarion.provision.openbao / silvarion.secrets.openbao):

# Via ansible-vault encrypted group_vars
ansible-vault encrypt_string 'my-api-secret' --name proxmox_api_token_secret
# Or via an OpenBao lookup inline in a leaf all.yml — evaluated lazily,
# raises AnsibleError (not an empty string) if the lookup fails
proxmox_api_token_secret: "{{ lookup('silvarion.provision.openbao',
  server='https://openbao.example.com:8200',
  path='proxmox/ansible', key='api_token_secret',
  action='read') }}"

Collection Structure

silvarion.provision/
├── galaxy.yml                    # Collection metadata and dependencies
├── meta/
│   └── runtime.yml               # Ansible version requirement
├── plugins/
│   └── lookup/
│       ├── env_parser.py         # Walks the env dir, merges the 4-layer hierarchy
│       └── openbao.py            # OpenBao KV read/write/generate lookup
├── playbooks/
│   ├── main.yml                  # Entry point
│   ├── dynamic_inventory.yml     # Inventory registration
│   ├── infra_work.yml            # 3-play provision/install/configure pipeline
│   ├── tech/run_role.yml         # Shared per-role include
│   └── plugin_test.yml           # End-to-end test for the openbao lookup
├── requirements.yml               # Dependency installation shortcut
└── roles/
    ├── inventory/                 # Parse env dir, register hosts
    └── proxmox/                   # Create/delete LXC containers and VMs

License

MIT

Author

Jesus Alejandro Sanchez Davila jsanchez.consultant@gmail.com