# infra/cloud-init — first-boot baseline templates Phase 1 **T-1.2**. The "Baseline" node lifecycle stage (docs/02 stage 2). These templates are consumed by the OpenTofu `libvirt_cloudinit_disk` in `../tofu/` (via `templatefile()`), one seed per node. **Authoring only — never applied.** Serves **R-ENV-01** (nodes are "created, baselined, cluster-joined, managed as code") and lays the kernel/OS floor ADR-0001 (k3s) + ADR-0002 (Cilium) + ADR-0003 (Longhorn) + ADR-0005 (KubeVirt) require. ## Files - `user-data.yaml.tftpl` — `#cloud-config`: login user + injected SSH **public** key, hostname, package baseline, kernel modules, sysctls, Longhorn data-disk mount, swap-off. - `meta-data.yaml.tftpl` — NoCloud instance-id / local-hostname. - `network-config.yaml.tftpl` — netplan v2 **static** IP (DHCP is off on the NAT). `${...}` tokens are **OpenTofu** template vars filled by `../tofu/main.tf` (`hostname`, `fqdn`, `username`, `ssh_authorized_key`, `ip`, `prefix`, `gateway`) — they are not cloud-init/Jinja. ## Baseline (cloud-init's job) vs. Ansible's job | cloud-init does (here) | Ansible does (T-1.3) | |---|---| | user + SSH public key, hostname | install k3s (HA, embedded etcd) | | static networking | join nodes, disable flannel/kube-proxy/traefik/servicelb | | `overlay`, `br_netfilter`, `iscsi_tcp`, `dm_crypt`, `nfs` modules | install Cilium (kube-proxy replacement, Gateway API, Hubble) | | bridge-nf + `ip_forward` sysctls, inotify limits | verify readiness | | open-iscsi + nfs-common (Longhorn client prereqs) | Flux + SOPS bootstrap handoff | | mount `/dev/vdb` at `/var/lib/longhorn` | — | | `swapoff` + strip swap from fstab | — | ### Why these specifics - **overlay / br_netfilter + bridge-nf-call sysctls** — pod networking / iptables bridging Cilium and kube-networking need. - **ip_forward / forwarding** — routing between pods, nodes, and egress. - **iscsi_tcp + open-iscsi (iscsid) and nfs / nfs-common** — Longhorn attaches volumes over iSCSI and uses the NFS client for backup/RWX (ADR-0003). - **dm_crypt** — headroom for Longhorn volume encryption. - **swap off** — kubelet/k3s expectation. - **qemu-guest-agent** — lets libvirt/tofu read guest state. Nested-virt for KubeVirt (Phase 5) comes from the tofu `host-passthrough` CPU mode, not from here.