Installing FreeBSD 14.2 on the Raspberry Pi 4 Model B ======================================================================== Table of Contents ======================================================================== Materials Needed Preparing the External Hard Drive First Boot - Change root's Password - Create Users and Groups - Change the Hostname - Configure Networking - Enable ntpd(8) - Bootstrap pkg(8) - Enable ZFS on Startup - Install FUSE and exFAT Support - Additional Security - Create a USB Key Disk for ZFS - Create a raidz ZFS Pool ======================================================================== Materials Needed ======================================================================== I used: - A Raspberry Pi 4 Model B purchased from Vilros in late 2024 - A 256GB internal SATA III SSD drive - A SABRENT external 2.5" SATA III USB enclosure (for the SSD) - An Ethernet cable - Another computer (I used a machine with Void Linux) ======================================================================== Preparing the External Hard Drive ======================================================================== Download the aarch64 Raspberry Pi (RPI) image from freebsd.org: wget https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/14.2/FreeBSD-14.2-RELEASE-arm64-aarch64-RPI.img.xz wget https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/14.2/CHECKSUM.SHA{256,512}-FreeBSD-14.2-RELEASE-arm64-aarch64-RPI Verify the downloaded image's integrity: shasum -c CHECKSUM.SHA{256,512}-FreeBSD-14.2-RELEASE-arm64-aarch64-RPI Insert your external hard drive into your other computer and run this (change the output device to your external hard drive!): unxz FreeBSD-14.2-RELEASE-arm64-aarch64-RPI.img.xz dd if=FreeBSD-14.2-RELEASE-arm64-aarch64-RPI.img of=/dev/sda bs=1M conv=sync Mount the first partition on the external hard drive (in this example, /dev/sda1): mount -o noatime /dev/sda1 /mnt Open config.txt in the mounted partition and change the "hdmi_safe=1" setting to the following. Note that "hdmi_group" should be "1" if you are connecting your Raspberry Pi to a TV and that you should probably use a different value for "hdmi_mode". Consult https://www.raspberrypi.com/documentation/computers/legacy_config_txt.html#hdmi_mode for the "hdmi_mode" value that corresponds to your screen's resolution. I picked "hdmi_mode=82" for 1920x1080 at 60Hz (1080p): ------------------------------------------------------------------------ hdmi_force_hotplug=1 hdmi_ignore_edid=0xa5000080 config_hdmi_boost=5 hdmi_group=2 hdmi_mode=82 disable_overscan=0 overscan_left=24 overscan_right=24 overscan_top=24 overscan_bottom=24 ------------------------------------------------------------------------ Disconnect your external hard drive. ======================================================================== First Boot ======================================================================== Insert the external hard drive into one of your Raspberry Pi 4's USB 2 ports, unplug the Ethernet cable from the computer, and boot it. It should load the FreeBSD kernel and give you a login prompt. ------------------------------------------------------------------------ Change root's Password ------------------------------------------------------------------------ The default users and passwords are: 1. user "freebsd" with password "freebsd" 2. user "root" with password "root" Needless to say, you should change these passwords before you insert the Ethernet cable. Use passwd(1) to do this. As the root user, change the root user's password first: passwd ------------------------------------------------------------------------ Create Users and Groups ------------------------------------------------------------------------ You probably want different users than freebsd. Get rid of the freebsd user as root thus: rmuser -yv freebsd Create new users via adduser(8). For example, if you want a user called "chuck" who belongs to the "wheel" group, run this as root: adduser -G wheel adduser(8) will prompt you for the new user's settings. If you need new supplementary groups, add them to /etc/group. For example, if you want to add the user "chuck" to a new group "farmers", add a line like this (choose an appropriate group ID instead of 123): ------------------------------------------------------------------------ farmers:*:123:chuck ------------------------------------------------------------------------ The final component of that line is a comma-separated list of users who belong to the group. See group(5) for more information. ------------------------------------------------------------------------ Change the Hostname ------------------------------------------------------------------------ Set the hostname variable in /etc/rc.conf to whatever you desire. This will take effect on the next boot; if you do not want to wait that long, run hostname(1) thus (this example sets the hostname to "yosemite"): hostname yosemite ------------------------------------------------------------------------ Configure Networking ------------------------------------------------------------------------ Correct the ::1 and 127.0.0.1 domain names in /etc/hosts. Plug your Ethernet cable in. Verify that the Raspberry Pi gets an IPv4 and IPv6 address by running ifconfig(8): ifconfig ------------------------------------------------------------------------ Enable ntpd(8) ------------------------------------------------------------------------ Enable ntpd(8) to synchronize your clock: sysrc ntpd_enable=YES ntpd_sync_on_start=YES Then start ntpd(8): service ntpd start You might have to reboot for this to take effect. ------------------------------------------------------------------------ Bootstrap pkg(8) ------------------------------------------------------------------------ Bootstrap pkg(8) thus: pkg bootstrap -y pkg update ------------------------------------------------------------------------ Enable ZFS on Startup ------------------------------------------------------------------------ To make FreeBSD mount ZFS pools and datasets on boot: sysrc zfs_enable=YES zfskeys_enable=YES Then enable the service as root: service zfs start ------------------------------------------------------------------------ Install FUSE and exFAT Support ------------------------------------------------------------------------ Install the FUSE exFAT module: pkg install exfat-utils fusefs-exfat Ensure that the kernel loads the fusefs kernel module on boot (after all disks mount -- see "kld_list" in rc.conf(5)): sysrc kld_list+=fusefs To load the kernel module immediately, run: kldload fusefs See fusefs(5) and mount_fusefs(8) for more information about using FUSE. ------------------------------------------------------------------------ Additional Security ------------------------------------------------------------------------ Uncomment (or add) this line to /etc/sysctl.conf to prevent users from seeing information about other users' processes: ------------------------------------------------------------------------ security.bsd.see_other_uids=0 ------------------------------------------------------------------------ Ensure that booting into single-user mode requires the root password by changing "secure" to "insecure" on the "console" line in /etc/ttys. ------------------------------------------------------------------------ Create a USB Key Disk for ZFS ------------------------------------------------------------------------ This explains how to create an msdosfs(5) filesystem on a USB drive for storing zfs(8) encryption keys. I prefer exFAT on USB thumb drives and SD cards because it is portable and gets around primitive FAT file size limits, but I have not figured out how to correctly list exFAT mounts in fstab(5). Therefore, this guide splits the USB drive into a small msdosfs(5) partition and an exFAT partition that takes the rest of the drive for general use. Manage disks with gpart(8). Insert your USB drive. Use "gpart list" or "gpart status" to figure out which device represents the drive. It will probably be a da(4) device. Once you determine the device (these instructions assume da0, but make sure you use the correct one), create a GPT scheme on that device: gpart create -s GPT da0 If there is already a partition table on the drive, creation might fail. In that case, destroy it first: gpart destroy da0 You might have to use the "-F" flag to force destruction. Add a single partition that will hold the msdosfs(5) (FAT) filesystem and another for an exFAT partition. The msdosfs(5) filesystem will consume 128MB and the exFAT partition will take the rest of the USB drive's free space. Change these settings to your liking: gpart add -t ms-basic-data -s 128M da0 gpart add -t ms-basic-data da0 Note: If you had used an MBR scheme instead ("gpart create -s MBR da0"), the filesystem type should be "ntfs". Note the new msdosfs(5) partition's rawuuid, which is its GPT partition's UUID. Get it from gpart(8): gpart list da0 | grep rawuuid | head -n 1 Create the msdosfs(5) filesystem on the first partition: newfs_msdos /dev/gptid/$(gpart list da0 | grep rawuuid | head -n 1 | awk '{print $2}') Create the exFAT filesystem on the second partition. Use the GPT UUID: mkexfatfs /dev/gptid/$(gpart list da0 | grep rawuuid | head -n 2 | tail -n 1 | awk '{print $2}') If you want to automatically mount the key disk on boot (or when you run "mount -a"), add a line like this to /etc/fstab (change the GPT UUID), noting that the field separators are tabs: ------------------------------------------------------------------------ /dev/gptid/12345678-1234-1111-2222-123412341234 /mnt/keys msdosfs failok,ro,noatime,emptydir,nocover,noexec,nosuid,uid=0,gid=0 0 0 ------------------------------------------------------------------------ If you have multiple key disks holding the same zfs(8) keys, you can list all of them in /etc/fstab, one per line, and mount all of them at the same directory path; then as long as one of them is plugged into your system at boot, it will get mounted. ------------------------------------------------------------------------ Create a raidz ZFS Pool ------------------------------------------------------------------------ Attach the disks you want to add to your ZFS pool. Suppose you want a raidz2 pool (stripes parity and tolerates up to two simultaneous disk failures). Suppose further you have three disks: /dev/da1, /dev/da2, and /dev/da3. If you followed the USB key disk for ZFS procedure above and mounted a USB drive's msdosfs(5) partition at /mnt/keys, create an encryption key for the ZFS pool: dd if=/dev/urandom bs=32 count=1 of=/mnt/keys/shared Then create the ZFS pool: ------------------------------------------------------------------------ zpool create -O atime=off -O checksum=skein -O compression=lz4 -O devices=off -O encryption=aes-256-gcm -O keyformat=raw -O keylocation=file:///mnt/keys/shared -O overlay=off -O setuid=off -m /mnt/shared shared raidz2 da1 da2 da3 ------------------------------------------------------------------------ The pool will mount at /mnt/shared.