Linux VM Provisioning
Here are some steps that need to be done when creating a VM template that will be used multiple times:
Template Usage
See this page to setup a deployed instance from a template VM: Ubuntu v24 Host Setup
References
Here’s a good reference for template generation and cloud-init usage: https://medium.com/@dsykes012/making-a-custom-ubuntu-20-04-lts-focal-fossa-vm-template-that-works-with-cloud-init-2cfffb6783b4
Important Notes
Machine-ID Uniqueness: Anytime you power on a Linux VM template (whether making changes or not), you need to clear its machine-id before shutting it back down. This ensure that any generated clones will get a unique machine-id when the clone boots. If you forget to do this, the template will see that it has a machine-id, and will not generate one as a clone, causing all spawned clones to share the same machine-id.
Follow this section before powering down a template: https://wiki.galaxydump.com/link/391#bkmrk-clear-the-machine-id
Host Template Setup
Here are steps for creating a golden template VM.
Create Template VM
Create a VM guest instance with minimal CPU, memory, and hard disk space for the template.
We go with minimal resources, as it’s easier to script additional resources, than it is to reduce them.
For example, it’s much faster and less risk to expand a drive than reducing one.
Assign the VM’s NIC to the provisioning VLAN, as this allows us to easily access and setup deployed clones.
DHCP Addressing
Setup the template with DHCP, so we don’t worry about address collisions when spawning multiple clones at once.
Perform Updates and Upgrades
To speed up the process of clone setup, we will do any updates and upgrades on the template.
Do this:
apt update && apt -y upgrade && apt -y autoremove && apt clean
SSH Server
Install the openssh server.
Configure it to listen on port 22 of all adapters.
Disable password authentication over SSH.
Firewall
Setup the ufw firewall rules with 22 as allowed.
Don’t enable the firewall on the template. We can script this as use cases require.
Provisioning User Account
Create User
Create a provisioning user on the VM template.
NOTE: If not running as root, you will need to prepend these commands with 'sudo'.
NOTE: By default, we use the username 'provisioner'.
Run this to create the user with a password:
useradd -m provisioner
NOTE: We included the '-m' switch, to give the user a home directory.
This is done, so that our user can authenticate with SSH keys, which need a .ssh folder under the user's home directory.
Once created, add the provisioner account to the sudo group, so it can run elevated commands:
usermod -aG sudo provisioner
NOTE: The -aG
option tells usermod
to add the user to the listed groups.
User Shell
If you want the provisioner user to have shell access, set the shell with this:
sudo chsh -s /bin/bash provisioner
See this page for details: Linux: Minimalistic Shell
NOTE: It may not be necessary for an automation account to have a shell.
But, it does help when troubleshooting.
Account Password
You need to choose if you want the provisioner account to have a password or not.
NOTE: You don't really have to create a password for a provisioning user account if:
- You will use SSH keys for authentication,
- You will be bypassing sudo checks for this user
If you want it to have a password, use this to create one:
passwd provisioner
If you don't want the user to have a password, run this:
passwd -l provisioner
The above will lock the password, making login via password impossible.
Sudo Bypass
We will allow the provisioner user to skip any sudo challenge checks.
We do this, so that we don't have to manage passwords in the deployment scripting.
Follow this page for how to do that: Linux: Allow User to Skip Sudo Challenge
Edit the visudo file with this:
visudo -f /etc/sudoers
And, add this line above the includedir line:
provisioner ALL=(ALL) NOPASSWD: ALL
SSH Key Installation
Install an SSH key for the user.
NOTE: If you are just setting up this user, it may not yet have an authorized_keys file, or an .ssh folder in its profile.
If the .ssh folder is missing, follow this: Linux: Missing .SSH Folder
To do so, locate the authorized_keys file for the provisioner user at: /home/provisioner/.ssh/authorized_keys.
And, add the public key of the provisioner account.
You can open it with this:
sudo nano /home/provisioner/.ssh/authorized_keys
Save and close when done.
Verify SSH Access
Once the SSH key is loaded, you can verify SSH authentcationauthentication with this:
ssh -i /path/to/id_rsaprivatekeyfile user@server.nixcraft.comprovisioner@hostname
Login as Provisioning User
Log into the template VM as root.
This allows us to scrub unnecessary users and groups from the system.
Reset Hostname
Every host needs a unique name in your network.
So, we will clear an default the hostname of a template.
The following will erase it:
truncate -s0 /etc/hostname
And, this will set it to 'localhost':
hostnamectl set-hostname localhost
Clear the Machine-Id
Machine-Id is a string value that uniquely identifies a linux host, similar to how a Windows VM is uniquely identified by its machine sid.
Linux stores the machine-id is stored in a file at: /etc/machine-id.
So. If you are cloning VMs, you need to make sure this value is different for each VM clone.
The following will erase the machine-id, and any symbolic links to it:
truncate -s0 /etc/machine-id
rm /var/lib/dbus/machine-id
ln -s /etc/machine-id /var/lib/dbus/machine-id
The next time the VM reboots, the OS will generate a new machine-id during the boot process.
NOTE: Each time you boot the template, creates a new machine Id.
So, you will need to re-execute the above, after each time you boot the template VM for updates or changes.