# Changelog 2026-07-09 -- OpenTofu cloud-init/base-image VM modules (DOCFIX-145)

No live infrastructure touched -- unapplied IaC source only. Continues the
DOCFIX-142/144 OpenTofu scaffold.

## Item

### 1. DOCFIX-145 -- `opentofu/modules/base-image` + `opentofu/modules/cloudinit-vm`
FILES (new): `opentofu/modules/base-image/{main,variables,outputs}.tf`,
`opentofu/modules/cloudinit-vm/{main,variables,outputs}.tf`.

WHAT: the second VM-creation pattern this repo needs, for Office1's own
service VMs (MAAS-region, NetBox, GitBucket -- D-103), genuinely distinct
from `modules/node-vm`'s blank-disk PXE pattern (that one is for MAAS-managed
OpenStack nodes MAAS itself images after enlistment; these are self-managed
VMs that need a real bootable OS + cloud-init). Split into two modules
matching how the provider's own real example separates concerns:
`base-image` downloads one shared cloud image once (`libvirt_volume` with
`create.content.url`); `cloudinit-vm` creates a per-instance copy-on-write
overlay disk (`backing_store`), a `libvirt_cloudinit_disk` NoCloud seed, and
the domain referencing both.

VERIFICATION: every resource/attribute shape used is taken directly from
`examples/alpine_cloudinit.tf` (fetched and read as real, runnable code last
turn while building the node-VM module) -- the same high-confidence source
that surfaced the syntax-bug fix in DOCFIX-144. One design choice improved
during authoring: the base image's `.path` is threaded across the module
boundary as a real output/input (`module.<base-image>.path` ->
`cloudinit-vm`'s `base_volume_path` variable) rather than reconstructed from
a pool name + volume name string, avoiding an unconfirmed path-convention
guess entirely.

DELIBERATELY NOT DONE:
- **`user_data`/`meta_data`/`network_config` have no defaults and no generic
  fallback content.** What Office1's three service VMs actually need
  installed/configured is real design work that hasn't happened; a
  plausible-looking default (e.g. the common `dhcp4: true` netplan stanza)
  would also silently fail here regardless, since this repo's plane networks
  carry no libvirt-managed DHCP (NetBox is the IPAM apex).
- **OPNsense applicability is explicitly NOT confirmed.** This whole
  cloud-init/NoCloud mechanism is standard for Linux cloud images; OPNsense
  is FreeBSD-based, and its support for the same mechanism was not checked
  this session. Flagged prominently in both modules' headers and
  `opentofu/README.md` -- do not assume `cloudinit-vm` covers OPNsense
  without verifying that specifically first.
- **Neither module instantiated in root `main.tf`.** No image source has
  been chosen for any Office1 service VM.

Workflow doc (`docs/dc-dc-deployment-workflow.md`) Stage 2 authoring status,
gap register items 2 and 4, and the status summary table updated to match;
companion visual tracker (same Artifact URL) redeployed.

HARNESS: none added -- pure `.tf` source, same as the prior OpenTofu
deliveries; `scripts/opentofu-validate.sh` covers all of `opentofu/`
generically once a `tofu` binary is available to run it.

REVERT: `git rm -r opentofu/modules/base-image opentofu/modules/cloudinit-vm`;
revert the workflow-doc sections listed above if reverting fully.

## Next actionable step (unchanged, still logged not actioned)

Same as DOCFIX-144: on a machine with the `tofu` binary and registry network
access, run `bash scripts/opentofu-validate.sh` against all of `opentofu/`,
then `tofu providers schema -json` to confirm the remaining unverified
details (the `boot`-order shape in `node-vm`; whether `libvirt_cloudinit_disk`
+ this whole pattern actually produces a bootable OPNsense image, which needs
a real test boot, not just a schema check).
