Skip to main content

Module 01 — VirtualBox VM Setup

Objective

Create 3 networked Ubuntu Server VMs in VirtualBox and configure SSH access from your Mac Terminal.

By the end of this module you will have:

VM NameIP AddressFuture Role
db-server192.168.56.11PostgreSQL
app-server192.168.56.12Go backend + frontend
web-server192.168.56.13Nginx + Tailscale Funnel

All 3 VMs will be accessible via ssh <hostname> from your Mac, can reach each other over a Host-Only network, and have internet access through NAT.


1. Create the Host-Only Network in VirtualBox

A Host-Only network lets your Mac and the VMs talk to each other on a private subnet (192.168.56.0/24) without exposing anything to the outside world.

1.1 Create the interface

VBoxManage hostonlyif create

This creates an interface named vboxnet0 (if this is your first Host-Only network). If you already have one, it may create vboxnet1 — adjust accordingly.

1.2 Configure the IP address

VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.56.1 --netmask 255.255.255.0

1.3 Disable the built-in DHCP server

We will use static IPs, so the DHCP server is not needed.

VBoxManage dhcpserver remove --ifname vboxnet0 2>/dev/null || true

1.4 Verify

VBoxManage list hostonlyifs

Expected output (key lines):

Name:            vboxnet0
GUID: ...
DHCP: Disabled
IPAddress: 192.168.56.1
NetworkMask: 255.255.255.0

Confirm that IPAddress is 192.168.56.1 and DHCP is Disabled.


2. Create the First VM (db-server)

2.1 Create the VM

VBoxManage createvm --name "db-server" --ostype "Ubuntu_64" --register

2.2 Configure hardware

# 1 GB RAM, 1 CPU
VBoxManage modifyvm "db-server" --memory 1024 --cpus 1

# Enable I/O APIC (required for Ubuntu)
VBoxManage modifyvm "db-server" --ioapic on

# Set boot order: DVD first, then disk
VBoxManage modifyvm "db-server" --boot1 dvd --boot2 disk --boot3 none --boot4 none

2.3 Create a virtual hard disk (10 GB, dynamically allocated)

VBoxManage createmedium disk \
--filename "$HOME/VirtualBox VMs/db-server/db-server.vdi" \
--size 10240 \
--format VDI

2.4 Add a SATA controller and attach the disk

VBoxManage storagectl "db-server" --name "SATA Controller" --add sata --controller IntelAhci

VBoxManage storageattach "db-server" \
--storagectl "SATA Controller" \
--port 0 --device 0 --type hdd \
--medium "$HOME/VirtualBox VMs/db-server/db-server.vdi"

2.5 Add an IDE controller and attach the Ubuntu ISO

Replace the path below with the actual location of your downloaded ISO file.

VBoxManage storagectl "db-server" --name "IDE Controller" --add ide

VBoxManage storageattach "db-server" \
--storagectl "IDE Controller" \
--port 0 --device 0 --type dvddrive \
--medium "$HOME/Downloads/ubuntu-24.04-live-server-amd64.iso"

2.6 Configure network adapters

Adapter 1 — NAT (provides internet access):

VBoxManage modifyvm "db-server" --nic1 nat

Adapter 2 — Host-Only (provides VM-to-VM and Mac-to-VM communication):

VBoxManage modifyvm "db-server" --nic2 hostonly --hostonlyadapter2 vboxnet0

2.7 Start the VM and install Ubuntu Server

VBoxManage startvm "db-server"

This opens a VirtualBox window. Follow the Ubuntu Server installer:

  1. Language: English
  2. Keyboard: Your preferred layout (default is fine)
  3. Installation type: Ubuntu Server (minimized) — select the minimal option
  4. Network: The installer will auto-detect both adapters. Leave the defaults for now (we configure static IPs later).
  5. Storage: Use the entire disk (default).
  6. Profile setup:
    • Your name: trainee
    • Server name: db-server
    • Username: trainee
    • Password: choose something you will remember (e.g., training)
  7. SSH: Check "Install OpenSSH server" when prompted — this saves a step later.
  8. Featured snaps: Skip (do not select any).
  9. Wait for installation to complete, then select Reboot Now.

Tip: If the VM boots back into the installer after reboot, power off the VM and remove the ISO:

VBoxManage storageattach "db-server" \
--storagectl "IDE Controller" \
--port 0 --device 0 --type dvddrive \
--medium emptydrive

Then start the VM again.

2.8 Verify

The VM should boot to a login prompt:

db-server login: _

Log in with username trainee and the password you set.


3. Configure Static IP on db-server

After logging in to db-server, you need to assign a static IP to the Host-Only adapter so the Mac and other VMs can always reach it at 192.168.56.11.

3.1 Identify your network interfaces

ip link show

You should see at least:

  • lo — loopback
  • enp0s3 — NAT adapter (Adapter 1)
  • enp0s8 — Host-Only adapter (Adapter 2)

Note: Interface names may vary. If you see different names, use ip link show output to identify which is which. The Host-Only adapter is typically the second one listed after loopback.

3.2 Edit the Netplan configuration

sudo nano /etc/netplan/00-installer-config.yaml

Replace the entire file contents with:

network:
version: 2
ethernets:
enp0s3:
dhcp4: true
enp0s8:
dhcp4: false
addresses:
- 192.168.56.11/24

What this does:

  • enp0s3 (NAT) uses DHCP — VirtualBox assigns it an IP automatically for internet access.
  • enp0s8 (Host-Only) gets a static IP of 192.168.56.11 on the 192.168.56.0/24 subnet.

Save the file: press Ctrl+O, Enter, then Ctrl+X.

3.3 Apply the configuration

sudo netplan apply

3.4 Verify

ip addr show enp0s8

Expected output (key line):

inet 192.168.56.11/24 brd 192.168.56.255 scope global enp0s8

Also confirm internet still works:

ping -c 2 8.8.8.8

You should see replies from 8.8.8.8.


4. Enable SSH on db-server

If you selected "Install OpenSSH server" during the Ubuntu installation, SSH is already installed and running. Verify and ensure it is enabled.

4.1 Install OpenSSH server (if not already installed)

sudo apt update && sudo apt install -y openssh-server

4.2 Enable and start the SSH service

sudo systemctl enable ssh
sudo systemctl start ssh

4.3 Verify SSH is running on the VM

sudo systemctl status ssh

Expected output (key line):

Active: active (running)

4.4 Verify SSH from your Mac

Open a new Terminal window on your Mac (not inside the VM) and run:

ssh trainee@192.168.56.11

Type yes when asked about the host fingerprint, then enter your password.

Expected result: You are now logged in to db-server from your Mac Terminal.

Type exit to return to your Mac.


5. Clone db-server to Create app-server and web-server

Instead of repeating the entire installation process, we will clone db-server.

5.1 Shut down db-server

From inside the VM (or from your Mac via SSH):

sudo shutdown -h now

Wait until VirtualBox shows the VM as "Powered Off".

5.2 Clone to create app-server

VBoxManage clonevm "db-server" \
--name "app-server" \
--register \
--mode machine \
--options keepallmacs

Note: We use --options keepallmacs here but will reinitialize the MAC address for the Host-Only adapter next, to avoid conflicts.

Reinitialize the MAC address for Adapter 2 (Host-Only):

VBoxManage modifyvm "app-server" --macaddress2 auto

5.3 Clone to create web-server

VBoxManage clonevm "db-server" \
--name "web-server" \
--register \
--mode machine \
--options keepallmacs

Reinitialize the MAC address for Adapter 2:

VBoxManage modifyvm "web-server" --macaddress2 auto

5.4 Start app-server and update its identity

VBoxManage startvm "app-server"

Log in with trainee / your password, then:

Update the hostname:

sudo hostnamectl set-hostname app-server

Update the static IP to 192.168.56.12:

sudo nano /etc/netplan/00-installer-config.yaml

Change the address from 192.168.56.11/24 to 192.168.56.12/24:

network:
version: 2
ethernets:
enp0s3:
dhcp4: true
enp0s8:
dhcp4: false
addresses:
- 192.168.56.12/24

Apply and verify:

sudo netplan apply
ip addr show enp0s8

Expected output (key line):

inet 192.168.56.12/24 brd 192.168.56.255 scope global enp0s8

5.5 Start web-server and update its identity

VBoxManage startvm "web-server"

Log in, then:

Update the hostname:

sudo hostnamectl set-hostname web-server

Update the static IP to 192.168.56.13:

sudo nano /etc/netplan/00-installer-config.yaml

Change the address to 192.168.56.13/24:

network:
version: 2
ethernets:
enp0s3:
dhcp4: true
enp0s8:
dhcp4: false
addresses:
- 192.168.56.13/24

Apply and verify:

sudo netplan apply
ip addr show enp0s8

Expected output (key line):

inet 192.168.56.13/24 brd 192.168.56.255 scope global enp0s8

5.6 Reboot both clones to finalize hostname changes

On app-server:

sudo reboot

On web-server:

sudo reboot

After reboot, each VM's login prompt should show its correct hostname.


6. Configure SSH Config on Your Mac

Setting up an SSH config file lets you connect to each VM by name instead of typing the full IP address every time.

6.1 Create or edit the SSH config file

On your Mac Terminal, run:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/config

Add the following entries (append to the file if it already has content):

Host db-server
HostName 192.168.56.11
User trainee

Host app-server
HostName 192.168.56.12
User trainee

Host web-server
HostName 192.168.56.13
User trainee

Save and exit (Ctrl+O, Enter, Ctrl+X).

6.2 Set correct permissions

chmod 600 ~/.ssh/config

6.3 Verify

Make sure all 3 VMs are running, then from your Mac:

ssh db-server

You should be prompted for the password and logged in to db-server. Type exit, then:

ssh app-server

And:

ssh web-server

All three should connect successfully.


7. Verify Full Connectivity

This final check confirms that every network path is working.

7.1 From your Mac — ping all 3 VMs

ping -c 2 192.168.56.11
ping -c 2 192.168.56.12
ping -c 2 192.168.56.13

Expected: All pings receive replies.

7.2 From each VM — ping the other 2 VMs

SSH into db-server and run:

ping -c 2 192.168.56.12
ping -c 2 192.168.56.13

SSH into app-server and run:

ping -c 2 192.168.56.11
ping -c 2 192.168.56.13

SSH into web-server and run:

ping -c 2 192.168.56.11
ping -c 2 192.168.56.12

Expected: All pings receive replies.

7.3 From each VM — verify internet access

On each VM:

ping -c 2 8.8.8.8

Expected: Replies from 8.8.8.8 on all 3 VMs. This confirms the NAT adapter is working.

7.4 Summary check

Run this from your Mac to quickly verify all connections:

for host in db-server app-server web-server; do
echo "--- $host ---"
ssh "$host" "hostname && ip addr show enp0s8 | grep 'inet ' && ping -c 1 8.8.8.8 | tail -1"
done

Expected output:

--- db-server ---
db-server
inet 192.168.56.11/24 brd 192.168.56.255 scope global enp0s8
rtt min/avg/max/mdev = ... ms
--- app-server ---
app-server
inet 192.168.56.12/24 brd 192.168.56.255 scope global enp0s8
rtt min/avg/max/mdev = ... ms
--- web-server ---
web-server
inet 192.168.56.13/24 brd 192.168.56.255 scope global enp0s8
rtt min/avg/max/mdev = ... ms

Troubleshooting

"SSH connection refused"

Cause: OpenSSH server is not installed or not running on the VM.

Fix: Log in to the VM directly (via VirtualBox window) and run:

sudo apt update && sudo apt install -y openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh
sudo systemctl status ssh

Confirm the status shows active (running).

"Network unreachable to other VMs"

Cause: The Host-Only adapter is not configured correctly.

Fix:

  1. Verify the VM has two network adapters:

    VBoxManage showvminfo "db-server" | grep -i "nic"

    You should see NIC 1 as NAT and NIC 2 as Host-Only.

  2. Inside the VM, verify the Host-Only interface exists:

    ip link show

    You should see enp0s8 (or similar). If it is missing, the adapter is not attached to the VM.

  3. Verify the Host-Only network exists on your Mac:

    VBoxManage list hostonlyifs

"No internet on VM"

Cause: The NAT adapter (Adapter 1) is not configured.

Fix:

  1. Verify Adapter 1 is set to NAT:

    VBoxManage showvminfo "db-server" | grep "NIC 1"

    It should say NAT.

  2. Inside the VM, check that enp0s3 has an IP via DHCP:

    ip addr show enp0s3

    It should have an IP in the 10.0.2.x range.

  3. If not, restart networking:

    sudo netplan apply

"Clone has the same IP as db-server"

Cause: You forgot to update the Netplan configuration on the clone.

Fix: Log in to the clone via the VirtualBox window (not SSH, since the IP conflicts). Then edit the netplan file and change the IP:

sudo nano /etc/netplan/00-installer-config.yaml

Update the address to the correct IP for that VM:

  • app-server: 192.168.56.12/24
  • web-server: 192.168.56.13/24

Then apply:

sudo netplan apply

"Permission denied (publickey)" when using SSH

Cause: SSH password authentication may be disabled.

Fix: Log in via the VirtualBox window and enable password authentication:

sudo nano /etc/ssh/sshd_config

Find the line PasswordAuthentication and set it to yes:

PasswordAuthentication yes

Then restart SSH:

sudo systemctl restart ssh

VBoxManage commands not found

Cause: VirtualBox CLI tools are not in your PATH.

Fix: On macOS, add VirtualBox to your PATH:

export PATH="$PATH:/usr/local/bin"

Or reference the full path:

/usr/local/bin/VBoxManage --version

What You Have Now

You have successfully set up the foundational infrastructure for the rest of this training:

VMHostnameIP AddressAccess
db-serverdb-server192.168.56.11ssh db-server
app-serverapp-server192.168.56.12ssh app-server
web-serverweb-server192.168.56.13ssh web-server

All VMs can reach each other and the internet. You are ready for Module 02.