#cloud-config # 1. Hostname configuration hostname: ${hostname} fqdn: ${hostname} preserve_hostname: false # 2. User creation # # Unlike Alpine, sshd on Debian/Ubuntu/Rocky is built with PAM, which accepts # pubkey auth even when the shadow entry is locked ("!"). So the Alpine # /etc/shadow workaround is NOT needed here. # # Groups: # - Debian/Ubuntu: sudo group grants admin rights # - Rocky/RHEL: wheel group grants admin rights # We include both so the same template works for all supported distros; cloud- # init silently skips groups that don't exist on the target system. # (The "admin" group is intentionally NOT included: it was deprecated on # Ubuntu 12.04 and absent on RHEL-family distros.) users: - name: ${username} sudo: ALL=(ALL) NOPASSWD:ALL groups: [sudo, wheel] shell: /bin/bash lock_passwd: true ssh_authorized_keys: - ${ssh_key} # 3. System update package_update: true package_upgrade: true # 4. Package installation packages: - qemu-guest-agent - curl # 5. Services and Tailscale # Order matters: qemu-guest-agent FIRST so Terraform can read the VM IP # without waiting for the (potentially slow) Tailscale install. runcmd: # Enable and start qemu-guest-agent (systemd) - [ systemctl, enable, qemu-guest-agent, --now ] # Install Tailscale (official installer detects the distro) - [ sh, -c, "curl -fsSL https://tailscale.com/install.sh | sh" ] # Bring the node up on the tailnet. Retry a few times to absorb the small # delay between `systemctl start tailscaled` and the daemon's socket being # ready to accept commands. - [ sh, -c, "for i in 1 2 3 4 5; do tailscale up --authkey=${tailscale_auth_key} --hostname=${vm_name} && break; sleep 2; done" ]