# Reference project — Ansible for Proxmox VE

The finished state of what participants build during the workshop. Hand it out
afterwards, use it to unblock someone who fell behind, or use it as the starting
point for a real project.

```
.
├── ansible.cfg                  # always run Ansible from this directory
├── requirements.yml             # collections
├── site.yml                     # module 04: node base state, via the role
├── inventory/
│   ├── hosts.yml                # the three nodes (static)
│   ├── lab.proxmox.yml          # module 06: guests, from the API
│   └── group_vars/
│       ├── all.yml              # operational values
│       └── pve.yml              # cluster name, root password
├── playbooks/
│   ├── 00-check.yml             # module 00/01: connectivity and PVE version check
│   ├── 10-node-prep.yml         # module 02: the flat playbook (before the role)
│   ├── 20-cluster.yml           # module 03: forms the cluster
│   └── 30-operations.yml        # module 05: storage, users, VM, backup, bridge
├── roles/pve_node/              # module 04: the same work as 10-node-prep
└── tests/                       # verification suite, see tests/README.md
```

## Prerequisites

On the control node:

- **ansible-core 2.17 or newer**, required by `community.proxmox`
- `proxmoxer` ≥ 2.3 and `requests` (`pip install --user proxmoxer requests`, or the
  distribution packages `python3-proxmoxer` and `python3-requests`)
- network access to port 8006 on the nodes

```bash
ansible-galaxy collection install -r requirements.yml
```

## Before the first run

1. Adjust the addresses in `inventory/hosts.yml`.
2. Check which storage your nodes have (`pvesm status`) and set `pve_vm_storage` in
   `inventory/group_vars/all.yml`.
3. Set the trainer root password in `inventory/group_vars/pve.yml`. In production
   that value belongs in Ansible Vault or your CI/CD secret store.
4. Verify the keyring path on a node (`ls /usr/share/keyrings/`) and, if it differs,
   override `pve_keyring` in `group_vars`.

## Running it

```bash
ansible-playbook site.yml --check --diff   # dry run
ansible-playbook site.yml                  # base state
ansible-playbook playbooks/20-cluster.yml  # form the cluster
ansible-playbook playbooks/30-operations.yml     # storage, users, VM, backup
```

Everything except the backup task is idempotent: a second run of any of these should
report `changed=0`.

## Verifying

```bash
./tests/run.sh all
```

See [`tests/README.md`](tests/README.md).

## What this is not

A production setup. Three things would have to change first:

- **`validate_certs: false`**: install certificates from your own CA (or use the
  ACME integration) and switch validation on
- **`host_key_checking = False`** in `ansible.cfg`: distribute `known_hosts` instead
- **the root password**: use an API token with the minimum privileges required;
  module 05 shows how to create one
