Coming /home
FreeBSD 14.0-RELEASE annoucement is immiment. Due to faster (re)boot and related improvements by Colin Percival, this version made headlines in tech media even before it got released, which got me interested in trying it out on some of our machines. I installed the first beta on one of our servers and shortly afterward reported an upgrade bug, which got fixed during the beta cycle and was shipped as an errata in 13.2-RELEASE-p4 and 12.4-RELEASE-p6.
I was following the subsequent pre-releases with great interest as well. The final FreeBSD 14.0-RELEASE brings Clang/LLVM 16.0 (which we use in scientific software development and course teaching), OpenSSL 3.0, OpenZFS 2.2, Lua configuration support in the boot loader, upgraded WireGuard in the kernel wg driver, and plenty of other changes that are relevant to our usage. I found it well worth the time it took to go through these changes and learn what to expect from the release.
FreeBSD 14 is moving /usr/home
to /home
As Skylar Grey would put it in her song Coming Home, Pt. II (typewriter styling and slashes added by the author of the blog post):
See you can doubt, and you can hate
But I know, no matter what it takesI'm coming
/home
I'm coming/home
Tell theworld
I'm coming/home
On a less artistic and a more technical note, in the Userland Application Changes section of the release notes for FreeBSD 14.0-RELEASE, a block of text caught my eye (typewriter styling added in the quoted text):
The pw(8) and bsdinstall(8) programs now create home directories for users in
/home
by default rather than/usr/home
. The default symbolic link for/home
, referencing/usr/home
, is no longer created. bbb2d2ce4220
This is further explained in the commit message of bbb2d2ce4220 (typewriter styling added):
When adding a user,
pw
will create the path to the home directory if needed. However, if creating a path with just one component, i.e. that appears to be in the root directory,pw
would create the directory in/usr
, and create a symlink from the root directory. Most commonly, this meant that the default of/home/$user
would turn into/usr/home/$user
. This was added in a self-described kludge 26 years ago. It made (some) sense when root was generally a small partition, with most of the space in/usr
. However, the default is now one large partition./home
really doesn't belong under/usr
, and anyone who wants to use/usr/home
can specify it explicitly. Remove the kludge to move/home
under/usr
and create the symlink, and just use the specified path. Note that this operation was done only on the first invocation for a path, and this happened most commonly when adding a user during the install.
Interesting bit of history and a cool anecdote to remember for operating systems and sysadmin courses. As far as I know, (GNU/)Linux had home
directory set up like this since the beginning, so this change is also helpful to new users who these days mostly come with prior experience with Unix-like operating systems obtained only on (GNU/)Linux.
"Upgrading" /usr/home
to /home
on an existing installation
I started to wonder if this change was also made while performing an upgrade
via freebsd-update(8), but it expectedly turned out that it was not.
% ls -ld /home
lrwxr-xr-x 1 root wheel 11 7 tra 2023 /home -> usr/home
Since I made sure to keep the pre-upgrade ZFS snapshot (that's fairly easy when you normally run zfs-destroy(8) on old snapshots only when disk usage becomes a problem), there was little worry that the machine would be put in a nonrecoverable state. Let's see if /usr/home
can simply be moved to /home
.
% doas zfs rename zroot/usr/home zroot/home
Password:
cannot unmount '/usr/home': pool or dataset is busy
Of course not. That was a bit too optimistic, wasn't it? Even for ZFS.
Preparing for the move
It is impossible to perform this operation without unmounting the filesystem first, and unmounting can't be done on a busy filesystem. A busy filesystem in this case means a busy home directory, and a busy home directory in general means user processes running, be it session processes or per-user daemons. As a consequence, all regular users have to be logged out and all of their processes should be killed before the move can happen. Logging out is easy, killing session processes too, so let's check which daemons are running for my user.
% grep vedran /etc/rc.conf
syncthing_home="/home/vedran/.config/syncthing"
syncthing_user="vedran"
syncthing_group="vedran"
No wonder Syncthing is running, it is a very simple and useful file synchronization tool. Let's make sure it is stopped so it does not try to access its configuration directory via the /home -> /usr/home
symlink while we are moving the home directory.
% doas service syncthing stop
Password:
Stopping syncthing.
Waiting for PIDS: 34480.
One can now log out as a regular user and log in as root
on the display and the keyboard attached to the system, if any. As this particular machine is headless and without an input device, I opted to log in as root
via SSH. To do this, one has to replace the line in the OpenSSH daemon configuration file /etc/ssh/sshd_config
. Instead of
#PermitRootLogin no
there should be
PermitRootLogin yes
Of course, after changing the configuration, one should also activate the changes using the service(8) command:
% doas service sshd reload
Password:
Performing sanity check on sshd configuration.
Moving the home directory
It looks like we can finally log in as root
and perform the move. Let's first get the existing symlink out of the way.
# rm /home
ZFS is smart enough to unmount and mount on filesystem rename so running just zfs-rename(8) should do the whole job for us.
# zfs rename zroot/usr/home zroot/home
That went with issues, good! Let's use zfs-get(8) to see what we got.
# zfs get mountpoint zroot/home
NAME PROPERTY VALUE SOURCE
zroot/home mountpoint /zroot/home inherited from zroot
# ls /zroot
home
Honestly, /zroot
is not exactly the place where we want the home
directory to be. Let's fix that using zfs-set(8).
# zfs set mountpoint=/home zroot/home
# zfs get mountpoint zroot/home
NAME PROPERTY VALUE SOURCE
zroot/home mountpoint /home local
# ls /zroot
It looks like that worked. Is the home directory finally where it should be?
# ls -ld /home
drwxr-xr-x 3 root wheel 3 15 kol 00:25 /home
The home directory is indeed in its proper place, great!
Tip
When my user was created during installation, pw(8) set its home directory to /home/vedran
, as can be easily seen from the relevant part of the /etc/passwd
file:
# grep vedran /etc/passwd
vedran:*:1001:1001:Vedran Miletic:/home/vedran:/bin/tcsh
Some software might choose to use the /usr/home/vedran
path to access the user's home directory regardless of this setting. Of course, the configuration of such software should be updated with the correct path. However, until this configuration is updated, it could be useful to have a "reverse" symlink:
# ln -s /home /usr/home
Cleaning up after the move
So, the move is done, but we still have to undo some of the preparatory work. Let's not forget to change that line in the OpenSSH daemon configuration file /etc/ssh/sshd_config
back to
#PermitRootLogin no
and reload the service
# service sshd reload
Of course, it also would be useful to get Syncthing running again.
# service syncthing start
And that's it! That's what I like about FreeBSD (and ZFS), there is absolutely no need to reinstall the operating system just to get all the latest and greatest directory hierarchy conventions from 14.0-RELEASE applied. To the contrary, the required changes can be done fairly easily in an existing installation that was upgraded from 13.2-RELEASE or 12.4-RELEASE.