Seed Inventory #
Before any host can be PXE booted, its definition must exist in the Ansible inventory. MAC addresses, IP assignments, DNS records, and DHCP reservations are all driven from host_vars.
Repository: ansible-inventory-deevnet
When This Is Required #
| Scenario | Action |
|---|---|
| Capacity expansion | Add host to hosts.yml, create new host_vars/<hostname>.yml |
| Hardware replacement | Update MAC address in existing host_vars/<hostname>.yml |
| Greenfield build | All hosts need both steps |
Inventory Structure #
ansible-inventory-deevnet/
└── mobile/
├── hosts.yml # Main inventory (hosts and group memberships)
├── group_vars/ # Variables by group
└── host_vars/ # Per-host variables (MAC, IP, DNS, DHCP)
├── dv02hyp001p01.yml
├── dv02hyp002p02.yml
└── ...
Adding a New Host (Expansion) #
1. Add to hosts.yml #
Add the hostname to appropriate groups:
hypervisors:
hosts:
dv02hyp001p01: {}
dv02hyp002p02: {}
dv02hyp003p01: {} # new host
2. Create host_vars file #
Create host_vars/<hostname>.yml with infrastructure and environment data:
infrastructure:
form: hv
interfaces:
eth0:
mac: "aa:bb:cc:dd:ee:ff"
env:
interfaces:
eth0:
ip: 10.20.99.23
purpose: mgmt
segment: management
dns:
host_a_record: true
dhcp_reservation: true
3. Apply configuration #
# DNS record and DHCP reservation on the core router
cd ansible-collection-deevnet.net
make dns
make dhcp
# PXE boot config on the Builder, if the host will network-boot
cd ansible-collection-deevnet.builder
ansible-playbook playbooks/site.yml --limit bootstrap_nodes
Updating for Hardware Replacement #
When replacing hardware (new NIC = new MAC address), update the existing host_vars file:
infrastructure:
interfaces:
eth0:
mac: "d8:9e:f3:7d:94:c4" # updated MAC, read off the new NIC
Then apply configuration as above.
Management-Hypervisor VMs Are Different #
Everything above assumes a MAC is a hardware fact you can read off a NIC. A management-hypervisor VM has no NIC to read until something creates one, so its MAC is derived from its Proxmox VMID and written into inventory by a tool rather than typed in by hand.
Such a host uses a host_vars directory, with the generated values in their own file:
mobile/host_vars/dv02tdn001v01/
├── vars.yml # hand-written
└── identity.yml # GENERATED - do not edit
vars.yml references the generated values and defaults them, so the file parses
before an identity exists:
infrastructure:
form: vm
interfaces:
eth0:
mac: "{{ deevnet_assigned_mac | default('') }}"
mgmt_vm:
vmid: "{{ deevnet_assigned_vmid | default(0) }}"
Then allocate the identity, which writes identity.yml:
cd ansible-collection-deevnet.mgmt
make vm-identity-assign
Full procedure, including why allocation must precede the DHCP reservation and the VM’s first boot: Allocate VM Identity.
Workstation Users #
Hosts in the workstations group get the operator accounts listed in dev_users, in group_vars/workstations.yml:
dev_users:
- name: cdeever
primary_group: cdeever
extra_groups:
- wheel
home: /home/cdeever
github_keys_url: "https://github.com/cdeever.keys"
The workstation role in deevnet.builder creates each account and installs its SSH keys from github_keys_url.
Host Variables Reference #
| Path | Purpose |
|---|---|
infrastructure.form | Device type (hv, rt, sw, ap, etc.) |
infrastructure.interfaces.<iface>.mac | MAC address |
mgmt_vm.vmid | Proxmox VMID (management-hypervisor VMs only; source of the MAC) |
env.interfaces.<iface>.ip | IP address (or dhcp) |
env.interfaces.<iface>.segment | Network segment name |
env.interfaces.<iface>.dns.host_a_record | Create DNS A record |
env.interfaces.<iface>.dns.dhcp_reservation | Create DHCP reservation |
env.interfaces.<iface>.dns.cnames | List of CNAME aliases |