profile picture

Deploying a Cloud-Init Ubuntu on Proxmox

October 17, 2023 - blogging beginner

I wanted a reusable template for a VM that can easily be deployed and automatically get connected to my Tailnet as soon as it receives internet connection. To future me, here's how I created it:

wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img -O /var/lib/vz/template/iso/jammy-server-cloudimg-amd64.img
qm create 9000 --memory 2048 --net0 virtio,bridge=vmbr0,firewall=1
qm importdisk 9000 /var/lib/vz/template/iso/jammy-server-cloudimg-amd64.img local-lvm
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0
qm set 9000 --ide2 local-lvm:cloudinit
qm set 9000 --boot c --bootdisk scsi0
qm set 9000 --serial0 socket --vga serial0
qm template 9000

Now that the template is ready, time to configure Proxmox so that it can store snippets that will be used for custom Cloud-Init settings.

pvesm set local --content images,rootdir,vztmpl,backup,iso,snippets

Next is to prepare the config files.

cat << EOF > /var/lib/vz/snippets/userdata.yaml
#cloud-config
hostname: cloudinit-jammy
manage_etc_hosts: true
user: omada
password: $(mkpasswd --method=SHA-512 --rounds=4096 notplaintextpass)
chpasswd:
  expire: False
users:
  - default
package_upgrade: true

runcmd:
  # One-command install, from https://tailscale.com/download/
  - ['sh', '-c', 'curl -fsSL https://tailscale.com/install.sh | sh']
  # Set sysctl settings for IP forwarding (useful when configuring an exit node)
  - ['sh', '-c', "echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf && sudo sysctl -p /etc/sysctl.d/99-tailscale.conf" ]
  # Generate an auth key from your Admin console
  # https://login.tailscale.com/admin/settings/keys
  # and replace the placeholder below
  - ['tailscale', 'up', '--authkey=tskey-abcdef1432341818']
  # Optional: Include this line to make this node available over Tailscale SSH
  - ['tailscale', 'set', '--ssh']
  # Optional: Include this line to configure this machine as an exit node
  - ['tailscale', 'set', '--advertise-exit-node']
EOF

cat << EOF > /var/lib/vz/snippets/network.yaml
version: 1
config:
    - type: physical
      name: ens18
      subnets:
      - type: static
        address: '192.168.1.2'
        netmask: '255.255.255.0'
        gateway: '192.168.1.1'
    - type: nameserver
      address:
      - '1.1.1.2'
      search:
      - 'local'
EOF

And here's how I used it:

qm clone 9000 101 --name cloudinit-vm
qm resize 101 scsi0 +13G
qm set 101 --cicustom "user=local:snippets/userdata.yaml,network=local:snippets/network.yaml"
qm start 101

Voila! New node just got added to the Tailnet.

References