cloud-init
You want to use cloud-init, for sure! Here are my configs I usually use for bootstraping new servers quickly.
Ubuntu 24.04
Delete the content you don’t need. Otherwise it joins the server to my tailnet, installs some packages, does a system upgrade and enables automatic updates.
#cloud-config <hostname>
locale: en_US.UTF-8
timezone: UTC
package_update: true
package_upgrade: true
packages:
- vim
- git
- wget
- curl
- dnsutils
- net-tools
users:
- name: technat
groups: sudo
sudo: ALL=(ALL) NOPASSWD:ALL # Allow any operations using sudo
gecos: "Admin user created by cloud-init"
shell: /usr/bin/bash
write_files:
- path: /etc/sysctl.d/99-tailscale.conf
content: |
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
- path: /etc/apt/apt.conf.d/50unattended-upgrades
content: |
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
"${distro_id}:${distro_codename}-updates";
"${distro_id}:${distro_codename}-proposed";
"${distro_id}:${distro_codename}-backports";
};
Unattended-Upgrade::DevRelease "auto";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "23:00";
Unattended-Upgrade::SyslogEnable "true";
runcmd:
- sysctl -p /etc/sysctl.d/99-tailscale.conf
- systemctl enable --now unattended-upgrades.service
- systemctl mask ssh
- curl -fsSL https://tailscale.com/install.sh | sh
- tailscale up --ssh --auth-key "<single-use-pre-approved-key>"
- ufw default deny incoming
- ufw default allow outgoing
- ufw allow in on tailscale0
- ufw --force enable