The VirtualBox cheat sheet covers headless VM lifecycle management with VBoxManage - creating and tuning VMs, attaching disks and ISOs, networking modes, snapshots, cloning, NAT port forwarding, shared folders, VRDE remote display, and OVA import/export for building repeatable labs.
# Debian / Ubuntu (from Oracle repo)
sudo apt install virtualbox virtualbox-ext-pack
# Fedora / RHEL
sudo dnf install VirtualBox
# Arch
sudo pacman -S virtualbox virtualbox-host-modules-arch
# Gentoo
emerge -av app-emulation/virtualbox
# Verify + version
VBoxManage --version
VBoxManage --help | head
# Add your user to the vboxusers group (USB, etc.)
sudo usermod -aG vboxusers $USER
| Front-end | Purpose |
|---|---|
VBoxManage |
|
VBoxHeadless |
|
VBoxSDL |
Minimal SDL GUI front-end |
VirtualBox |
Qt GUI manager |
vboxmanage |
Symlink alias on some distros |
VBoxManage is the authoritative interface - the GUI is a thin wrapper over it. Subcommand syntax: VBoxManage <subcommand> <vm> <options>. <vm> is the name or UUID.
# Registered VMs and running VMs
VBoxManage list vms
VBoxManage list runningvms
# OS type IDs (for --ostype)
VBoxManage list ostypes
# Host capabilities / inventory
VBoxManage list hostinfo
VBoxManage list bridgedifs
VBoxManage list hostonlyifs
VBoxManage list natnets
VBoxManage list dhcpservers
VBoxManage list usbhost
VBoxManage list extpacks
# Full config dump of one VM (machine-readable)
VBoxManage showvminfo "kali" --machinereadable
# Create and register in one step
VBoxManage createvm --name "kali" \
--ostype Debian_64 \
--register
# Where files live: --basefolder /path
# Get valid --ostype values:
VBoxManage list ostypes | grep -i debian
# Delete a VM and all its files
VBoxManage unregistervm "kali" --delete
--ostype sets sane hardware defaults (chipset, audio, network card). Common IDs: Ubuntu_64, Debian_64, Windows10_64, Windows11_64, ArchLinux_64, RedHat_64.
VBoxManage modifyvm "kali" \
--memory 4096 \
--cpus 2 \
--vram 128 \
--ioapic on \
--pae on \
--rtcuseutc on \
--graphicscontroller vmsvga \
--boot1 dvd --boot2 disk --boot3 none
# Enable nested virtualization (run VMs inside the guest)
VBoxManage modifyvm "kali" --nested-hw-virt on
# EFI firmware (needed for Windows 11)
VBoxManage modifyvm "win11" --firmware efi
| Option | Meaning |
|---|---|
--memory <MB> |
|
--cpus <n> |
vCPU count |
--vram <MB> |
Video memory |
--ostype <id> |
Guest OS profile |
--boot1..4 |
Boot order (disk/dvd/net/none) |
--nested-hw-virt on |
Expose VT-x/AMD-V to guest |
--firmware efi |
UEFI instead of BIOS |
# Bidirectional clipboard + drag-and-drop
VBoxManage modifyvm "kali" \
--clipboard-mode bidirectional \
--draganddrop bidirectional
# CPU execution cap (throttle to 50%)
VBoxManage modifyvm "kali" --cpuexecutioncap 50
# Description / group for organization
VBoxManage modifyvm "kali" --description "pentest box"
VBoxManage modifyvm "kali" --groups "/Lab/Attackers"
# 1. Create a dynamically-allocated VDI (40 GB)
VBoxManage createmedium disk \
--filename "kali.vdi" \
--size 40000 \
--format VDI
# --variant Fixed # preallocated
# --format VMDK|VHD|VDI
# 2. Add a SATA controller
VBoxManage storagectl "kali" \
--name "SATA" \
--add sata \
--controller IntelAhci \
--portcount 2 \
--bootable on
# Attach the disk to SATA port 0
VBoxManage storageattach "kali" \
--storagectl "SATA" \
--port 0 --device 0 \
--type hdd \
--medium "kali.vdi"
# Attach an install ISO to port 1 (DVD drive)
VBoxManage storageattach "kali" \
--storagectl "SATA" \
--port 1 --device 0 \
--type dvddrive \
--medium "/isos/kali.iso"
# Eject the ISO (empty the drive) after install
VBoxManage storageattach "kali" \
--storagectl "SATA" \
--port 1 --device 0 \
--type dvddrive \
--medium emptydrive
| Controller type | --add value |
|---|---|
| SATA (AHCI) | sata |
| IDE | ide |
| NVMe | pcie |
| SAS | sas |
| SCSI | scsi |
| Floppy | floppy |
# Resize a VDI/VHD to 60 GB (dynamic only)
VBoxManage modifymedium disk "kali.vdi" --resize 60000
# List/close registered media
VBoxManage list hdds
VBoxManage closemedium disk "old.vdi" --delete
# Clone a disk (new UUID)
VBoxManage clonemedium disk "kali.vdi" "kali-copy.vdi"
# Compact a dynamic disk to reclaim space
VBoxManage modifymedium disk "kali.vdi" --compact
| Mode | --nic<N> value |
Guest reaches host | Guest reaches LAN | Reachable from outside | Guest-to-guest |
|---|---|---|---|---|---|
| NAT | nat |
via forwarding | only via port-forward | no | |
| NAT Network | natnetwork |
via forwarding | only via port-forward | ||
| Bridged | bridged |
||||
| Host-only | hostonly |
no | no | ||
| Internal | intnet |
no | no | no | |
| Not attached | null |
no | no | no | no |
# Each VM sits behind its own private NAT - isolated,
# gets internet, invisible to the LAN.
VBoxManage modifyvm "kali" --nic1 nat
# Set card model (Windows guests may need e1000)
VBoxManage modifyvm "kali" \
--nictype1 82540EM
# virtio, 82540EM (Intel PRO/1000),
# Am79C973 (PCnet)
# VM appears as a real host on the physical LAN,
# gets an IP from the LAN DHCP.
VBoxManage list bridgedifs # find --name value
VBoxManage modifyvm "kali" \
--nic1 bridged \
--bridge-adapter1 "eth0"
# Fully isolated switch - only VMs on the same
# named net talk. Great for an air-gapped lab.
VBoxManage modifyvm "kali" --nic1 intnet --intnet1 "labnet"
VBoxManage modifyvm "victim" --nic1 intnet --intnet1 "labnet"
A NAT network is a shared NAT switch multiple VMs join - they get internet AND can talk to each other.
# Create a NAT network
VBoxManage natnetwork add \
--netname "labnat" \
--network "10.0.2.0/24" \
--enable --dhcp on
# Attach VMs to it
VBoxManage modifyvm "kali" \
--nic1 natnetwork --nat-network1 "labnat"
# Port-forward into a NAT-network VM
VBoxManage natnetwork modify \
--netname "labnat" \
--port-forward-4 "ssh:tcp:[]:2222:[10.0.2.5]:22"
# List / remove
VBoxManage natnetwork list
VBoxManage natnetwork remove --netname "labnat"
Host-only creates a private vboxnet interface the host shares with its VMs - no internet, but SSH/RDP from the host works. Ideal for a jump-off management network.
# Create the interface (name auto-assigned: vboxnet0)
VBoxManage hostonlyif create
# Set its host-side IP / mask
VBoxManage hostonlyif ipconfig vboxnet0 \
--ip 192.168.56.1 --netmask 255.255.255.0
# Optional DHCP server for the host-only net
VBoxManage dhcpserver add \
--interface vboxnet0 \
--server-ip 192.168.56.1 \
--netmask 255.255.255.0 \
--lower-ip 192.168.56.100 \
--upper-ip 192.168.56.200 \
--enable
# Attach a VM
VBoxManage modifyvm "kali" \
--nic2 hostonly --host-only-adapter2 vboxnet0
# Remove interface
VBoxManage hostonlyif remove vboxnet0
# Rule format: name,proto,hostip,hostport,guestip,guestport
# hostip/guestip may be left empty.
# SSH: host :2222 -> guest :22
VBoxManage modifyvm "kali" \
--natpf1 "ssh,tcp,127.0.0.1,2222,,22"
# HTTP: host :8080 -> guest :80
VBoxManage modifyvm "kali" \
--natpf1 "web,tcp,,8080,,80"
# Delete a rule by name
VBoxManage modifyvm "kali" --natpf1 delete "ssh"
# Add/remove without rebooting via controlvm
VBoxManage controlvm "kali" \
natpf1 "rdp,tcp,,3389,,3389"
VBoxManage controlvm "kali" \
natpf1 delete "rdp"
# Then from the host:
ssh -p 2222 [email protected]
--natpf1 targets NIC 1; use --natpf2 for the second adapter. Rules persist in the VM config. This is the only way to reach a plain-NAT guest from the host.
# GUI window
VBoxManage startvm "kali" --type gui
# Headless - no window, VRDE only (servers)
VBoxManage startvm "kali" --type headless
# equivalent:
VBoxHeadless --startvm "kali"
# Separate: detachable GUI you can close
# without killing the VM
VBoxManage startvm "kali" --type separate
| Command | Effect |
|---|---|
pause |
|
resume |
Un-freeze |
reset |
|
poweroff |
|
savestate |
|
acpipowerbutton |
Graceful OS shutdown |
acpisleepbutton |
ACPI sleep signal |
VBoxManage controlvm "kali" pause
VBoxManage controlvm "kali" resume
VBoxManage controlvm "kali" savestate
VBoxManage controlvm "kali" acpipowerbutton
VBoxManage controlvm "kali" poweroff
# Live-tune resources
VBoxManage controlvm "kali" cpuexecutioncap 40
Prefer acpipowerbutton for a clean guest shutdown; poweroff risks filesystem corruption. savestate is the fastest resume but breaks if the VM config changes.
# Take a snapshot (VM can be running or off)
VBoxManage snapshot "kali" take "clean-install" \
--description "fresh, tools installed"
# List the snapshot tree
VBoxManage snapshot "kali" list
VBoxManage snapshot "kali" list --machinereadable
# Restore a named snapshot (VM must be powered off)
VBoxManage snapshot "kali" restore "clean-install"
# Restore the most recent snapshot
VBoxManage snapshot "kali" restorecurrent
# Delete a snapshot (merges its diff into parent)
VBoxManage snapshot "kali" delete "clean-install"
# Rename / re-describe
VBoxManage snapshot "kali" edit "clean-install" \
--name "baseline" \
--description "golden image"
# Live snapshot with saved memory state
VBoxManage snapshot "kali" take "before-detonate" --live
Snapshots are diff disks layered on the base - deep chains slow I/O. Take a "baseline" before detonating malware, then restore to reset the lab instantly. Deleting a snapshot merges, it does not lose the current state.
# Full clone - independent copy, new disks
VBoxManage clonevm "kali" \
--name "kali-2" \
--register
# Linked clone - shares base disk via a snapshot,
# tiny + fast (needs an existing snapshot)
VBoxManage clonevm "kali" \
--name "kali-linked" \
--options link \
--snapshot "baseline" \
--register
| Option | Purpose |
|---|---|
--options link |
|
--options keepallmacs |
Preserve MAC addresses |
--options keepnatmacs |
Keep NAT MACs only |
--mode all |
Clone whole snapshot tree |
--mode machine |
Current state only |
--snapshot <name> |
Clone from a snapshot |
# Clone just one snapshot's state
VBoxManage clonevm "kali" \
--name "kali-snap" \
--snapshot "baseline" \
--mode machine \
--register
Full clones cost disk but are portable; linked clones spin up dozens of lab boxes cheaply - deleting the parent breaks them.
# Package a VM into a single .ova appliance
VBoxManage export "kali" \
--output kali.ova \
--ovf20
# Add appliance metadata
VBoxManage export "kali" -o kali.ova \
--vsys 0 \
--product "Lab Kali" \
--vendor "homelab" \
--version "1.0"
# Export multiple VMs into one appliance
VBoxManage export "kali" "victim" -o lab.ova
# Preview what an appliance contains (dry run)
VBoxManage import kali.ova --dry-run
# Import, overriding name / RAM / CPUs
VBoxManage import kali.ova \
--vsys 0 \
--vmname "kali-imported" \
--memory 4096 \
--cpus 2
# ovftool (VMware) - convert to/from OVF
ovftool source.vmx kali.ova
.ova is a tar of the .ovf descriptor + disks; .ovf is just the descriptor. Use --ovf20 for broad compatibility. ovftool (from VMware) bridges to ESXi/Workstation formats.
Guest Additions provide clipboard, drag-and-drop, dynamic resolution, and shared folders. Install inside the guest.
# Attach the shipped Additions ISO to the guest
VBoxManage storageattach "kali" \
--storagectl "SATA" --port 1 --device 0 \
--type dvddrive \
--medium /usr/share/virtualbox/VBoxGuestAdditions.iso
# --- inside a Linux guest ---
sudo mount /dev/cdrom /mnt
sudo /mnt/VBoxLinuxAdditions.run
sudo reboot
# Run commands in the guest from the host (GA required)
VBoxManage guestcontrol "kali" run \
--username user --password pass \
--exe /bin/ls -- ls -la /tmp
# Persistent shared folder (auto on next boot)
VBoxManage sharedfolder add "kali" \
--name "share" \
--hostpath "/home/user/share" \
--automount
# Transient (removed on VM stop)
VBoxManage sharedfolder add "kali" \
--name "tmp" --hostpath "/tmp/x" --transient
# Read-only share
VBoxManage sharedfolder add "kali" \
--name "iso" --hostpath "/isos" --readonly
# Remove
VBoxManage sharedfolder remove "kali" --name "share"
# --- mount inside Linux guest ---
sudo mount -t vboxsf share /mnt/share
# or auto: appears under /media/sf_share
VRDE serves an RDP-compatible remote console - connect with any RDP client to a headless VM's screen. Requires the Extension Pack.
# Enable VRDE and pin a port
VBoxManage modifyvm "kali" \
--vrde on \
--vrde-port 3390 \
--vrde-address 127.0.0.1
# Range so multiple VMs auto-pick a free port
VBoxManage modifyvm "kali" --vrde-port 5000-5010
# Require authentication
VBoxManage modifyvm "kali" \
--vrde-auth-type external
# Toggle on a running VM
VBoxManage controlvm "kali" vrde on
VBoxManage controlvm "kali" vrdeport 3390
# Which port did it grab?
VBoxManage showvminfo "kali" | grep -i vrde
# --- from the host / another box ---
xfreerdp /v:127.0.0.1:3390
rdesktop 127.0.0.1:3390
Pair VRDE with --type headless to run a screenful VM on a server with no display. Bind to 127.0.0.1 and tunnel over SSH rather than exposing RDP on the LAN.
#!/usr/bin/env bash
set -euo pipefail
ISO=/isos/kali.iso
NET=labnet
for VM in attacker victim; do
VBoxManage createvm --name "$VM" --ostype Debian_64 --register
VBoxManage modifyvm "$VM" --memory 4096 --cpus 2 --vram 64 \
--nic1 intnet --intnet1 "$NET" --nictype1 virtio
VBoxManage createmedium disk --filename "$HOME/VMs/$VM.vdi" \
--size 40000 --format VDI
VBoxManage storagectl "$VM" --name SATA --add sata --portcount 2
VBoxManage storageattach "$VM" --storagectl SATA --port 0 --device 0 \
--type hdd --medium "$HOME/VMs/$VM.vdi"
VBoxManage storageattach "$VM" --storagectl SATA --port 1 --device 0 \
--type dvddrive --medium "$ISO"
VBoxManage startvm "$VM" --type headless
done
# After install: baseline snapshots to reset the lab
for VM in attacker victim; do
VBoxManage controlvm "$VM" acpipowerbutton || true
VBoxManage snapshot "$VM" take baseline
done
Give the attacker a second --nic2 nat if it needs internet for tooling while keeping intnet1 isolated for the engagement. Reset the whole lab with snapshot restore baseline on each VM.