DragonFly BSD Multiboot Installation Tutorial

Martin Aleksandrov Ivanov martin.ivanov at greenpocket.de
Sun May 17 02:01:00 PDT 2020


I finally finished my fully tested tutorial for installing DragonFly to 
a disk partition in a multiboot configuration with rEFInd. In the 
following days I will add parts of it to relevant places in the 
DragonFly documentation, as was already suggested to me. The tutorial is 
at the end of this post. I am not a computer scientist by education, so 
I cannot pretend to have the most precise terminology. This is rather a 
practically oriented manual to be used by anybody who loves BSD and 
wants to play with DragonFly. That being said, I would be happy to get 
your critical commentaries.

Have fun!

Best regards,

Martin Ivanov

DragonFly BSD Multiboot Installation Tutorial

This tutorial contains step-by-step instructions for a manual 
installation of DragonFly to a hard
drive slice. The content has been tested on a UEFI Laptop with an SSD 
hard drive. I cannot enough
recommend reading 
https://www.dragonflybsd.org/docs/handbook/UNIXBasics/#index11h2 before 
this tutorial, especially the sections on Disk Organisation, Choosing 
File System Layout, and Disk
Slices, Partitions and local UNIX file systems.

Currently, the DragonFly BSD Installer only supports a full-disk 
installation. Obviously, this
set-up is not appropriate for multibooting with other operating systems 
(OSs), because each OS
resides on it own hard drive slice. Therefore, for multiboot we have to 
install DragonFly to a hard
drive slice. For this, we have to do a manual installation.

Information on how to create the DragonFly install medium is available on
https://www.dragonflybsd.org/docs/handbook/Installation. After booting 
DragonFly with the install
medium, login as root. To see how your hard drive is recognised, issue:

# if you have a Hard Disk Drive (HDD)
camcontrol devlist


# if you have a Solid State Drive (SSD)
nvmectl info

An HDD will be recognised as da0 and an SSD as nvme0. For simplicity, 
hereafter we assume that we
have an SSD that is recognised as nvme0. If you have an HDD, you can 
simply substitute nvme0 with
da0 in the following instructions.

To be safe, clean up the starting sectors of the disk drive from 
remnants of any previous partitioning:

dd if=/dev/zero of=/dev/nvme0 count=1024 bs=1m

If you omit this step, you may encounter problems creating file systems 
on your drive partitions.
I made this mistake and when I attempted to format the EFI System 
Partition (ESP) at a later stage
with newfs_msdos, I got some obscure error messages about "read-only 
file system".  You definitely
do not want this.

Partition the hard drive

Here we assume GUID Partition Table (GPT) partitioning (see the gpt 
manual page: man gpt). For MBR
partitioning with fdisk, you can take a look at one of my earlier posts:

# destroy any existing GPT partition table
gpt destroy nvme0

# create a new partition table
gpt create -f nvme0

In between, to view the current partition table, you can issue:

# view current partition table
gpt -v show -l nvme0

Before we start adding the slices, we note that slice sizes are 
specified in number of disk drive
sectors. Normally, a sector has 512 bytes. To check that, you can run:

dmesg | grep blksize

to find out the sector size. The output on my machine looks like this:
nvme0: Disk nvme0 ns=1 blksize=512 lbacnt=1000215216 cap=476GB 
which confirms that the sector size is 512 bytes. So, if we need a slice 
of size S bytes, we have to
specify S/512 number of sectors for it.

We proceed to create the ESP that will be half a GiB, that is 512 MiB. 
The ESP will be our first
slice and hence obtain a slice number of 0. The corresponding number of 
sectors is
(512 * 1024 ** 2) / 512 = 1048576.

# create an ESP of 512 MiB
gpt add -i 0 -s 1048576 -t efi nvme0

In the above command, -i specifies slice number 0, -s the slice size in 
sectors, and -t specifies the
slice type that can be one of: efi, swap, ufs, hfs, linux, dfly, hammer2.

# label the EFI slice: the label has to be UTF-8
gpt label -i 0 -l "EFI System" nvme0

# add a 200 GiB DragonFly slice
gpt -v show nvme0 gpt add -i 1 -s 419430400 -t dfly nvme0

# label the DragonFly slice
gpt label -i 1 -l "DragonFly BSD" nvme0

In UNIX, each slice can be partitioned with disklabel partitions. It is 
the disklabel partitions
that are normally referred to as "partitions" in the UNIX world. GPT 
partitions are known as
slices. Each disklabel partition can be formatted with a different file 
On the DragonFly slice we will create three partitions: "a" for /boot, 
"b" for swap and "d" for the root
file system.

# create a standard virgin disk label for the DragonFly slice
disklabel64 -r -w nvme0s1 auto

# create the disklabel partitions on the DragonFly slice
disklabel64 -e nvme0s1

The above command opens a text editor, where we can describe the 
partitions we want to add, with their
sizes and file system types. We add the following three lines:
a: 1G * 4.2BSD
b: 16G * swap
d: * * HAMMER2
to specify a partition "a" of 1 GiB that will carry a UFS file system, a 
partition "b" of 16 GiB for
swap, and a partition "d" encompassing the remaining space on the 
DragonFly slice for the root file
system. The size of the swap space depends on the available RAM. For 
more information on selecting
the swap size, see https://itsfoss.com/swap-size.

# add a 200 GiB OpenBSD slice
gpt add -i 2 -s  419430400 -t "Unused" nvme0 # specifying -t "OpenBSD" 
is not supported

# label the OpenBSD slice
gpt label -i 2 -l "OpenBSD" nvme0

# add a linux slice encompassing the remaining space on the disk drive
gpt add -i 3 -t linux nvme0

# label the linux slice: I install Slackware Linux, but you can specify 
the distro you like here ;-)
gpt label -i 3 -l "Slackware Linux"

Now that we have sliced the hard drive, we can proceed with installing 
DragonFly BSD onto its

Create file systems on the ESP slice and the DragonFly disklabel partitions:

# format the ESP slice with FAT file system
newfs_msdos nvme0s0

# format the "a" partition on the DragonFly slice with UFS
newfs nvme0s1a

# format the "d" partition on the DragonFly slice with HAMMER2
newfs_hammer2 -L ROOT /dev/nvme0s1d

When creating mount points and mounting disk partitions it is important 
to keep in mind that the
directory hierarchy determines the order of the commands. More 
specifically, if partition B is to be
mounted under a directory of partition A, then first partition A has to 
be mounted, then the mount
point for partition B created on A, and finally partition B mounted. If 
you proceed first creating the
mount points and then mounting the partitions without heeding the 
hierarchy, as I did originally,
you will get into trouble :-). Be warned about that.

Mount the DragonFly partitions:

mount_hammer2 nvme0s1d /mnt
mkdir /mnt/boot
mount nvme0s1a /mnt/boot

Mount the EFI System partition:

mkdir /mnt/efimnt
mount_msdos /dev/nvme0s0 /mnt/efimnt

Create the required directory structure of the ESP:

mkdir -p /mnt/efimnt/EFI/BOOT

We will use rEFInd (http://www.rodsbooks.com/refind) as multiboot 
manager. Prior to starting the
DragonFly installation, make sure to have downloaded the latest rEFInd 
version as a binary zip file
from http://www.rodsbooks.com/refind/getting.html, unzipped it and 
written it to a USB stick.

Install rEFInd to the ESP:

# create a mount point for the USB stick with the rEFInd executables
mkdir /mnt/usb

# go to the EFI/BOOT directory of the ESP
cd /mnt/efimnt/EFI/BOOT

Insert the USB stick with the rEFInd executables. On inserting the 
stick, the system reports the new
device. You can double-check how it is recognised by issuing:

camcontrol devlist

We assume the USB stick is recognised as /dev/da9.

# mount the USB stick with the rEFInd executables (assuming it is /dev/da9)
mount_msdos /dev/da9s1 /mnt/usb

# copy the rEFInd executable to the current directory (assuming you have 
rEFInd version 0.12.0)
cp -r /mnt/usb/refind-bin-0.12.0/refind/* .

# unmount the USB stick with the rEFInd executables and delete its mount 
umount /mnt/usb
rmdir /mnt/usb

Remove the unnecessary drivers, efi executables and tools. E.g, for an 
amd64 machine you have to
remove the *aa64* and *ia32* files and directories:

# remove unnecessary stuff assuming an amd64 machine
rm -rf *aa64* *ia32*

# rename the rEFInd executable
mv refind_x64.efi bootx64.efi

# copy the DragonFly BSD boot1.efi under a different name
cp /boot/boot1.efi bootx64-dragonflybsd.efi

# configure rEFInd
mv refind.conf-sample refind.conf

# edit refind.conf
vi refind.conf
# add this section:
menuentry "DragonFly BSD" {
     loader /EFI/BOOT/bootx64-dragonflybsd.efi
     icon /EFI/BOOT/icons/os_freebsd.png

You may ask why we provided the freebsd icon above? Well, at the time of 
writing this tutorial there
is no os_dragonflybsd.png icon. If you wish, you can create your own one 
and copy it to the ./icons
directory; it has to be a 128 x 128 png. Of course, as you install other 
OSs at a later stage, you
have to provide relevant entries for them in the refind.conf file and 
copy the necessary booting
executables to the ESP. Information on this is usually provided by the 
OS or available as part
of the rEFInd documentation. Caveat: when installing the other OSs, make 
sure they do not overwrite
the ESP we just created. It would be best to not install rEFInd using 
the OS installer, but do this
manually: the process involves copying a few relevant files to the ESP 
and making a respective entry in

# leave the ESP

HAMMER2 is a file system that allows creating pseudo file systems (PFSs) 
within it, which
dynamically share a common storage space. Oversimplified, you can think 
of HAMMER2 as of a logical
volume manager (LVM) with logical volumes (PFSs) that are not of fixed 
size. Each PFS obtains as
much drive space as it needs. In the following, we create a disk layout 
that is relatively
complicated, as it creates separate PFSs for directories that are 
separately mounted in many UNIX
installations. Of course, you are free to devise another layout that 
best suits your needs. Here, we
show an example layout and the steps to set it up in DragonFly.

Create the HAMMER2 PFSs. The path to the mounted HAMMER2 ROOT filesystem 
is specified via the -s

hammer2 -s /mnt pfs-create usr
hammer2 -s /mnt pfs-create usr.dports
hammer2 -s /mnt pfs-create usr.local
hammer2 -s /mnt pfs-create usr.src
hammer2 -s /mnt pfs-create var
hammer2 -s /mnt pfs-create home
hammer2 -s /mnt pfs-create build

To view the created PFSs, you can in between issue:

hammer2 pfs-list /mnt

Create the mount points and mount the PFSs, taking care of the directory 
hierarchy (see the note
above on creating mount points and mounting partitions):

mkdir /mnt/usr
mount_hammer2 @usr /mnt/usr # note how a PFS is specified by a "@" in front

mkdir /mnt/usr/dports
mkdir /mnt/usr/local
mkdir /mnt/usr/src
mkdir /mnt/var
mkdir /mnt/build

mount_hammer2 @usr.dports /mnt/usr/dports
mount_hammer2 @usr.local /mnt/usr/local
mount_hammer2 @usr.src /mnt/usr/src
mount_hammer2 @var /mnt/var
mount_hammer2 @build /mnt/build

Note that among these directories there are such with non-existent 
(/usr/dports and /usr/src) or
empty (/build and /home) counterparts on the install medium. You may ask 
why we mount /usr/dports
and /usr/src although they will remain empty; the answer is, as cpdup 
does not cross mount
boundaries, this prevents cpdup from asking whether to delete them 
(because they do not exist on the
installation media) when copying /usr from the install medium at a later 
stage. There is no need to
mount /home, as it is an independent file system that will remain empty. 
/build is something like
scratch space in DragonFly BSD. On it, we create directories for file 
systems that do not normally
need backup. At a later stage, we will null-mount these directories to 
their respective mount points
in the hierarchy.

# create directories for file systems that do not normally need backup
mkdir /mnt/build/usr.distfiles
mkdir /mnt/build/usr.obj
mkdir /mnt/build/var.cache
mkdir /mnt/build/var.crash
mkdir /mnt/build/var.log
mkdir /mnt/build/var.run
mkdir /mnt/build/var.spool

# create the mount points for the /build null mounts that do not exist 
on the install medium
mkdir /mnt/usr/distfiles

# create mount points for the non-empty /build null mounts:
mkdir /mnt/var/crash
mkdir /mnt/var/log
mkdir /mnt/var/run
mkdir /mnt/var/spool

There is no need to create mount points for the empty /build null mounts 
that exist on the install
medium (/usr/obj and /var/cache), as they will be copied by cpdup 
together with /usr and /var at a
later stage.

# mount the non-empty /build null mounts:
mount_null /mnt/build/var.crash /mnt/var/crash
mount_null /mnt/build/var.log /mnt/var/log
mount_null /mnt/build/var.run /mnt/var/run
mount_null /mnt/build/var.spool /mnt/var/spool

Mount /usr/distfiles as it does not exist under /usr on the installation 
media (to prevent cpdup
from asking whether to delete it when copying /usr at a later stage):

mount_null /build/usr.distfiles /mnt/usr/distfiles

Install DragonFly by copying the non-empty file systems. Luckily, cpdup 
won't cross mount boundaries
on the source or destination, so it takes a few commands:

cpdup / /mnt
cpdup /boot /mnt/boot
cpdup /usr /mnt/usr
cpdup /usr/local /mnt/usr/local
cpdup /var /mnt/var

# copy the non-empty /build null mounts
cpdup /var/crash /mnt/var/crash
cpdup /var/log /mnt/var/log
cpdup /var/run /mnt/var/run
cpdup /var/spool /mnt/var/spool

DragonFly BSD uses a different /etc from the one present on the install 
medium. The /etc on the
install medium is only used during installation. It is the /etc.hdd 
directory that is intended
for permanent use. We can delete /etc, but we prefer to store it under 
the name /etc.live instead:

mv /mnt/etc /mnt/etc.live
mv /mnt/etc.hdd /mnt/etc

There is no example fstab in /etc.hdd. The one from /etc.live has to be 

cp /mnt/etc.live/fstab.example /mnt/etc/fstab

Describe ALL mounts in fstab:

vi /mnt/etc/fstab
# the fstab for the above disk layout must have the following content:

/dev/nvme0s1a /boot ufs rw 1 1
/dev/nvme0s1b none swap sw 0 0
/dev/nvme0s1d / hammer2 rw 1 1
@usr /usr hammer2 rw 0 0
@usr.dports /usr/dports hammer2 rw 0 0
@usr.local /usr/local hammer2 rw 0 0
@usr.src /usr/src hammer2 rw 0 0
@var /var hammer2 rw 0 0
@home /home hammer2 rw,nosuid 0 0 @build
/build hammer2 rw 0 0
/build/usr.distfiles /usr/distfiles null rw 0 0
/build/usr.obj /usr/obj null rw 0 0
/build/var.cache /var/cache null rw 0 0
/build/var.crash /var/crash null rw 0 0
/build/var.log /var/log null rw 0 0
/build/var.run /var/run null rw 0 0
/build/var.spool /var/spool null rw 0 0
tmpfs /tmp tmpfs rw,nosuid,noexec,nodev 0 0
tmpfs /var/tmp tmpfs rw,nosuid,noexec,nodev 0 0
proc /proc procfs rw 0 0

# specify the correct root file system
vi /mnt/boot/loader.conf

Unmount mounted filesystems:

umount /mnt/efimnt
umount /mnt/boot
umount /mnt/usr/distfiles
umount /mnt/usr/dports
umount /mnt/usr/local
umount /mnt/usr/src
umount /mnt/var/crash
umount /mnt/var/log
umount /mnt/var/run
umount /mnt/var/spool
umount /mnt/usr
umount /mnt/var
umount /mnt/build
umount /mnt

# halt to give you time to remove the install medium

Wait for the system to halt, remove the installation media after that, 
and finally press any key to

Basic Configuration of DragonFly BSD

Here, I post the first settings I make on my machine after a fresh 
DragonFly BSD installation. You
can use them as an example.

# set a root password

# set time zone

# add a user
adduser -s -config_create

The above command starts an interrogation. For my user, I select:

login group: wheel

in order to be able to su to root. I also:

invite my user into other groups: guest staff

If your video card is fully supported you may also invite your user to 
the group video. Otherwise,
having the video group may cause instability to the xorg server.

Shell: tcsh

vi /etc/rc.conf
# add the following lines:
wlans_iwm0="wlan0" # this line configures my wireless interface, for you 
it may be a bit different
ifconfig_wlan0="WPA DHCP" # this line configures my internet connection, 
for you it may be different
dntpd_enable="YES" # time daemon to automatcally get correct time from 
hostname="dragonfly" # make sure hostname only contains lowercase letters

vi /boot/loader.conf
# add the following lines:
snd_hda_load="YES" # this enables sound
# the following two lines load the correct kernel module for my wifi 
card; for your machine
# they may be different:

# configure wireless connection
vi /etc/wpa_supplicant.conf
# add the following section:

# install some packages for development desktop use
pkg install git tig gcc xorg xdm cwm lumina xfce kde5 libreoffice vim 
hexchat texlive-full chromium \
thunderbird wget gkrellm2 knotes telegram-desktop

vi /etc/sysctl.conf:
kern.ipc.shm_allow_removed=1 # necessary for google-chrome
hw.snd.default_unit=3 # I need this to redirect sound to my external 
sound system

# configure X server:
Xorg -configure
cp xorg.conf.new /etc/X11/xorg.conf
# if your graphics card is not fully supported, add to the Section "Device":
vi /etc/X11/xorg.conf
Option "Accel" "False"

To limit the mouse cursor within the visible screen, assuming a 
resolution of 1920x1080:
vi .xinitrc
# at the start of the file add:
xrandr --output "Screen 0" --mode 1920x1080 --fb 1920x1080
# to start XFCE add:
exec ck-launch-session startxfce4
# to start kde5 add:
exec ck-launch-session startplasma-x11

Some packages have very useful post-install messages. To view them:
pkg info -aD | gvim -

More information about the Users mailing list