Creating VirtualBox Lab Environments Using Cloud Images
Lately, I have been using VirtualBox more often to adjust and follow existing learning or lab environments that already use VirtualBox as the standard virtualization platform.
One thing that bothered me was how repetitive the VM setup process usually is:
- install OS manually
- configure networking manually
- configure SSH manually
- set static IP manually
- disable IPv6 manually
- configure DNS manually
Compared to other virtualization platforms or cloud providers, this process felt very slow and inefficient.
Because of that, I started using Ubuntu Cloud Images combined with Cloud-Init to make VirtualBox environments faster and easier to provision.
With this approach:
- the VM boots already configured
- SSH is ready immediately
- static IP can already be configured
- custom DNS is already configured
- no manual setup after booting
I only need to:
- adjust the VirtualBox network adapter
- attach the cloud-init ISO
- boot the VM
- SSH directly into the machine
Environment
- Host OS: Ubuntu 26.04 LTS
- Guest OS: Ubuntu Server Cloud Image (Ubuntu 26.04 LTS)
Create meta-data
The meta-data file is used by cloud-init to identify the instance information such as:
- instance ID
- hostname
This helps cloud-init recognize the VM during the initialization process when the machine boots for the first time.
Create a file named:
meta-data
Content:
instance-id: machine
local-hostname: machine
Create user-data
The user-data file is used to automate the initial VM configuration process during the first boot using cloud-init.
In my case, I use this configuration because I want the VM to be immediately ready to use without additional manual setup after booting.
Some configurations that I usually need are:
- creating a user automatically
- configuring SSH public key authentication
- allowing SSH access immediately after boot
- configuring custom DNS
- disabling IPv6 because my environment does not use IPv6
- installing required packages such as
openssh-server - configuring SSH daemon settings
- enabling sudo access without password for lab purposes
This approach helps speed up lab provisioning, especially when repeatedly rebuilding VirtualBox environments for learning or testing purposes.
Create a file named:
user-data
Content:
#cloud-config
hostname: machine
package_update: true
package_upgrade: true
packages:
- openssh-server
users:
- name: ubuntu
sudo: ALL=(ALL) NOPASSWD:ALL
groups: sudo
shell: /bin/bash
lock_passwd: false
ssh_authorized_keys:
- "my-pub-key"
- name: root
ssh_authorized_keys:
- "my-pub-key"
write_files:
- path: /etc/sysctl.d/99-disable-ipv6.conf
content: |
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
owner: root:root
permissions: '0644'
- path: /etc/ssh/sshd_config.d/99-custom.conf
content: |
Port 22
PermitRootLogin prohibit-password
PubkeyAuthentication yes
owner: root:root
permissions: '0644'
- path: /etc/systemd/resolved.conf.d/dns.conf
content: |
[Resolve]
DNS=8.8.8.8
FallbackDNS=1.1.1.1
owner: root:root
permissions: '0644'
runcmd:
- sysctl --system
- systemctl enable ssh
- systemctl restart ssh
- ufw allow 22
- ufw enable
Configure Network
The network-config file is used to configure VM networking automatically during the first boot process.
In my case, I use two network adapters in VirtualBox:
- NAT Adapter for internet access
- Host-Only Adapter for internal lab communication and SSH access from the host machine
Using network-config helps avoid manual network configuration after the VM boots.
This configuration is useful because:
- the VM immediately gets internet access from the NAT adapter
- the Host-Only interface already has a static IP address
- SSH access can be used immediately
- no need to manually edit netplan configuration inside the VM
- the lab environment becomes more consistent and repeatable
Create a file named:
network-config
Content:
#cloud-config
network:
version: 2
ethernets:
enp0s3:
dhcp4: true
dhcp6: false
link-local: []
enp0s8:
dhcp4: false
dhcp6: false
link-local: []
addresses:
- 192.168.56.10/24
routes:
- to: 192.168.56.0/24
via: 192.168.56.1
metric: 100
Generate Cloud-Init ISO
After creating all required files:
meta-datauser-datanetwork-config
the next step is to generate a cloud-init ISO image.
This ISO file will later be attached to the VirtualBox VM and used by cloud-init during the first boot process to automatically apply the VM configuration.
If the mkisofs command is not available yet, install the required package first.
For Ubuntu/Debian:
sudo apt install genisoimage -y
After the package is installed, generate the ISO using:
mkisofs -output cloud-init.iso \
-volid cidata \
-joliet \
-rock \
user-data meta-data network-config
Explanation:
cloud-init.iso: generated cloud-init ISO filecidata: required volume label recognized by cloud-inituser-data: cloud-init configurationmeta-data: instance metadatanetwork-config: automatic network configuration
After the ISO is generated successfully, attach it to the VirtualBox VM together with the Ubuntu cloud image before booting the machine.
VirtualBox Configuration
After creating the cloud-init configuration files and generating the cloud-init ISO, the next step is adjusting the VirtualBox VM configuration so the VM can properly use the Ubuntu cloud image and cloud-init configuration during boot.
In my case, I use:
- Adapter 1 → NAT
- Adapter 2 → Host-Only Adapter
The NAT adapter is used for internet access, while the Host-Only adapter is used for SSH access and internal lab communication.
Then configure the VM by:
- attaching the Ubuntu cloud image as the primary disk
- attaching
cloud-init.isoas the cloud-init ISO - configuring the network adapters
- booting the VM
Once the VM boots for the first time, cloud-init will automatically read the configuration from the attached ISO and apply all predefined settings.
After the VM boots:
- SSH is already enabled
- DNS is already configured
- static IP is already configured
- IPv6 is already disabled
- no additional setup is needed
I can directly SSH into the VM:
This setup helps speed up VirtualBox lab provisioning because most of the initial machine configuration is already automated during the first boot process.
Notes
This setup is based on my personal learning and lab environment needs using VirtualBox.
I have already tested this method myself and it works quite well for quickly provisioning VirtualBox lab environments using Ubuntu Cloud Images and Cloud-Init.
I created this note mainly because I tend to forget the setup steps after some time, so when I need it again in the future, I can simply revisit this personal note instead of repeating the troubleshooting and research process from the beginning.
This is also one of the approaches I found from browsing and experimenting. There are probably many other methods that may be simpler, cleaner, or more automated than this setup.
However, for my current learning environment and workflow, this approach is already practical enough and helps speed up repeated VM provisioning tasks in VirtualBox.