personal_infra/tofu/nodito/README.md

79 lines
3.4 KiB
Markdown
Raw Normal View History

2025-10-31 08:54:18 +01:00
## Nodito VMs with OpenTofu (Proxmox)
This directory lets you declare VMs on the `nodito` Proxmox node and apply with OpenTofu. It clones the Ansible-built template `debian-13-cloud-init` and places disks on the ZFS pool `proxmox-tank-1`.
### Prereqs
- Proxmox API token with VM privileges. Example: user `root@pam`, token name `tofu`.
- OpenTofu installed.
```
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://get.opentofu.org/opentofu.gpg | sudo tee /etc/apt/keyrings/opentofu.gpg >/dev/null
curl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | sudo gpg --no-tty --batch --dearmor -o /etc/apt/keyrings/opentofu-repo.gpg >/dev/null
sudo chmod a+r /etc/apt/keyrings/opentofu.gpg /etc/apt/keyrings/opentofu-repo.gpg
echo \
"deb [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any main
deb-src [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] https://packages.opentofu.org/opentofu/tofu/any/ any main" | \
sudo tee /etc/apt/sources.list.d/opentofu.list > /dev/null
sudo chmod a+r /etc/apt/sources.list.d/opentofu.list
sudo apt-get update
sudo apt-get install -y tofu
tofu version
```
- The Ansible template exists: `debian-13-cloud-init` (VMID 9001 by default).
### Provider Auth
Credentials are the only thing not in git. Copy `terraform.tfvars.example` to
`terraform.tfvars` (gitignored) and set:
2025-10-31 08:54:18 +01:00
- `proxmox_api_url` (e.g. `https://nodito:8006/api2/json`)
- `proxmox_api_token_id` (e.g. `root@pam!tofu`)
- `proxmox_api_token_secret`
Alternatively, export them as `TF_VAR_proxmox_api_token_secret` etc.
2025-10-31 08:54:18 +01:00
### Declare VMs
VMs are declared in `vms.auto.tfvars`, which is committed. `*.auto.tfvars` is
loaded automatically, so it needs no `-var-file`. Example entry:
2025-10-31 08:54:18 +01:00
```
vms = {
web1 = {
name = "web1"
cores = 2
memory_mb = 2048
disk_size_gb = 20
ipconfig0 = "ip=dhcp" # or "ip=192.168.1.50/24,gw=192.168.1.1"
}
}
```
All VM disks are created on `zfs_storage_name` (defaults to `proxmox-tank-1`). Network attaches to `vmbr0`. VLAN can be set per-VM with `vlan_tag`.
### Usage
```
tofu init
tofu plan
tofu apply
2025-10-31 08:54:18 +01:00
```
`terraform.tfvars` and `vms.auto.tfvars` are both auto-loaded.
2025-10-31 08:54:18 +01:00
2025-12-01 11:17:02 +01:00
> VMs are created once and then protected: the module sets `lifecycle.prevent_destroy = true` and ignores subsequent config changes. After the initial apply, manage day2 changes directly in Proxmox (or remove the lifecycle block if you need OpenTofu to own ongoing updates).
2025-10-31 08:54:18 +01:00
### Notes
- Clones are full clones by default (`full_clone = true`).
- Cloud-init injects `cloud_init_user` and `ssh_authorized_keys`.
- `.terraform.lock.hcl` is committed: it pins the provider hashes, which matters
because `versions.tf` tracks a release candidate (`3.0.2-rc05`).
- State is local (`terraform.tfstate`, gitignored) and has no remote backend, so
it exists only on the machine that last ran `tofu apply`.
- The map is not a complete inventory of nodito: state also manages
`bastion-box` (1100) and `nonkeiwaisi-box` (3300), which are not declared in
`vms.auto.tfvars`. `tofu plan` is clean today, but relaxing the `lifecycle`
block without first declaring them would put them up for destruction.
2025-10-31 08:54:18 +01:00
- Disks use `scsi0` on ZFS with `discard` enabled.