This document describes the procedure I follow to install FreeBSD on a system. I prefer to install it manually - without using the FreeBSD installation program - as this allows greater control over how the final system ends up.

I carry out the installation from the shell environment of a FreeBSD memstick.

I install my systems using ZFS as the filesystem, organising my datasets similarly to Sun’s original layout when ZFS first appeared in Solaris 10:

NAME                      MOUNTPOINT
pool0                     /pool0
pool0/ROOT                legacy
pool0/ROOT/FreeBSD        /
pool0/home                /home
pool0/home/user1          /home/user1
pool0/usr                 /usr
pool0/usr/local           /usr/local
pool0/usr/ports           /usr/ports
pool0/usr/ports/distfiles /usr/ports/distfiles

In the above structure, pool0/home and pool0/usr are used as containers for subordinate datasets only. They are not mountable and do not contain any files themselves. Any files placed in /home or /usr will actually be stored in the pool0/ROOT/FreeBSD dataset.

Installing the minimal system

Booting the installation environment

Download the FreeBSD-11.0-RELEASE-amd64-memstick.img and write it to a USB stick using dd or equivalent.

Boot the system from the USB stick.

Once the bsdinstall program has started, select shell.

Partitioning disks

The following examples assume the installation is onto a SATA disk named ada0.

GPT scheme on BIOS systems

Create a GPT scheme on ada0.

# gpart create -s gpt ada0

Add freebsd-boot, freebsd-swap and freebsd-zfs partitions. Many OS’s now start their first partition at the 1MiB offset as a way of ensuring filesystem alignment to any underlying block sizes on the storage device, such as pages on flash storage or 4KiB sectors on Advanced Format disks. I do a similar thing by placing a 512KiB freebsd-boot partition at the 512KiB offset, causing the next partition to start at exactly 1MiB.

# gpart add -t freebsd-boot -b 512k -s 512k ada0
# gpart add -t freebsd-swap -s 4G ada0
# gpart add -t freebsd-zfs ada0

Write the protective MBR and bootcode:

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0

GPT scheme on UEFI systems

Create the GPT scheme on ada0:

# gpart create -s gpt ada0

Create efi, freebsd-swap and freebsd-zfs partitions, starting from an offset of 1MiB.

# gpart add -t efi -b 1M -s 128M ada0
# gpart add -t freebsd-swap -s 4G ada0
# gpart add -t freebsd-zfs ada0

Create a FAT32 filesystem on the EFI partition and copy loader to default location:

# newfs_msdos /dev/ada0p1
# mount -t msdosfs /dev/ada0p1 /mnt
# mkdir -p /mnt/EFI/BOOT
# cp /boot/boot1.efi /mnt/EFI/BOOT/BOOTX64.EFI
# umount /mnt

Create zpool and datasets

Create the pool on the freebsd-zfs partition (ada0p3) with a temporary root mountpoint of /mnt, to avoid newly created datasets from being mounted over the live memstick filesystems.

# zpool create -R /mnt pool0 ada0p3

Create initial ZFS datasets, and mount the one which will contain the new installation.

# zfs create -o mountpoint=legacy pool0/ROOT
# zfs create -o mountpoint=/ -o canmount=noauto pool0/ROOT/FreeBSD
# zfs mount pool0/ROOT/FreeBSD

Extract FreeBSD base tree and kernel

# cd /mnt
# tar xpf /usr/freebsd-dist/base.txz
# tar xpf /usr/freebsd-dist/kernel.txz

Make new installation bootable

Load the ZFS kernel module at boot, and designate the dataset to boot FreeBSD from

# echo 'zfs_load="YES"' > /mnt/boot/loader.conf
# zpool set bootfs=pool0/ROOT/FreeBSD pool0

Reboot into new installation

# zpool export pool0
# shutdown -r now

Post-installation configuration

At this point, there is a minimal unconfigured FreeBSD system installed. The following remains to be done:

  • Set root’s password

# passwd
  • Set the timezone

# tzsetup
  • Update /etc/rc.conf to configure hostname, networking and other things:

# vi /etc/rc.conf
  • Update /etc/resolv.conf

# vi /etc/resolv.conf:
domain  home
  • Update /etc/fstab to mount additional filesystems:

# vi /etc/fstab
tmpfs   /tmp    tmpfs   rw,mode=01777   0       0
  • Create additional ZFS datasets for local data and home directories:

# zfs create -o mountpoint=/home canmount=off pool0/home
# zfs create -o mountpoint=/usr canmount=off pool0/usr
# zfs create pool0/usr/local
# zfs create pool0/usr/ports
# zfs create pool0/usr/ports/distfiles
  • Create non-root user:

# zfs create pool0/home/user1
# adduser