Important notes:
1) This tutorial assumes you have the OS you want to dual-boot with already installed on your drive, and that you already have freed up some disk space. Essentially, you will be installing FreeBSD with root-on-ZFS on the remaining free space of the disk, instead of using the entire drive as it's done by default by FreeBSD's installer.
2) This method only works for GPT disk layouts using UEFI mode. Legacy BIOS and MBR disks are not supported. As always, make sure to disable Secure Boot and Fast Boot.
3) Here, we use ada0 (disk 1) for everything, and we assume your disk already has an EFI partition, located in partition 1 (ada0p1). Change it according to your setup, if needed. Run
4) We will create our ZFS Pool with "Stripe" as the Virtual Device type (vdev).
5) After completing installation, to be able to choose what OS to boot you'll need to either install rEFInd boot manager, or use GRUB (assuming the other OS is a Linux distro). I personally recommend rEFInd, but I won't detail how to install it here. Neither will I explain how to alter the GRUB config. Just gonna show you how the respective entries should look like in each case.
6) Finally, I'm not responsible for any problem or data loss you may experience. This tutorial is not an unsafe procedure if you understand what you're doing (especially in regards to selecting the correct disk where you want to install). Anyway, do it at your own risk!
Well, let's start:
First of all, boot your FreeBSD install USB stick. Proceed installing as usual, until you reach the "Partitioning" stage. Here, choose the "Shell" option, so you can create your swap and ZFS partitions by hand:
# Load the ZFS kernel module:
# Force 4K sectors:
# Create a swap partition (in this case, of 4 GB size):
# Create a ZFS partition to fill the remaining free space:
# Mount tmpfs in /mnt, where the installer will install the operating system to:
# Create your zroot pool:
# Create ZFS file system hierarchy:
# Define the default ZFS datasets for root zpool:
zfs create -o mountpoint=/tmp -o exec=on -o setuid=off zroot/tmp # We'll be using tmpfs for /tmp.
# Create a symlink to /usr/home:
# Change /tmp and /var/tmp permissions:
chmod 1777 /mnt/tmp # Not needed now.
# Configure the Boot Environment:
# Instruct FreeBSD to mount ZFS pools during system initialization:
# Add an fstab entry to use a GELI-encrypted swap partition:
# Add an fstab entry to use tmpfs for /tmp:
# Mount the existing EFI partition of your disk:
# Create FreeBSD boot directory in the EFI partition:
# Copy FreeBSD loader to the previously created directory:
# Now add a UEFI boot entry:
# Unmount EFI partition:
# Exit Shell Partitioning mode, so bsdinstall can continue and complete the installation:
After finishing the installation, don't forget to add a boot entry for FreeBSD in GRUB or rEFInd.
Here I share some sample entries to guide you a bit. Remember to modify them to reflect your own reality:
# For GRUB:
# For rEFInd, add something like this at the end of refind.conf:
That's all. Hope you find it useful!
Sources:
https://www.freebsd.org/doc/handbook/bsdinstall-partitioning.html
https://wiki.freebsd.org/RootOnZFS/GPTZFSBoot
http://kev009.com/wp/2016/07/freebsd-uefi-root-on-zfs-and-windows-dual-boot/
https://github.com/freebsd/freebsd-src/blob/releng/13.0/usr.sbin/bsdinstall/scripts/zfsboot
https://github.com/freebsd/freebsd-src/blob/releng/13.0/usr.sbin/bsdinstall/scripts/bootconfig
EDIT 1:
-Added some sources.
EDIT 2:
-Reworded the title for better clarity.
-Added a note about FreeBSD's efi loader name used in this tutorial.
-Removed /tmp from ZFS datasets, to use a tmpfs /tmp instead. This way it provides better performance and doesn't cause troubles with some programs, like Firefox on Wayland, for instance.
UPDATE (2021/02/12):
-Fixed some little issues.
-Added useful efibootmgr command.
-Updated FreeBSD efi boot loader name and location to match new FreeBSD 13.0 defaults.
-Added more sources.
1) This tutorial assumes you have the OS you want to dual-boot with already installed on your drive, and that you already have freed up some disk space. Essentially, you will be installing FreeBSD with root-on-ZFS on the remaining free space of the disk, instead of using the entire drive as it's done by default by FreeBSD's installer.
2) This method only works for GPT disk layouts using UEFI mode. Legacy BIOS and MBR disks are not supported. As always, make sure to disable Secure Boot and Fast Boot.
3) Here, we use ada0 (disk 1) for everything, and we assume your disk already has an EFI partition, located in partition 1 (ada0p1). Change it according to your setup, if needed. Run
gpart show
to be sure.4) We will create our ZFS Pool with "Stripe" as the Virtual Device type (vdev).
5) After completing installation, to be able to choose what OS to boot you'll need to either install rEFInd boot manager, or use GRUB (assuming the other OS is a Linux distro). I personally recommend rEFInd, but I won't detail how to install it here. Neither will I explain how to alter the GRUB config. Just gonna show you how the respective entries should look like in each case.
6) Finally, I'm not responsible for any problem or data loss you may experience. This tutorial is not an unsafe procedure if you understand what you're doing (especially in regards to selecting the correct disk where you want to install). Anyway, do it at your own risk!
Well, let's start:
First of all, boot your FreeBSD install USB stick. Proceed installing as usual, until you reach the "Partitioning" stage. Here, choose the "Shell" option, so you can create your swap and ZFS partitions by hand:
# Load the ZFS kernel module:
kldload zfs
# Force 4K sectors:
sysctl vfs.zfs.min_auto_ashift=12
# Create a swap partition (in this case, of 4 GB size):
gpart add -a 4k -l swap0 -s 4G -t freebsd-swap ada0
# Create a ZFS partition to fill the remaining free space:
gpart add -a 4k -l zfs0 -t freebsd-zfs ada0
# Mount tmpfs in /mnt, where the installer will install the operating system to:
mount -t tmpfs tmpfs /mnt
# Create your zroot pool:
zpool create -f -o altroot=/mnt -O compress=lz4 -O atime=off -m none zroot /dev/gpt/zfs0
# Create ZFS file system hierarchy:
zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ zroot/ROOT/default
# Define the default ZFS datasets for root zpool:
zfs create -o mountpoint=/usr -o canmount=off zroot/usr
zfs create zroot/usr/home
zfs create -o setuid=off zroot/usr/ports
zfs create zroot/usr/src
zfs create -o mountpoint=/var -o canmount=off zroot/var
zfs create -o exec=off -o setuid=off zroot/var/audit
zfs create -o exec=off -o setuid=off zroot/var/crash
zfs create -o exec=off -o setuid=off zroot/var/log
zfs create -o atime=on zroot/var/mail
zfs create -o setuid=off zroot/var/tmp
# Create a symlink to /usr/home:
ln -s /usr/home /mnt/home
# Change /tmp and /var/tmp permissions:
chmod 1777 /mnt/var/tmp
# Configure the Boot Environment:
zpool set bootfs=zroot/ROOT/default zroot
# Instruct FreeBSD to mount ZFS pools during system initialization:
printf 'zfs_enable="YES"' >> /tmp/bsdinstall_etc/rc.conf
# Add an fstab entry to use a GELI-encrypted swap partition:
printf "/dev/gpt/swap0.eli\tnone\tswap\tsw\t0\t0\n" >> /tmp/bsdinstall_etc/fstab
# Add an fstab entry to use tmpfs for /tmp:
printf "tmpfs\t/tmp\ttmpfs\trw,mode=1777\t0\t0\n" >> /tmp/bsdinstall_etc/fstab
# Mount the existing EFI partition of your disk:
mount -t msdosfs /dev/ada0p1 /media
# Create FreeBSD boot directory in the EFI partition:
mkdir -p /media/efi/freebsd
# Copy FreeBSD loader to the previously created directory:
cp /boot/loader.efi /media/efi/freebsd/loader.efi
# Now add a UEFI boot entry:
efibootmgr --create --activate --label "FreeBSD" --loader "/media/efi/freebsd/loader.efi"
# Unmount EFI partition:
umount /media
# Exit Shell Partitioning mode, so bsdinstall can continue and complete the installation:
exit
After finishing the installation, don't forget to add a boot entry for FreeBSD in GRUB or rEFInd.
Here I share some sample entries to guide you a bit. Remember to modify them to reflect your own reality:
# For GRUB:
Code:
menuentry "FreeBSD" {
insmod part_gpt
insmod fat
set root=(hd0,gpt1)
chainloader /efi/freebsd/loader.efi
}
# For rEFInd, add something like this at the end of refind.conf:
Code:
# FreeBSD
menuentry "FreeBSD" {
loader /efi/freebsd/loader.efi
icon /efi/refind/icons/os_freebsd.png
}
That's all. Hope you find it useful!
Sources:
https://www.freebsd.org/doc/handbook/bsdinstall-partitioning.html
https://wiki.freebsd.org/RootOnZFS/GPTZFSBoot
http://kev009.com/wp/2016/07/freebsd-uefi-root-on-zfs-and-windows-dual-boot/
https://github.com/freebsd/freebsd-src/blob/releng/13.0/usr.sbin/bsdinstall/scripts/zfsboot
https://github.com/freebsd/freebsd-src/blob/releng/13.0/usr.sbin/bsdinstall/scripts/bootconfig
EDIT 1:
-Added some sources.
EDIT 2:
-Reworded the title for better clarity.
-Added a note about FreeBSD's efi loader name used in this tutorial.
-Removed /tmp from ZFS datasets, to use a tmpfs /tmp instead. This way it provides better performance and doesn't cause troubles with some programs, like Firefox on Wayland, for instance.
UPDATE (2021/02/12):
-Fixed some little issues.
-Added useful efibootmgr command.
-Updated FreeBSD efi boot loader name and location to match new FreeBSD 13.0 defaults.
-Added more sources.
Last edited: