📖 Chapter 05 — VMs with KVM
Full operating systems in software. The right tool when containers aren't enough.
Learning Objectives
- Create a VM on TrueNAS using KVM
- Configure CPU, RAM, disk, and networking for a VM
- Install an OS in the VM
- Access the VM (console, SSH, RDP)
Introduction
From Chapter 03: containers are the default. Reach for VMs when you need a different OS, kernel access, or strong isolation. This chapter is the practical VM: how to create one, install an OS, configure the basics, and use it.
When to use a VM
Use a VM when:
- You need a different OS than the host. Most commonly: a Windows VM on a Linux host, or a Linux distro you want to test (Fedora, Arch, NixOS).
- You're learning system administration. A VM is a real computer you can break and rebuild.
- You need a development environment that mimics production. A VM with the same OS, the same packages, the same configuration as your production server.
- You need a Windows-only app. A Windows VM with the app installed, accessed from your Linux or Mac laptop via RDP.
- You need strong isolation. A VM is more isolated than a container.
TrueNAS and KVM
TrueNAS Scale uses KVM (the Linux kernel's hypervisor) for VMs. The setup is in the TrueNAS web UI:
- Virtualization → Add.
- Choose an operating system (Linux, Windows, FreeBSD, etc.).
- Upload or specify an installer ISO. (You'll need to download this — Ubuntu, Debian, Fedora, Windows installer ISOs are all available from their respective sites.)
- Configure the VM:
- Name: the VM's name (e.g., "dev-vm")
- CPU: number of virtual CPUs (start with 2-4)
- RAM: in MB or GB (start with 4-8 GB for a Linux dev VM, 8-16 GB for a Windows VM)
- Disk: create a new zvol (block device in ZFS) for the VM's main disk
- Network: attach to a virtual network (the default bridge is fine)
- Save. The VM is created. Click "Start" to boot it.
On first boot, the VM boots from the ISO (you attached). Install the OS. After installation, eject the ISO and reboot. The VM is now running the installed OS.
Resource sizing
The right amount of CPU, RAM, and disk for a VM depends on the workload:
| VM type | vCPUs | RAM | Disk |
|---|---|---|---|
| Linux dev VM | 2-4 | 4-8 GB | 50-100 GB |
| Linux server VM | 2-4 | 4-8 GB | 50-100 GB |
| Linux desktop VM | 4 | 8 GB | 100 GB |
| Windows 11 VM | 4-8 | 8-16 GB | 100-200 GB |
| K8s/k3s node | 2-4 | 4-8 GB | 50 GB |
Start small. You can always increase resources; shrinking is harder (you'd have to resize the disk).
Networking in a VM
By default, the VM is on a virtual network bridge. It can reach the host and the internet. From the host (or any other device on the LAN), you can reach the VM at its IP address (assigned by the VM's DHCP, which is the host's built-in DHCP for the virtual network).
For a static IP, configure it in the VM's network settings (the standard OS network configuration). For port forwarding (e.g., expose the VM's web server on port 80 to the LAN), use the host's NAT/port forwarding in the TrueNAS VM settings.
For an isolated VM (one that can reach the internet but not the LAN), create a separate virtual network with no bridge to the host's physical network. The VM is on a private subnet, can reach the internet through the host's NAT, but is invisible to other LAN devices.
Accessing the VM
Three ways:
- Console: the TrueNAS web UI has a console view of the VM. You see the VM's screen in the browser. Good for initial setup, bad for ongoing use.
- SSH: for Linux VMs. Enable the SSH server in the VM, then SSH to the VM's IP from your laptop. Standard Linux admin workflow.
- RDP: for Windows VMs. Enable Remote Desktop in the VM, connect from your laptop using Microsoft Remote Desktop, Remmina, or any RDP client. Standard Windows admin workflow.
For most home lab use, SSH (Linux) or RDP (Windows) is the right answer. The console is for the initial setup only.
Storage for VMs
Two options:
- Zvol: a block device in ZFS. The VM sees it as a virtual disk. Faster than a file-based disk. The right answer for performance-sensitive VMs.
- qcow2 file: a file on the ZFS dataset. The VM sees it as a virtual disk. Slightly slower than a zvol. Easier to back up (it's a file).
For most home lab VMs, qcow2 files are fine. They're easy to back up, easy to copy, easy to delete. For VMs that need every bit of I/O performance (database servers, large compilation jobs), use a zvol.
Snapshots for VMs
TrueNAS lets you snapshot a VM. The snapshot is a frozen copy of the VM's disk and state. You can roll back to it if the VM gets into a bad state.
To snapshot a VM:
- Stop the VM (or take a live snapshot if the filesystem supports it — most modern filesystems do).
- TrueNAS → Virtualization → Select the VM → Snapshot.
- The snapshot is a ZFS snapshot of the zvol or a copy-on-write snapshot of the qcow2 file.
For the "I just installed the OS, before I start customizing" moment, take a snapshot. For the "I just installed all the apps, before I start using them" moment, take another. Roll back to the snapshot if something breaks.
Backing up VMs
VMs are just files (or zvols). Back them up like any other data.
For qcow2 files: copy the file to a backup location. Compress it for smaller backups. Use qemu-img convert to convert between formats if needed.
For zvols: use zfs send | zfs receive to replicate the zvol. This is the same pattern as the dataset replication from Volume 3, Chapter 5.
For ongoing VM backups, a simple cron job that copies the qcow2 file to a backup dataset, once a day or once a week, is sufficient. For most home lab VMs, the data on the VM is more important than the VM itself (the OS is reproducible; the data is not).
The "VM as development environment" pattern
For software development, the right pattern is often: a VM that matches your production environment, and your laptop is just a thin client.
- Install your dev tools in the VM (compiler, runtime, dependencies).
- Edit code on the laptop (where your editor and tools live).
- Sync the code to the VM (Syncthing, Git, or a shared folder).
- Build, test, and run in the VM.
The benefit: the dev environment is reproducible. If your laptop dies, you can spin up a new VM and have the same dev environment. The laptop is just the editor; the VM is the workspace.
The "Windows VM" pattern
For Windows-only apps (Microsoft Office, Adobe Creative Cloud, a piece of software that only ships for Windows), a Windows VM is the right answer. The setup:
- Create a Windows VM in TrueNAS.
- Install Windows from an ISO.
- Activate Windows with a license (or use it unactivated with the watermark).
- Install the Windows-only apps.
- Connect from your laptop via RDP.
For best performance, dedicate 8+ GB of RAM and 4+ vCPUs to the Windows VM. Enable RemoteFX or the equivalent GPU acceleration if your hardware supports it.
The "VM as honeypot or sandbox" pattern
For security research, a VM you don't trust anything in is the right answer. Examples:
- Testing software from an untrusted source
- Visiting a suspicious website
- Learning about malware (in a controlled environment)
Use a VM with no access to the family network. Take a snapshot before each session. Roll back to the snapshot (or delete the VM) after the session. The blast radius of a malicious app is the VM, not the host.
Common mistakes
- Over-allocating resources. Giving a Linux dev VM 16 GB of RAM when 4 GB would do. Each VM's resources come from the host's resources. Allocate what you need, not what you have.
- Not taking snapshots before changes. The "before I install that, let me snapshot" moment is the right discipline. Cheap to do; saves hours of rebuilding when things go wrong.
- Storing important data only in the VM. If the VM's disk dies and you have no backup, the data is gone. The VM is a tool; the data on the VM is what matters.
Engineering Note
VMs are for things containers can't do. Don't reach for VMs out of habit. They're heavier (more RAM, more CPU, more disk), slower to start, and harder to manage than containers. The default is containers. The exception is when the workload really needs a different OS, kernel access, or strong isolation. The default is more efficient.
Summary
VMs in TrueNAS: KVM-based, configured in the web UI. One VM per workload. Use a zvol for performance-sensitive VMs, a qcow2 file for most. SSH for Linux, RDP for Windows. Snapshots before changes. Back up the VM files. Don't over-allocate resources. Don't store irreplaceable data only in a VM. Use VMs when containers aren't enough; use containers when VMs aren't needed.
Checklist
- ⬜ Identify the workloads that need VMs (different OS, kernel access, strong isolation)
- ⬜ Create one VM per workload, sized appropriately
- ⬜ Configure SSH (Linux) or RDP (Windows) for ongoing access
- ⬜ Take a snapshot after OS installation, before customization
- ⬜ Set up VM backups (copy the qcow2 or replicate the zvol)
Looking Ahead
Chapter 06 is reverse proxies and TLS: how to expose services to the internet with HTTPS, the right way. Traefik, Caddy, and Nginx are the tools. The chapter that turns "I have a service running on port 8080" into "I have a service available at https://app.mydomain.com with a real certificate."