FreeBSD in VirtualBox as a Guest

standarizing unconformity

Index


OpenGL

An ideal world would allow all of us to use our most beloved operating system as the one and only daily driver for work, hobby, gaming and anything in between.

— But since we don't have that ideal world yet. What can we do? The answer is virtualisation.

There is an extensive guide on FreeBSD virtualisation on the Handbook. This guide aims to be a savvy setup only. Further reference should be taken from the Handbook entry.

Virtualisation to the rescue

FreeBSD can be virtualised using VirtualBox. Just download an ISO image from the official site and install it.

For this example, the host is a Windows 10 x64 machine.

FreeBSD should work out of the box on the fresh install inside VirtualBox however, in order to enhance the experience, we need to tweak it a bit.

Since we are using the OS as a guest, we should only need to install the following package:

$ doas pkg install -y virtualbox-ose-additions

And then edit the /etc/rc.conf file to add some VirtualBox options:

vboxguest_enable="YES"
vboxservice_enable="YES"
vboxservice_flags="--disable-timesync"
vboxvfs_load="YES"

You will notice that the moment you restart the vm, only the borderless mouse interaction works out of the box. You can enable the rest of features using the cli tool VBoxClient. The flag --help will tell you all the available options.

Some really cool feature is the bidirectional clipboard. You can enable it by typing VBoxClient --clipboard. If everything goes fine you should be able to perform copy-paste operations from and to both the host and guest.

Features enabled via VBoxClient are not automatically enabled at boot time, you may need to create a custom script that enables the one you want after executing .xinitrc.

Fixing the tty size

Once you boot FreeBSD from VirtualBox, if your screen has a big resolution you'll notice that the buffer offered by default from VirtualBox is too small.

This happens due to the new virtual terminal implemented in FreeBSD, Newcons or vt. vt is in active development and as for now it has limited support for modesetting. It adds the following features over sc:

It's true that when using a KMS driver like i915kms or radeonkms, you can set a mode in /boot/loader.conf like kern.vt.fb.default_mode="1024x768".

Since we are using a virtual machine with no intention on accelerated graphics (at least for now), the fastest solution to our limited tty size is to change the virtual console from vt to sc.

$ doas echo 'kern.vty=sc' >> /boot/loader.conf

Once the setting is changed, we can check the available modes for the sc tty using vidcontrol:

$ vidcontrol -i mode

This workaround is confirmed to be working in 13.2-RELEASE. A screen of 1024x768x24 should be MODE_280

To make your selection permanent, you will have to add it to /etc/rc.conf: allscreens_flags="MODE_280".

Adding custom resolution(s) for X11

If you plan to use the virtual machine with X11, there are a couple steps you can do to improve the screen resolution once you are in the window manager of choice.

First, from the VirtualBox UI under the Settings menu, select the Display tab. You should see there a dropdown menu for the Graphics Controller. Despite a yellow warning discouraging you to use VBoxVGA GC, select it.

Disable the option for Enabling 3D Acceleration if it's enabled.

Then from the OS guest, we can use xrandr(1) to set the resolution. If you don't find the desired resolution when executing the tool without any args, then you can try to setup a custom one.

In this guide, we are missing the 1366x768 resolution in the guest OS. We can add it by first creating a new modeline with:

$ cvt 1366 768 60

where the 60 is the refresh rate in Hz.

It should generate a line that looks like this:

Modeline "1366x768_60.00"  85.25  1366 1440 1576 1784  768 771 781 798 -hsync +vsync

Now, using xrandr(1) we can create the new mode, and add it:

$ xrandr --newmode "1366x768_60.00"  85.25  1366 1440 1576 1784  768 771 781 798 -hsync +vsync
$ xrandr --addmode "1366x768_60.00"

If you run xrandr(1) again, you should see the new mode available in the list. To make the changes permanent, add the previous two lines into ~/.xprofile.

As a last step, we can enable the new mode from .xinitrc: xrandr -s 1366x768_60.00 so each time we launch the graphic environment, the resolution is automatically set.

Enabling shared directories

Using a virtual machine to work often needs that the user can share data between the host and the guest. The most common way to do so is through ssh, but we can also use shared directories from within VirtualBox.

In order to achieve it this way, we need to follow these steps:

From the FreeBSD guest side, we can mount the shared directory as:

$ doas mount -t vboxvfs -o rw,gid=1001,uid=1001 vmshare /mnt/vmshare

where the gid and uid are the owner of the directory and can be obtained by running $ id <username>.

In order to automatically mount the shared directory on boot, we need to add the following line to /etc/fstab:

vmshare /mnt/vmshare vboxvfs rw,gid=1001,uid=1001 0 0

And from the VirtualBox host side, we have to check-enable the Auto-mount option at the Settings tab Shared Folders -> your_shared_dir -> Edit.

From now on, each time you boot your FreeBSD virtual machine, it will automatically mount the shared directory and you will have access to it.

Headless VM and SSH

Once you've tinkered around using a VM for daily work, details and tweaks about enhancing the workflow arise. What if we could launch the VM from within the terminal, work all the time through ssh for example?

Enter the magic of ssh and X11. Despite all the controversy around it, X11 is still a workhorse that can solve a lot in our non-ideal world of operating systems.

Anyway let's go step for step. As for the headless launch of the virtual machine, since our host is a Windows 10 os, we can write a batch script that looks like this:

@echo off
set VMNAME=%1
if "%VMNAME%"=="" set VMNAME=freebsd
VBoxManage startvm "%VMNAME%" --type  headless

It can take a virtual machine name from the first argument, or default to a pre-established name if no first argument is found. Then it uses cli tools from virtual box to launch the VM headless mode.

The script can be improved to include some sort of warning or info about the readiness of the guest

Once launched we can log in through ssh. In order to do so, we can configure some settings to make it work from localhost aka our computer.

In the VirtualBox GUI, go to the image settings, under the network tab, select adapter 1 and check that it is attached to NAT, then enable the Virtual Cable Connected checkbox.

Click on the Port Forwarding button, and in the Port forwarding rules window set the following line:

name protocol Host IP Host Port Guest IP Guest Port
ssh TCP 127.0.0.1 2222 10.0.2.15 22

This way we ensure that from our localhost, through port 2222 we can tell VirtualBox's NAT engine to connect to the VM at 10.0.25, port 22.

Look Ma' we have X11

Now that we now how to work all the time through ssh, how do we launch graphical X11 programs when needed?

For the X11 integration, we can make use of VcXsrv which is a Windows X-server similar to Xming or Cygwin's xwin.

After installing, execute the newly installed XLaunch and follow the actions in order: Multiple windows → Display 0 → "Disable access control" → Finish.

From the PowerShell instance, we may need to set up the DISPLAY variable if running echo $env:DISPLAY returns nothing. To do so, run either set DISPLAY=localhost:0.0 or setx DISPLAY=localhost:0.0.

As for the guest os in the virtual machine we need to edit the sshd_config file, and enable the following options:

X11Forwarding yes
X11DisplayOffset 10
X11UseLocalHost yes

Once done, we need to restart the sshd service (doas service sshd stop|start) and we can log back in using the flags -X or -Y in the ssh command.

ssh -v -Y user@remote-ip -pXXXX

The session launched with this parameters will launch graphical programs when asked. As a quick test you can try:

xclock &

More tips & tricks

As with many other notes, this one is being updated regularly based on knowledge and pitfalls during daily work. As of now instead of adding more minimal sections, all the tricks I'm having to make are listed down below.