Lab Setup Guide
You cannot learn Linux by reading about it. You learn Linux by breaking things, fixing them, breaking them again, and eventually understanding why they broke. For that, you need a lab -- a safe environment where you can experiment without fear of destroying anything important.
This appendix walks you through every practical option for setting up a Linux practice lab, from the simplest (spinning up a single VM) to the more sophisticated (multi-machine Vagrant environments). Pick the approach that fits your hardware, your operating system, and your comfort level. You can always graduate to a more complex setup later.
Option 1: VirtualBox -- The Classic Approach
Oracle VirtualBox is free, open source, and runs on Windows, macOS, and Linux. It is the most common choice for beginners and works well for most of the exercises in this book.
Installing VirtualBox
On Windows:
- Download the installer from virtualbox.org.
- Run the installer. Accept the defaults.
- If prompted about network interfaces being temporarily reset, click "Yes." This is normal.
- Reboot if asked.
On macOS:
- Download the macOS .dmg from the VirtualBox downloads page.
- Open the .dmg and run the installer.
- You will need to allow the kernel extension in System Preferences > Security & Privacy.
- On Apple Silicon (M1/M2/M3) Macs, VirtualBox support is available but still maturing. Consider UTM or multipass as alternatives.
On Linux (Ubuntu/Debian):
$ sudo apt update
$ sudo apt install virtualbox virtualbox-ext-pack
On Linux (Fedora):
$ sudo dnf install VirtualBox
Creating Your First VM
- Open VirtualBox and click "New."
- Give it a name (e.g., "ubuntu-lab"), choose type "Linux," version "Ubuntu (64-bit)."
- Allocate memory: 2048 MB minimum, 4096 MB if you can spare it.
- Create a virtual hard disk: VDI, dynamically allocated, 25 GB minimum.
- Before starting the VM, go to Settings:
- System > Processor: Give it 2 CPUs if you have them to spare.
- Storage: Click the empty optical drive, then click the disk icon and choose your downloaded ISO.
- Network: The default NAT adapter is fine for internet access from the VM.
- Start the VM. The ISO will boot and you can proceed with the Linux installation.
Downloading a Linux ISO
For the exercises in this book, we recommend:
- Ubuntu Server 24.04 LTS -- Best for beginners. Massive community.
ubuntu.com/download/server - Rocky Linux 9 or AlmaLinux 9 -- RHEL-compatible, excellent for learning enterprise Linux.
rockylinux.orgoralmalinux.org - Debian 12 (Bookworm) -- Rock-solid, minimalist.
debian.org
Download the server edition (not the desktop edition). Server installs are leaner, and you will learn more by working from the command line.
VirtualBox Networking Modes
Understanding the networking modes is critical for lab work. Here is what each one does:
┌─────────────────────────────────────────────────────────┐
│ Your Host Machine │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ VirtualBox │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ VM 1 │ │ VM 2 │ │ VM 3 │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ │ │ │ │ │ │
│ │ ┌────┴──────────────┴──────────────┴────┐ │ │
│ │ │ Internal Network / Host-Only │ │ │
│ │ │ 192.168.56.0/24 │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ │ NAT │
└─────────────────────────┼───────────────────────────────┘
│
Internet
| Mode | VMs talk to Internet? | Host talks to VM? | VMs talk to each other? | Best for |
|---|---|---|---|---|
| NAT | Yes | No (unless port forwarding) | No | Single VM that needs internet |
| Bridged | Yes | Yes | Yes | VM on the real network like a physical machine |
| Host-Only | No | Yes | Yes | Isolated lab network |
| Internal Network | No | No | Yes | Fully isolated VM-to-VM network |
| NAT Network | Yes | No (unless port forwarding) | Yes | VMs need internet AND must talk to each other |
Recommended setup for this book: Give each VM two network adapters:
- Adapter 1: NAT (for internet access to install packages)
- Adapter 2: Host-Only (so you can SSH from your host into the VM, and VMs can talk to each other)
To create a Host-Only network:
- Go to File > Host Network Manager (or Tools > Network in newer versions).
- Create a new network. Use the defaults (usually 192.168.56.1/24 with DHCP).
- In each VM's settings, add a second adapter set to "Host-Only Adapter" using this network.
VirtualBox Guest Additions
Install Guest Additions in your VM for shared folders, better screen resolution, and shared clipboard:
# Inside the VM (Ubuntu/Debian)
$ sudo apt update
$ sudo apt install build-essential dkms linux-headers-$(uname -r)
# Insert the Guest Additions CD from the VirtualBox menu: Devices > Insert Guest Additions CD
$ sudo mount /dev/cdrom /mnt
$ sudo /mnt/VBoxLinuxAdditions.run
$ sudo reboot
VirtualBox Snapshots
This is your safety net. Before doing anything risky in a lab exercise, take a snapshot:
- In VirtualBox Manager, select your VM.
- Click the "Snapshots" tab (or the camera icon).
- Click "Take." Name it something meaningful like "clean-install" or "before-nginx-config."
If things go sideways, restore the snapshot and you are back to a known good state in seconds. Use this liberally.
Option 2: QEMU/KVM -- The Linux-Native Approach
If your host is already running Linux, QEMU/KVM is the superior virtualization option. It uses hardware virtualization directly and gives better performance than VirtualBox.
Installation
# Ubuntu/Debian
$ sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager
$ sudo usermod -aG libvirt $USER
$ sudo usermod -aG kvm $USER
# Log out and back in for group changes to take effect
# Fedora/RHEL
$ sudo dnf install @virtualization
$ sudo systemctl enable --now libvirtd
Creating a VM with virt-manager (GUI)
virt-manager provides a graphical interface very similar to VirtualBox:
- Open Virtual Machine Manager.
- Click "Create a new virtual machine."
- Choose "Local install media (ISO)."
- Browse to your downloaded ISO.
- Set RAM (2048 MB) and CPUs (2).
- Create a disk (25 GB).
- Name the VM and choose the network (default NAT is fine).
Creating a VM from the command line
For those who prefer the terminal:
# Create a disk image
$ qemu-img create -f qcow2 /var/lib/libvirt/images/ubuntu-lab.qcow2 25G
# Install from ISO
$ virt-install \
--name ubuntu-lab \
--ram 2048 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/ubuntu-lab.qcow2,format=qcow2 \
--cdrom /path/to/ubuntu-24.04-live-server-amd64.iso \
--os-variant ubuntu24.04 \
--network network=default \
--graphics vnc,listen=0.0.0.0 \
--noautoconsole
Managing VMs with virsh
$ virsh list --all # List all VMs
$ virsh start ubuntu-lab # Start a VM
$ virsh shutdown ubuntu-lab # Graceful shutdown
$ virsh destroy ubuntu-lab # Force stop (like pulling the power)
$ virsh snapshot-create-as ubuntu-lab clean-install # Take a snapshot
$ virsh snapshot-revert ubuntu-lab clean-install # Revert to snapshot
$ virsh console ubuntu-lab # Connect to serial console
Option 3: WSL2 on Windows -- Linux Without a VM
If you are on Windows 10 or 11, Windows Subsystem for Linux 2 (WSL2) gives you a real Linux kernel running inside a lightweight virtual machine, integrated directly into Windows. It is the fastest way to get a Linux terminal on Windows.
Installation
Open PowerShell as Administrator:
wsl --install
That single command installs WSL2 and Ubuntu. Reboot when prompted.
After reboot, Ubuntu will launch automatically. Create a username and password when asked.
Installing additional distributions
# List available distributions
wsl --list --online
# Install a specific distribution
wsl --install -d Debian
wsl --install -d Ubuntu-24.04
# List installed distributions
wsl --list --verbose
WSL2 configuration
Create or edit ~/.wslconfig in your Windows home directory (e.g., C:\Users\YourName\.wslconfig):
[wsl2]
memory=4GB
processors=2
swap=2GB
localhostForwarding=true
And inside the Linux distribution, /etc/wsl.conf:
[boot]
systemd=true
[automount]
enabled=true
options="metadata,uid=1000,gid=1000,umask=22,fmask=11"
[network]
generateResolvConf=true
What WSL2 can and cannot do
Works great for:
- All command-line tools and exercises in this book
- Shell scripting, text processing, git, SSH, development tools
- Running servers (nginx, databases) accessible from Windows via localhost
- Docker (Docker Desktop integrates with WSL2)
Limitations:
- No systemd by default on older WSL2 versions (but modern versions support it with the
[boot] systemd=truesetting) - No direct hardware access (you cannot practice disk partitioning on real block devices)
- Networking is somewhat abstracted (NAT through the Windows host)
- Cannot practice kernel module loading or custom kernel builds easily
- Not a substitute for a real VM when practicing boot process, GRUB, or disk management
For most of this book, WSL2 is excellent. For chapters on boot process, disk management, and kernel topics, use a proper VM.
Option 4: Multipass -- Quick Ubuntu VMs
Canonical's multipass is the fastest way to spin up Ubuntu VMs on any platform. It is free, open source, and incredibly simple.
Installation
# macOS
$ brew install multipass
# Windows: Download from multipass.run
# Linux (snap)
$ sudo snap install multipass
Basic usage
# Launch an Ubuntu VM (defaults to the latest LTS)
$ multipass launch --name lab1 --cpus 2 --memory 2G --disk 20G
# List running instances
$ multipass list
# Open a shell in the VM
$ multipass shell lab1
# Run a command without entering the VM
$ multipass exec lab1 -- uname -a
# Transfer files
$ multipass transfer localfile.txt lab1:/home/ubuntu/
$ multipass transfer lab1:/home/ubuntu/remotefile.txt ./
# Stop, start, delete
$ multipass stop lab1
$ multipass start lab1
$ multipass delete lab1
$ multipass purge # Permanently remove deleted instances
Cloud-init support
Multipass supports cloud-init, so you can automate VM setup:
# Save as lab-init.yaml
#cloud-config
package_update: true
packages:
- nginx
- vim
- tmux
- net-tools
- curl
- git
users:
- name: student
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
ssh_authorized_keys:
- ssh-ed25519 AAAA... your-key-here
runcmd:
- systemctl enable --now nginx
$ multipass launch --name web-lab --cloud-init lab-init.yaml
Multipass is perfect when you need a quick, disposable Ubuntu instance and do not want to deal with VirtualBox configuration.
Option 5: Vagrant -- Reproducible Environments
Vagrant is a tool by HashiCorp that automates VM creation using simple configuration files called Vagrantfiles. It is open source and works with VirtualBox, libvirt/KVM, and other providers.
The killer feature: your entire lab environment is defined in a text file that you can version-control, share, and recreate in minutes.
Installation
# macOS
$ brew install vagrant
# Ubuntu/Debian
$ sudo apt install vagrant
# Fedora
$ sudo dnf install vagrant
# Windows: Download from vagrantup.com
Vagrant also needs a provider (a hypervisor to create the VMs). VirtualBox is the default.
Your first Vagrantfile
Create a directory for your lab and initialize it:
$ mkdir ~/linux-lab && cd ~/linux-lab
$ vagrant init ubuntu/jammy64
This creates a Vagrantfile. Let us look at a cleaned-up version:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.hostname = "lab1"
# Forward port 80 on the VM to 8080 on your host
config.vm.network "forwarded_port", guest: 80, host: 8080
# Private network so you can SSH and the VM gets a static IP
config.vm.network "private_network", ip: "192.168.56.10"
# Sync a folder from host to guest
config.vm.synced_folder "./shared", "/home/vagrant/shared"
# VM resources
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
vb.name = "linux-lab-1"
end
# Provisioning: run a script on first `vagrant up`
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y nginx vim tmux net-tools curl git
systemctl enable --now nginx
SHELL
end
Essential Vagrant commands
$ vagrant up # Create and start the VM
$ vagrant ssh # SSH into the VM
$ vagrant halt # Graceful shutdown
$ vagrant destroy # Delete the VM entirely
$ vagrant reload # Restart (re-reads Vagrantfile)
$ vagrant provision # Re-run provisioning scripts
$ vagrant snapshot save clean # Take a snapshot
$ vagrant snapshot restore clean # Restore a snapshot
$ vagrant status # Check VM status
$ vagrant global-status # All VMs across all projects
Multi-Machine Vagrantfile
This is where Vagrant really shines. Need a web server and a database server for practice? Define both in one file:
Vagrant.configure("2") do |config|
# Web server
config.vm.define "web" do |web|
web.vm.box = "ubuntu/jammy64"
web.vm.hostname = "web01"
web.vm.network "private_network", ip: "192.168.56.10"
web.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
vb.cpus = 1
end
web.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y nginx
systemctl enable --now nginx
SHELL
end
# Database server
config.vm.define "db" do |db|
db.vm.box = "ubuntu/jammy64"
db.vm.hostname = "db01"
db.vm.network "private_network", ip: "192.168.56.11"
db.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 1
end
db.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y postgresql postgresql-contrib
systemctl enable --now postgresql
SHELL
end
# Load balancer
config.vm.define "lb" do |lb|
lb.vm.box = "ubuntu/jammy64"
lb.vm.hostname = "lb01"
lb.vm.network "private_network", ip: "192.168.56.12"
lb.vm.provider "virtualbox" do |vb|
vb.memory = "512"
vb.cpus = 1
end
lb.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y haproxy
SHELL
end
end
$ vagrant up # Starts all three VMs
$ vagrant ssh web # SSH into the web server
$ vagrant ssh db # SSH into the database server
$ vagrant destroy -f # Tear down everything
Vagrant with libvirt (KVM)
If you are on Linux and prefer KVM over VirtualBox:
$ sudo apt install vagrant-libvirt # or install the plugin
$ vagrant plugin install vagrant-libvirt
# Use a libvirt-compatible box
$ vagrant init generic/ubuntu2204
In your Vagrantfile, swap the provider:
config.vm.provider "libvirt" do |lv|
lv.memory = "2048"
lv.cpus = 2
end
Recommended Lab Topologies
Here are some lab designs matched to what you are learning:
Topology 1: Single VM (Chapters 1-27)
For the first half of the book -- shell, filesystem, users, processes, scripting, text processing -- a single VM is all you need.
┌──────────────────────────┐
│ Your Host Machine │
│ │
│ ┌───────────────────┐ │
│ │ Ubuntu Server │ │
│ │ 192.168.56.10 │ │
│ │ 2 CPU, 2GB RAM │ │
│ └───────────────────┘ │
│ │
└──────────────────────────┘
Topology 2: Two VMs (Chapters 28-37, Networking)
For networking chapters, you need at least two machines to practice SSH, file transfers, firewalls, and routing.
┌──────────────────────────────────────────────────┐
│ Your Host Machine │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ server01 │ │ server02 │ │
│ │ 192.168.56.10 │<-->│ 192.168.56.11 │ │
│ │ (SSH server) │ │ (SSH client) │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │ │
│ └──────────┬───────────┘ │
│ Host-Only │
│ 192.168.56.0/24 │
└──────────────────────────────────────────────────┘
Topology 3: Three VMs (Chapters 44-47, Web + Load Balancing)
For web server and load balancing practice:
┌────────────────────────────────────────────────────────┐
│ Your Host Machine │
│ │
│ ┌──────────────┐ │
│ │ lb01 │ HAProxy / Nginx LB │
│ │ .56.12 │ │
│ └──────┬───────┘ │
│ │ │
│ ┌─────┴──────┐ │
│ │ │ │
│ ┌─┴────────┐ ┌─┴────────┐ │
│ │ web01 │ │ web02 │ Nginx web servers │
│ │ .56.10 │ │ .56.11 │ │
│ └──────────┘ └──────────┘ │
│ │
└────────────────────────────────────────────────────────┘
Topology 4: Full Lab (Chapters 44-70+, Production Practice)
For the later chapters on monitoring, automation, and containers:
┌──────────────────────────────────────────────────────────────┐
│ Your Host Machine │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ web01 │ │ web02 │ │ db01 │ │ monitor │ │
│ │ .56.10 │ │ .56.11 │ │ .56.20 │ │ .56.30 │ │
│ │ Nginx │ │ Nginx │ │ Postgres │ │ Grafana │ │
│ │ 1CPU/1GB │ │ 1CPU/1GB │ │ 1CPU/2GB │ │ 1CPU/2GB │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ ansible │ │ docker │ │
│ │ .56.40 │ │ .56.50 │ │
│ │ Control │ │ Docker │ │
│ │ 1CPU/1GB │ │ 2CPU/4GB │ │
│ └──────────┘ └──────────┘ │
│ │
│ Host-Only: 192.168.56.0/24 │
└──────────────────────────────────────────────────────────────┘
For this full lab you will need at least 16 GB of RAM on your host machine. If you do not have that much, bring VMs up and down as needed. You rarely need all of them running simultaneously.
Cloud Free Tiers for Practice
If your local machine does not have enough resources, cloud providers offer free tiers that are perfect for practice.
Oracle Cloud Free Tier
Oracle offers an "Always Free" tier that is genuinely generous:
- 2 AMD-based VM instances (1 CPU, 1 GB RAM each)
- Up to 4 Arm-based Ampere A1 instances (total of 4 CPUs and 24 GB RAM)
- 200 GB of block storage
- This is not a trial -- it is permanently free.
Sign up at cloud.oracle.com.
AWS Free Tier
- 750 hours/month of t2.micro or t3.micro (1 CPU, 1 GB RAM) for 12 months
- Good for a single always-on practice server
- Sign up at
aws.amazon.com/free
Google Cloud Platform
- $300 in credits for 90 days for new accounts
- Always-free e2-micro instance (2 vCPU, 1 GB RAM) in select regions
- Sign up at
cloud.google.com/free
Azure Free Tier
- $200 in credits for 30 days
- 12 months of free B1s VM (1 CPU, 1 GB RAM)
- Sign up at
azure.microsoft.com/free
DigitalOcean / Linode / Vultr
These are not "free tier" but are very affordable:
- $4-6/month for a basic VPS (1 CPU, 1 GB RAM, 25 GB disk)
- Simple interfaces, great for learning
- DigitalOcean and Linode frequently offer $100-200 in credits for new accounts through promotional links
Tip: If you use a cloud instance for practice, remember to shut it down or destroy it when you are done. Cloud bills can add up if you forget.
Hardware Resource Recommendations
How much machine do you need? Here is a practical guide:
Minimum (can learn, will be tight)
- CPU: 2 cores
- RAM: 8 GB
- Disk: 50 GB free
- What you can run: 1-2 lightweight VMs simultaneously, or WSL2
Comfortable (recommended)
- CPU: 4 cores
- RAM: 16 GB
- Disk: 100 GB free (SSD strongly recommended)
- What you can run: 3-4 VMs simultaneously, Docker, comfortable multitasking
Ideal (no compromises)
- CPU: 6+ cores
- RAM: 32 GB
- Disk: 250 GB+ SSD
- What you can run: Full multi-VM lab, Docker, Kubernetes, monitoring stack, everything at once
SSD vs HDD
If there is one upgrade that makes the biggest difference for running VMs, it is an SSD. VM performance on a spinning hard drive is painful. On an SSD, VMs boot in seconds, snapshots are nearly instant, and everything feels responsive. If you are still on an HDD, this is the upgrade to make.
Setting Up SSH Access to Your VMs
Regardless of which virtualization tool you use, you will want to SSH into your VMs from a terminal on your host. This is much more comfortable than working in the VM's console window.
Generate an SSH key (if you do not already have one)
$ ssh-keygen -t ed25519 -C "lab-key"
# Press Enter for the default path (~/.ssh/id_ed25519)
# Optionally set a passphrase
Copy your key to the VM
$ ssh-copy-id user@192.168.56.10
Set up your SSH config for convenience
Add to ~/.ssh/config:
Host lab1
HostName 192.168.56.10
User ubuntu
IdentityFile ~/.ssh/id_ed25519
Host lab2
HostName 192.168.56.11
User ubuntu
IdentityFile ~/.ssh/id_ed25519
Now you can simply type ssh lab1 instead of remembering IP addresses.
Tips for Effective Lab Work
-
Snapshot before every experiment. It takes seconds and saves hours. Make this a habit.
-
Keep a lab journal. A simple text file where you note what you tried, what worked, and what broke. Your future self will thank you.
-
Destroy and rebuild regularly. Do not just configure a VM once and treat it as precious. Practice rebuilding from scratch. In the real world, servers are disposable and reproducible setups are king.
-
Simulate real problems. Kill a process and see what happens. Fill a disk to 100%. Misconfigure a firewall. Then fix it. The debugging skills you build this way are more valuable than any certification.
-
Use version control for your configs. Keep your Vagrantfiles, scripts, and ansible playbooks in a git repository. This teaches you infrastructure-as-code habits from day one.
-
Start simple, add complexity later. One VM is enough for months of learning. Do not build a six-machine cluster on day one. Add machines when you have a concrete reason to.
-
Make it easy to start. The biggest enemy of learning is friction. If it takes you 20 minutes to get your lab running, you will not practice as often. Automate the setup with Vagrant or a simple shell script so you can go from zero to working lab in one command.
That is everything you need to get started. Pick the option that matches your situation, spin up a VM, and start working through the chapters. The lab is where the real learning happens.