NeoDev supports multiple hypervisor backends through a common abstraction layer. VirtualBox is a fully supported backend alongside QEMU.
- VirtualBox installed
VBoxManagein PATH (included with VirtualBox)- NeoDev >= 0.3.0 for automatic raw image → VDI synchronization (see below)
Debian/Ubuntu:
sudo apt install virtualbox virtualbox-ext-packFedora:
sudo dnf install VirtualBoxArch:
sudo pacman -S virtualboxVerify installation:
VBoxManage --version# 1. Build NeoDOS disk image
neodev build --image
# 2. Run with VirtualBox (auto-creates VM)
neodev run --backend virtualbox
# Run headless
neodev run --backend virtualbox --headlessneodev vm create --backend virtualboxCreates and configures the VM if it doesn't exist. Automatically converts
disk_image.img to disk_image.vdi.
neodev vm start --backend virtualbox # GUI mode
neodev vm start --backend virtualbox --headless # Headless modeneodev vm stop --backend virtualboxSends ACPI power button signal. Forces poweroff if ACPI fails.
neodev vm reset --backend virtualboxneodev vm status --backend virtualboxneodev vm delete --backend virtualboxRemoves the VirtualBox VM and all associated files.
Configure the default backend in neodev.toml:
[vm]
backend = "virtualbox"
memory = 4096
cpus = 4Override per-command with --backend:
neodev run --backend qemu
neodev run --backend virtualboxThe VirtualBox backend automatically configures:
| Setting | Value |
|---|---|
| OS Type | Linux_64 |
| Firmware | EFI |
| Chipset | ICH9 |
| Memory | Configurable (default: 512 MB) |
| CPUs | Configurable (default: 2) |
| Storage | AHCI/SATA with VDI disk |
| Serial | COM1 → file (for test logging) |
| Network | NAT (default) or Bridged |
- NAT (default): Guest accesses internet via NAT. Host cannot reach guest.
- Bridged: Guest appears on the host network. Auto-detects active interface.
# With QEMU (default)
neodev test
# With VirtualBox
neodev test --backend virtualboxThe test runner starts the VM headless, monitors the serial log for
completion markers (ALL_TESTS_COMPLETE, CMDTEST_COMPLETE, etc.),
and stops the VM when tests finish or timeout.
Before the VM starts, the backend synchronizes disk_image.vdi with
disk_image.img (same path used by run), so neodev test can never boot a
VDI that is older than the freshly built raw image. See
VDI synchronization for the exact rule.
VirtualBox serial output is logged to file for debugging:
- Default path during testing:
/tmp/neodos_serial.log - During interactive runs: path specified via
--serialflag
NeoDev
└── vmm (Virtual Machine Manager)
├── HypervisorBackend trait
├── QemuBackend
└── VirtualBoxBackend ← this
All hypervisor-specific logic is encapsulated in backend implementations.
Adding a new hypervisor requires only implementing the HypervisorBackend trait.
NeoDev includes an automated DHCP integration test that uses VirtualBox in bridged networking mode to obtain a real IP address from the local network router.
- VirtualBox installed with VBoxManage in PATH
- Your user added to the
vboxusersgroup - A physical network interface (Ethernet preferred, Wi-Fi supported)
- A DHCP server on the local network (typically your router)
# 1. Build NeoDOS with all components
neodev build --image
# 2. Run the DHCP integration test
neodev dhcp --backend virtualbox- Generates a registry hive with
EnableNetworkTest=1 - Rebuilds the disk image with the test configuration
- Configures VirtualBox with Bridged Adapter mode
- Automatically detects a physical Ethernet or Wi-Fi interface
- Starts NeoDOS in headless mode
- The kernel boots and initializes networking (e1000 NIC)
- NeoInit launches
dhcptest.nxewhich performs DHCP DORA - Validates: IP obtained, not APIPA, mask exists, gateway exists
- Displays full network configuration
- Reports pass/fail
[*] NeoDOS DHCP Integration Test
Backend: virtualbox
Network: Bridged (real DHCP)
Bridged interface candidates: 1 Ethernet (eth0), 0 Wi-Fi ()
Selected: eth0 for bridged networking
...
[DHCPTEST] DISCOVER xid=0x12345678
[DHCPTEST] OFFER from 192.168.1.1 IP=192.168.1.100
[DHCPTEST] ACK: IP=192.168.1.100 mask=255.255.255.0 gw=192.168.1.1 lease=86400s
[DHCPTEST] DORA complete
[DHCPTEST] === Validation ===
[DHCPTEST] [PASS] IP obtained: 192.168.1.100
[DHCPTEST] [PASS] IP is not APIPA
[DHCPTEST] [PASS] Subnet mask: 255.255.255.0
[DHCPTEST] [PASS] Gateway: 192.168.1.1
[DHCPTEST] [PASS] DNS: 8.8.8.8
[DHCPTEST] [PASS] Lease time: 86400 s
...
[+] DHCP TEST COMPLETE
[✓] DHCP INTEGRATION TEST: SUCCESS
| Check | Description |
|---|---|
| IP obtained | IP != 0.0.0.0 |
| Not APIPA | IP not in 169.254.x.x range |
| Subnet mask | Valid mask (not 0 or 0xFFFFFFFF) |
| Gateway | Gateway assigned (warning, not fatal) |
| DNS server | DNS server assigned (warning, not fatal) |
| Lease time | Lease time > 0 (warning, not fatal) |
The test has a default timeout of 180 seconds. If DHCP negotiation
does not complete within this time, the test fails with a timeout error.
This can be overridden with --timeout:
neodev dhcp --backend virtualbox --timeout 300| Feature | QEMU | VirtualBox |
|---|---|---|
| Interactive run | neodev run |
neodev run --backend virtualbox |
| Headless mode | --headless |
--headless |
| Tests | neodev test |
neodev test --backend virtualbox |
| DHCP test | ❌ | neodev dhcp --backend virtualbox |
| Serial monitoring | Telnet monitor + file | File only |
| KVM acceleration | ✅ | N/A (native) |
| GDB debugging | ✅ | ❌ |
| EFI support | ✅ (OVMF) | ✅ |
| Network modes | user/tap/bridge | NAT/bridged |
| Disk format | Raw .img |
VDI (auto-converted) |
| Bridge interface detection | ip link |
ip link + carrier + IP check |
which VBoxManage
# Should output a path like /usr/bin/VBoxManage
# If not found, ensure VirtualBox is installed correctlyIf the VM already exists, NeoDev reuses it automatically. To recreate:
neodev vm delete --backend virtualbox
neodev vm create --backend virtualboxWhen disk_image.img is rebuilt, NeoDev automatically re-converts it to
disk_image.vdi on the next run or test if the raw image is newer.
See VDI synchronization.
The VirtualBox backend keeps a single authoritative check,
vbox::ensure_vdi_current(), which runs before the VM starts for both
neodev run --backend virtualbox and neodev test --backend virtualbox.
if disk_image.img exists
and disk_image.vdi exists
and mtime(img) > mtime(vdi):
regenerate VDI from IMG
| Raw image | VDI | Action |
|---|---|---|
| missing | — | fail with Raw disk image not found (never boot a stale VDI) |
| present | missing | VBoxManage convertfromraw disk_image.img disk_image.vdi --format VDI |
| present | mtime(vdi) >= mtime(img) |
no conversion |
| present | mtime(vdi) < mtime(img) |
reconvert |
Details:
- The filesystem timestamps are compared directly; equal timestamps mean the VDI is current. There is no fixed sleep or fudge factor.
- If the VDI is already attached, it is detached (
storageattach … --medium none,closemedium) before conversion and re-attached afterwards, so an attached medium is never blindly deleted or overwritten. VM name, firmware, chipset, AHCI controller, port/device, MAC and network settings are preserved. - If the VM is running or paused, the disk is not touched; NeoDev returns a clear error asking you to stop the VM first.
- After conversion NeoDev verifies that the VDI exists and is at least as new as
the raw image, and that
convertfromrawexited successfully.
The validation harness ships with NeoDev at scripts/vbox-vdi-sync-check.sh.
Run it from the NeoDev checkout, pointing it at this repository:
# Force IMG newer than VDI, then run the VirtualBox test suite and verify.
/path/to/NeoDev/scripts/vbox-vdi-sync-check.sh --neodos-root /path/to/neodos
# Rebuild the image first instead of touching it.
/path/to/NeoDev/scripts/vbox-vdi-sync-check.sh --neodos-root /path/to/neodos --build --timeout 240The script records the IMG/VDI mtimes before and after, runs
neodev test --backend virtualbox, and asserts the VDI is at least as new as the
raw image. Exit status is non-zero on failure.
Ensure your user has permission to run VirtualBox VMs:
# Add user to vboxusers group
sudo usermod -aG vboxusers $USER
# Log out and back inThe old scripts/vbox-setup.sh has been removed. All VirtualBox management
is now handled by NeoDev via:
neodev vm create --backend virtualbox
neodev run --backend virtualbox
neodev test --backend virtualbox