Skip to content

Instantly share code, notes, and snippets.

@brianonn
Last active December 26, 2022 07:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianonn/924934303791dcd21a00791406224e85 to your computer and use it in GitHub Desktop.
Save brianonn/924934303791dcd21a00791406224e85 to your computer and use it in GitHub Desktop.
cleanup a standard ubuntu server install for making a cloud-init template (i.e. for VM creation template, proxmox, vmsphere, etc)
#!/bin/bash
###########################################
#
# 1) install a standard ubuntu server from the server image
# 2) during server installation you will have to create a user, so create a throwaway user, ie 'tmpinstall'
# 3) login to that throwaway user 'tmpinstall' after the server is up
# 4) install any additional packages and even any special users that you want to always
# be there in your base image template
# 5) when finished, become a clean root shell for the next steps:
# - to be a clean root, you must exec a root shell from the login shell, so that you can
# leave the login shell and the login user
# - the login user will be deleted by this script as part of the cleanup
# - steps: logout and login to the 'tmpinstall' user created during installation
# and immediately run `exec sudo -s`
# 6) next run this script `prepare-ubuntu-template.sh` as root to prepare the server image to be a VM template:
# `wget -O- https://gist.github.com/brianonn/924934303791dcd21a00791406224e85/raw | sh`
# 7) shutdown the server with `shutdown -h now` or `poweroff`
# 8) from the Proxmox UI Hardware tab, remove the cdrom drive and add a cloud-init drive.
# CLI: sudo qm set <VMID> -cdrom none
# CLI: sudo qm set <VMID> -ide2 local:cloud-init
# 9) add ssh keys to the cloud-init configuration and change the default user if needed
# - if you leave the cloud-init User : Default then it will be `ubuntu` or `debian`
# - remember to press `Regenerate Image` after you change configuration values in the cloud-init configuration
# 10) convert this VM server image to a template using the Proxmox UI or CLI `qm template <VMID>'
#
##########################################
if [ $(id -u) -ne 0 ] ; then
echo "This script should be run as the root user only"
exit 1
fi
# APT
apt-get update
apt-get upgrade -y
apt install qemu-guest-agent || true
apt clean
apt autoremove -y
# disable and remove swap
sed -i -e '/^\/swap.img/s/^/# /' /etc/fstab
swapoff -a
rm -vf /swap.img
# empty the machine id
truncate -s0 /etc/machine-id
ln -snf /etc/machine-id /var/lib/dbus/machine-id
# set the hostname to localhost in the template
truncate -s0 /etc/hostname
hostnamectl set-hostname localhost
# allow cloud-init to update the hostname using the VM name
sed -i 's/preserve_hostname: true/preserve_hostname: false/g' /etc/cloud/cloud.cfg
# reset networking
rm -f /etc/netplan/50-cloud-init.yaml
rm -f /etc/systemd/network/99-default.link
# remove ssh host keys
rm -f /etc/ssh/ssh_host_*
# the following is needed for Proxmox templates. Without this, some cloud-init
# modules are unable to determine the cloud environment and fail to run
echo 'datasource_list: [ NoCloud, None ]' | \
tee /etc/cloud/cloud.cfg.d/01_ds-identify.cfg > /dev/null
#
# remove any users that were added during installation (up to 10 users)
#
# a script to help read yaml files
# from https://stackoverflow.com/a/47791935
yaml() {
python3 -c "import yaml;print(yaml.safe_load(open('$1'))$2)"
}
INSTALLER_CFG="/etc/cloud/cloud.cfg.d/99-installer.cfg"
USERDATA_CFG="/tmp/$$.99-userdata.yml"
yaml $INSTALLER_CFG "['datasource']['None']['userdata_raw']" > $USERDATA_CFG
USERLIST=""
for i in $(seq 0 9); do
USERLIST="$USERLIST $( yaml $USERDATA_CFG "['users'][$i]['name']" 2>/dev/null )"
done
for user in $USERLIST; do
echo "Deleting user $user ... "
PIDS=$( ps --no-headers -u $user -o pid | xargs )
if [ -n "$PIDS" ]; then
kill $PIDS 2>/dev/null ; sleep 5; kill -9 $PIDS 2>/dev/null
fi
deluser --remove-home --remove-all-files $user 2>/dev/null
done
# finally, remove 99-installer.cfg so we don't re-add the same users on reboot
rm -rf $INSTALLER_CFG $USERDATA_CFG
#
# reset cloud-init
#
cloud-init clean --log
systemctl enable cloud-init
# clean out the root user history
truncate -s0 /root/.bash_history
exit 0
@brianonn
Copy link
Author

There are a few tutorials on the web, but they are missing some steps. I could never get it to actually run the cloud-init configuration set via the cloud-init drive in Proxmox.

These steps are what I have found ACTUALLY work and create a clean template that works, sets hostnames, creates users from the cloud-init template, adds ssh keys that are defined there, and can be used to create a proper template.

@brianonn
Copy link
Author

An alternative to this script is Hashicorp Packer, which can automate even the installer portion of the Ubuntu server (subiquity).

Hashicorp Packer has a higher initial learning curve and is more complete then this simple shell script. Packer supports multiple targets, so it knows how to create the same VM image for use with Proxmox, AWS, Google, etc.. as well as your local VMWare or Virtual Box too. That's pretty useful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment