Your own virtualized desktop FreeBSD lab
If you’re like me, eager to test new stuff in FreeBSD, you might as well run a virtualized FreeBSD laboratory on your desktop. I use Oracle VirtualBox, but you might as well use Microsoft Hyper-V, real hardware, or some other contraption. Couple this with ZFS and boot environments, and you’re even able to rapidly revert any mishaps, although enabled ZFS features can’t be reverted without some help in advance from the virtualization software.
Running such experiments should be economical in terms of disk space and network bandwidth used for the Subversion working copies for both the OS source code and the ports collection, for the downloaded source code of third party software (/usr/ports/distfiles
), for the packages produced, if any, and for the object tree. This paves way for spending less time updating one VM when another VM already has updated say the common working copy for the ports collection and downloaded any missing distfiles, or when one VM has already compiled a new world and kernel that you intend on installing on other VMs.
The only snag is being limited to run a single VM at a time.
If you’re using real hardware, you can avoid this limitation by having a NFS file server export all the needed files to all your individual experiments simultaneously.
Let’s got back to my use of VirtualBox. I use several common virtual harddrives for my VMs:
- Working copy of
base/head
, namedcommon-base-head.vdi
- Working copy of
base/stable/10
, namedcommon-base-stable-10.vdi
- Working copy of
base/stable/9
, namedcommon-base-stable-9.vdi
- Working copy of
base/stable/8
, namedcommon-base-stable-8.vdi
- Working copy of
ports/head
, namedcommon-ports-head.vdi
- Storage for
/usr/ports/distfiles
, namedcommon-ports-distfiles.vdi
- Storage for
/usr/ports/packages
; one for each of the following combinations:base/head
on amd64, namedcommon-packages-amd64-base-head.vdi
base/head
on i386, namedcommon-packages-i386-base-head.vdi
base/stable/10
on amd64, namedcommon-packages-amd64-base-stable-10.vdi
base/stable/10
on i386, namedcommon-packages-i386-base-stable-10.vdi
base/stable/9
on amd64, namedcommon-packages-amd64-base-stable-9.vdi
base/stable/9
on i386, namedcommon-packages-i386-base-stable-9.vdi
base/stable/8
on amd64, namedcommon-packages-amd64-base-stable-8.vdi
base/stable/8
on i386, namedcommon-packages-i386-base-stable-8.vdi
- Storage for
/usr/ports/workdirs
, namedcommon-ports-workdirs.vdi
(under the assumption you’ll always runrm -Rf /usr/ports/workdirs/*
when reusing this drive on other VMs) - Storage for
/usr/obj
; one for each of the following combinations:base/head
on amd64, namedcommon-usr4-obj-amd64-base-head.vdi
base/head
on i386, namedcommon-usr-obj-base-i386-head.vdi
base/stable/10
on amd64, namedcommon-usr-obj-amd64-base-stable-10.vdi
base/stable/10
on i386, namedcommon-usr-obj-i386-base-stable-10.vdi
base/stable/9
on amd64, namedcommon-usr-obj-amd64-base-stable-9.vdi
base/stable/9
on i386, namedcommon-usr-obj-i386-base-stable-9.vdi
base/stable/8
on amd64, namedcommon-usr-obj-amd64-base-stable-8.vdi
base/stable/8
on i386, namedcommon-usr-obj-i386-base-stable-8.vdi
I might have gone a bit overboard with all my virtual harddrives, but I guess it’ll pay up in the long run.
All these virtual harddrives are 5 GiB (5120 MiB) in size. That should be enough space for the foreseeable future. Any of these drives and their filesystems may be expanded at any time.
A question arrives, namely how to get started. I recommend you start by creating a single VM running base/release/10
or some snapshot of base/stable/10
. The reason is that svnlite
is available straight out of the box in these versions. base/head
is simply to noisy with its GENERIC
kernel, and after all it’s a moving target.
Start by creating a new VM. Remove the IDE controller, as it has low performance both in real life and when emulated. Add the SATA controller. Reattach the VM’s ordinary virtual harddrives and one DVD drive to the SATA controller. Try not to place the DVD drive beyond the fourth SATA port as VirtualBox doesn’t detect DVD drives that high up in the chain. Add the SCSI and the SAS controllers. Create the first 15 common virtual harddrives and attach them to the SCSI controller, taking care to name the virtual harddrives properly and placing them in a directory not associated with any particular VM. The directory “C:\Users\username\VirtualBox VMs
” should be suitable for this purpose. Make sure none of these drives occupies SCSI port 7 as this LUN is reserved for the SCSI controller itself. Any harddrive at SCSI port 7 will NOT be detected by FreeBSD. Create the last 8 common virtual harddrives and attach them to the SAS controller. Install a small system on the VM’s ordinary virtual harddrives. Reboot into the preparation system.
You can also use the command line tool VBoxManage
to create the common virtual harddrives:
C: cd "\Users\username\VirtualBox VMs" C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-base-head.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-base-stable-10.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-base-stable-9.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-base-stable-8.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-ports-head.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-ports-distfiles.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-amd64-base-head.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-i386-base-head.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-amd64-base-stable-10.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-i386-base-stable-10.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-amd64-base-stable-9.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-i386-base-stable-9.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-amd64-base-stable-8.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-packages-i386-base-stable-8.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-ports-workdirs.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-amd64-base-head.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-i386-base-head.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-amd64-base-stable-10.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-i386-base-stable-10.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-amd64-base-stable-9.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-i386-base-stable-9.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-amd64-base-stable-8.vdi C:\Program Files\Oracle\VirtualBox\VboxManage.exe createhd --size 5120 --filename common-usr-obj-i386-base-stable-8.vdi
The SATA controller can control up to 30 units. The SCSI controller can control up to 15 units. The SAS controller can control up to 8 units. The SATA controller is run by the ahci
driver, while the SCSI and the SAS controllers are both run by the mpt
driver.
Assuming your common virtual harddrives are named and attached as follows:
Filename | SCSI port | Device name |
---|---|---|
common-base-head.vdi |
0 | da0 |
common-base-stable-10.vdi |
1 | da1 |
common-base-stable-9.vdi |
2 | da2 |
common-base-stable-8.vdi |
3 | da3 |
common-ports-head.vdi |
4 | da4 |
common-ports-distfiles.vdi |
5 | da5 |
common-packages-amd64-base-head.vdi |
6 | da6 |
Add nothing here | 7 | |
common-packages-i386-base-head.vdi |
8 | da7 |
common-packages-amd64-base-stable-10.vdi |
9 | da8 |
common-packages-i386-base-stable-10.vdi |
10 | da9 |
common-packages-amd64-base-stable-9.vdi |
11 | da10 |
common-packages-i386-base-stable-9.vdi |
12 | da11 |
common-packages-amd64-base-stable-8.vdi |
13 | da12 |
common-packages-i386-base-stable-8.vdi |
14 | da13 |
common-ports-workdirs.vdi |
15 | da14 |
Filename | SAS port | Device name |
---|---|---|
common-usr-obj-amd64-base-head.vdi |
0 | da15 |
common-usr-obj-i386-base-head.vdi |
1 | da16 |
common-usr-obj-amd64-base-stable-10.vdi |
2 | da17 |
common-usr-obj-i386-base-stable-10.vdi |
3 | da18 |
common-usr-obj-amd64-base-stable-9.vdi |
4 | da19 |
common-usr-obj-i386-base-stable-9.vdi |
5 | da20 |
common-usr-obj-amd64-base-stable-8.vdi |
6 | da21 |
common-usr-obj-i386-base-stable-8.vdi |
7 | da22 |
I chose the SCSI and SAS controllers to make the device names intuitive while we’re preparing the virtual harddrives.
The next step is to create GPT partition tables, UFS partitions, and initialize the filesystems on each virtual harddrive:
for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22; do \ gpart create -s GPT da$d; \ gpart add -t freebsd-ufs da$d; \ newfs /dev/da${d}p1; \ done
GPT labels are a sure thing to keep track of the filesystems no matter what order you attach the drives in your future VMs:
gpart modify -i 1 -l base_head da0 gpart modify -i 1 -l base_stable_10 da1 gpart modify -i 1 -l base_stable_9 da2 gpart modify -i 1 -l base_stable_8 da3 gpart modify -i 1 -l ports_head da4 gpart modify -i 1 -l ports_distfiles da5 gpart modify -i 1 -l packages_amd64_base_head da6 gpart modify -i 1 -l packages_i386_base_head da7 gpart modify -i 1 -l packages_amd64_base_stable_10 da8 gpart modify -i 1 -l packages_i386_base_stable_10 da9 gpart modify -i 1 -l packages_amd64_base_stable_9 da10 gpart modify -i 1 -l packages_i386_base_stable_9 da11 gpart modify -i 1 -l packages_amd64_base_stable_8 da12 gpart modify -i 1 -l packages_i386_base_stable_8 da13 gpart modify -i 1 -l ports_workdirs da14 gpart modify -i 1 -l usr_obj_amd64_base_head da15 gpart modify -i 1 -l usr_obj_i386_base_head da16 gpart modify -i 1 -l usr_obj_amd64_base_stable_10 da17 gpart modify -i 1 -l usr_obj_i386_base_stable_10 da18 gpart modify -i 1 -l usr_obj_amd64_base_stable_9 da19 gpart modify -i 1 -l usr_obj_i386_base_stable_9 da20 gpart modify -i 1 -l usr_obj_amd64_base_stable_8 da21 gpart modify -i 1 -l usr_obj_i386_base_stable_8 da22
Now we need to mount the harddrives responsible for the Subversion working copies and populate them with their contents:
mkdir /mnt/base_head mkdir /mnt/base_stable_10 mkdir /mnt/base_stable_9 mkdir /mnt/base_stable_8 mkdir /mnt/ports_head mount -t ufs /dev/gpt/base_head /mnt/base_head mount -t ufs /dev/gpt/base_stable_10 /mnt/base_stable_10 mount -t ufs /dev/gpt/base_stable_9 /mnt/base_stable_9 mount -t ufs /dev/gpt/base_stable_8 /mnt/base_stable_8 cd /mnt/base_head svnlite co svn://svn0.us-west.freebsd.org/base/head . cd /mnt/base_stable_10 svnlite co svn://svn0.us-west.freebsd.org/base/stable/10 . cd /mnt/base_stable_9 svnlite co svn://svn0.us-west.freebsd.org/base/stable/9 . cd /mnt/base_stable_8 svnlite co svn://svn0.us-west.freebsd.org/base/stable/8 . cd /mnt/ports_head svnlite co svn://svn0.us-west.freebsd.org/ports/head . mkdir distfiles local packages workdirs
Feel free to choose any access method and Subversion mirror.
A bit of tidying up might be in order:
cd / umount /mnt/base_head umount /mnt/base_stable_10 umount /mnt/base_stable_9 umount /mnt/base_stable_8 umount /mnt/ports_head rmdir /mnt/base_head rmdir /mnt/base_stable_10 rmdir /mnt/base_stable_9 rmdir /mnt/base_stable_8 rmdir /mnt/ports_head
Remember to add the following line to the /etc/make.conf
file in every VM:
WRKDIRPREFIX=/usr/ports/workdirs
A VM running amd64 of base/head
will need these lines in its /etc/fstab
file:
/dev/gpt/base_head /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_amd64_base_head /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_amd64_base_head /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running i386 of base/head
will need these lines in its /etc/fstab
file:
/dev/gpt/base_head /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_i386_base_head /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_i386_base_head /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running amd64 of base/stable/10
will need these lines in its /etc/fstab
file:
/dev/gpt/base_stable_10 /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_amd64_base_stable_10 /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_amd64_base_stable_10 /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running i386 of base/stable/10
will need these lines in its /etc/fstab
file:
/dev/gpt/base_stable_10 /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_i386_base_stable_10 /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_i386_base_stable_10 /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running amd64 of base/stable/9
will need these lines in its /etc/fstab
file:
/dev/gpt/base_stable_9 /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_amd64_base_stable_9 /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_amd64_base_stable_9 /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running i386 of base/stable/9
will need these lines in its /etc/fstab
file:
/dev/gpt/base_stable_9 /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_i386_base_stable_9 /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_i386_base_stable_9 /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running amd64 of base/stable/8
will need these lines in its /etc/fstab
file:
/dev/gpt/base_stable_8 /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_amd64_base_stable_8 /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_amd64_base_stable_8 /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2
A VM running i386 of base/stable/8
will need these lines in its /etc/fstab
file:
/dev/gpt/base_stable_8 /usr/src ufs rw,late 2 2 /dev/gpt/usr_obj_i386_base_stable_8 /usr/obj ufs rw,late 2 2 /dev/gpt/ports_head /usr/ports ufs rw,late 2 2 /dev/gpt/ports_distfiles /usr/ports/distfiles ufs rw,late 2 2 /dev/gpt/packages_i386_base_stable_8 /usr/ports/packages ufs rw,late 2 2 /dev/gpt/ports_workdirs /usr/ports/workdirs ufs rw,late 2 2