Almost every post on this site begins the same way: a new virtual machine (VM) gets created on Proxmox before any actual project work starts. This document serves as the standard guide on configuring a VM in accordance with the standards of the rest of the lab environment.
VM Specifications
I keep VM sizing consistent and conservative. Most VMs serve singular purposes and run only a handful of lightweight services. For that purpose I use the following settings:
| Setting | Typical Value | Notes |
|---|---|---|
| OS | Ubuntu 24.04 LTS | Consistent across the entire lab |
| CPU | 2 vCPUs | Sufficient for most single-service VMs |
| RAM | 2–4GB | 2GB for lightweight services, 4GB for anything Java-based or running a database alongside the app |
| Storage | 20–32GB | 20GB baseline, 32GB when a local database is involved |
| VLAN | Matched to associated category | VLANs function as segmentation and as a categorization tool to group VMs |
Step 1 - Create the VM
In the Proxmox web UI:
- Click Create VM and assign the next available VM ID in sequence
- General Tab - Set a hostname following the lab's naming convention (e.g. LAB-<ROLE>)
- OS tab - Select the relevant operating system (e.g. Ubuntu 24.04 ISO)
- System tab - Defaults are fine for nearly everything in this lab
- Disks tab - Set storage per the sizing guidance above
- CPU tab - Set core count in accordance with guidelines above
- Memory tab - Set RAM in MB (e.g. 2048 = 2GB)
- Network tab - bridge to the appropriate virtual switch, assign the appropriate VLAN ID, model VirtIO.
- Confirm and configure the VM without starting it.
- Find the new VM in the list and select Console and Start Now on the Qemu agent window.
Step 2 - Ubuntu Install
For the purpose of this write-up we are going to focus on the process for installing Ubuntu. There are more installation guides on the Ubuntu distribution than there are people on the Earth. Mine will be brief. The most important section for our purposes is the network configuration screen. I always set a static IP manually rather than rely upon DHCP. Every VM in this lab serves a purpose and plays a hand in the overall infrastructure therefore it is only practical ensure their IPs are not shuffling on me and breaking numerous configs across various servers. A few notes to consider:
- IP Address - in the lab the third octet matches the VLAN, fourth octet is assigned host number (e.g. 10.10.35.25/24) for a host on the internal services VLAN.
- Gateway - the firewall's interface address for the same VLAN it is being assigned. Gateways on VLANs are not accessible from different VLANs.
- DNS - internal resolver, except for VMs on the DMZ segment, which uses a public resolver.
When prompted for additional OpenSSH server. Everything else gets installed deliberately later as needed. We purposefully avoid any bundles or packages that Ubuntu wants to bloat our machine with. My final recommendation when it comes to the Ubuntu install is enforce consistency. Ensure you match hostnames to Proxmox names initially and utilize a password manager like Bitwarden to keep track of the various passwords spanning your growing infrastructure.
Step 3 - Standard Hardening
Once the VM is reachable, I SSH in from my management host through the bastion host and apply the same baseline to every machine.
- Create the primary admin account (not root) with sudo privileges.
- Install my SSH public key and disable password authentication entirely once key-based login is confirmed working.
- Point /etc/resolv.conf at the correct internal DNS resovler for that VM's VLAN, and lock the file.
- Apply OS updates (apt update && apt upgrade) before anything else is installed.
- Confirm the VM can resolve and reach internal services (internal CA, DNS) before moving on to configuring the VM for its final purpose.
Common Issues
If a server is configured on a new VLAN or previously unused VLAN it is likely the interface still needs firewall rules explicitly permitting the new VLAN to access the internal DNS resolver. Ensure DNS is allowed before beginning Ubuntu configuration.