Published by bp99 on Sat Jul 6 20:44:35 2019


Setting up my Raspberry Pi home server

This post covers only how I set up the base system. I didn't document setting up the various hosted services.

Installing FreeBSD 12.0-RELEASE on the Pi

This is fortunately rather straightforward. Just download the disk image from FreeBSD's download page; do not forget to also fetch the checksums provided for the image.

After the download, make sure you have the uncorrupted file. On OpenBSD, this looks like


I did this for both the SHA256 and the SHA512 sums. If the output isn't OK, you ought to re-download the image.

Uncompress the file and burn it onto the SD card:

# unxz IMAGE_ARCHIVE && dd if=IMAGE of=/dev/rsdN bs=1m

(rsdN is the raw device descriptor file for my SD card)

Obviously, make very sure that you are writing to the right disk. You can corrupt your data if you write to the wrong disk!

Thankfully FreeBSD runs SSH by default, so I could just put the SD card in, attach the power cable and in a few minutes I could connect to the Pi via SSH.

I found the IP address using nmap(1):

beetroot# nmap -sn
Starting Nmap 7.70 ( ) at 2019-07-06 14:19 CEST
Nmap scan report for
Host is up (0.11s latency).
MAC Address: AA:BB:CC:DD:EE:FF (Raspberry Pi Foundation)
beetroot# ssh freebsd@
Password for freebsd@generic:

The default username/password pair is freebsd/freebsd.

Basic setup

After a quick su - (the default root password is root), I set up a few initial networking things.

Static IP and hostname

For rather obvious reasons, I want my Pi to have the same local IP always. To do this, you need to edit the file /etc/rc.conf.

While we are at it, we also change the hostname="generic" line to something cooler. Or something as unoriginal as hostname="raspberry".

The static address is set by changing the value of ifconfig_DEFAULT. However, I don't like using DEFAULT and I changed the key to use the network interface name of the Pi instead (ue0 for me; this can be found from ifconfig(8)). My entry is like this:


I think you also need to add this line:


Here we also see that sendmail(8) is disabled by default (which is what I want) and sshd(8) is enabled (thankfully).

Then I restart networking by issuing

# /etc/netstart

The SSH connection is of course lost at this point, so after closing it with the escape code <c-j>~., I open another using the right IP.

An additional networking step is to add a DNS server to /etc/resolv.conf. I use Cloudflare's and

Root password and my unprivileged user

I quickly change to root password using

# passwd

and also add a new user for myself using

# adduser

The setup is nice and straightforward. Don't forget to add yourself to the wheel group—that is if you want to utilize it of course. Then you can just relog using SSH into your own user.

SSH hardening

At this point, I only want to access SSH from my local network. Also, I want to disable password-based authentication and use only public-key based auth: this is much more secure. It protects me against brute-force login attempts. These are rather trivial changes to /etc/ssh/sshd_config.

Be careful not to disable password-based authentication before actually adding your public key to the authorized_keys file on the remote. I have given myself a hard time several times due to forgetting this…

Optional: RCS

This is a good time to set up some version control such as RCS (that I fondly use on OpenBSD) for retaining older versions of system config files. However, FreeBSD does not have RCS by default: I have to install it from packages. To do this:

# pkg update && pkg install -y rcs

Then I create a subdirectory named RCS in each directory where I edit the configuration, check in the file using ci(1)—only if it has not been checked in before—, check out the file using co(1) with the -l (lock) flag, edit the contents and then check it back in using ci -u (unlock). This is rather tedious, so I have a shell script for this which you can find in my scripts repo.

Thus I can simply edit config files using

# rcsedit FILE

and I still have the convenient features of RCS. I also get an overview of my modifications before I commit the changes.


OpenBSD's pf firewall is absolutely fantastic. I won't go into details here; I just create a minimal /etc/pf.conf at first, such as this:

ext_if = "ue0"
local_network = ""

ssh_ports = "1234"

pass in on $ext_if proto tcp from $local_network to port $ssh_ports

pass out on $ext_if proto tcp to port { http https }
pass out on $ext_if proto udp to port { domain }

pass out on $ext_if proto icmp icmp-type echoreq

Then I start and enable pf at startup using

# service pf enable && service pf start

Again, be careful not to lock yourself out. It is a good idea to issue something like sleep 60 && ptfcl -d before starting the firewall: this way, even if you mess up, the firewall will be turned off after 60 seconds.

Improving the environment

Here are a few programs I like to have:

I also like to wipe my initial home directory from all the default dotfiles and change/remove the ones that are added to each new user's home directory by default in /usr/share/skel.

Running top(1) at this stage reveals a lot of getty(8)‘s running for no damn reason. These can be disabled in /etc/ttys.


I always plan to set up a backup solution and never do in the end. Last time this happened I lost all my precious setup… So this time, listen to me and SET UP PERIODIC BACKUP NOW. That is

---> R I G H T    N O W <---

And do not forget to update your configuration every now and then to include new things that might need to be backed up.

I use duplicity for this and back up to a BackBlaze II bucket or whatever it's called.