Web Browser in FreeBSD Jail: Librewolf
1177 words, 6 minutes
While discovering FreeBSD Jails, I wrote on how to run a web browser inside a FreeBSD jail . Time has passed and a couple of testing later, I ended up changing a bit the way I use my Web Browser jails.
Things I’ve changed:
- FreeBSD is now 14.2.
I don’t think this really changes anything. - ZFS dataset mimics my OmniOS installation to deal with memory muscle.
- Jails don’t have a dedicated IP address.
There is no need for pf translation anymore. - Jail are installed using
bsdinstall
.
This mainly automates to regular user creation. - I’m using includes and global values in jail.conf / jail.conf.d.
This limits the number of duplicated configuration stuff.
Get ready for jails
To enable jails at boot time, run:
$ doas sysrc jail_enable="YES"
$ doas sysrc jail_parallel_start="YES"
Create a ZFS dataset to host Jail files:
$ doas zfs create -o compress=lz4 -o atime=off \
-o mountpoint=/jails zroot/jails
Install the FreeBSD Jail
The installation is done using the network. It basically just installs the files in the configured storage target.
$ doas bsdinstall jail /jails/librewolf
Note that during installation, an unprivileged user can be created. I gave it the same UID as the one I daily use on the host. That prevents issues with files permissions. But if you’re OK with dealing with permissions during file access, using a different UID could be a nice security add-on.
Initial Jail configuration
The jail.conf
contains common directives. The jail.conf.d
directory
contains specific directives for each jails.
# cat > /etc/jail.conf
path = "/jails/${name}";
exec.clean;
# Standard recipe
exec.start += "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown jail";
exec.consolelog = "/var/log/jail_${name}_console.log";
mount.devfs; # mount devfs
.include "/etc/jail.conf.d/*.conf";
^D
# cat > /etc/jail.conf.d/librewolf.conf
librewolf {
host = inherit;
ip4 = inherit;
devfs_ruleset = "80";
}
^D
# cat >> /etc/devfs.rules
[devfsrules_desktop_jail=80]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add path 'mixer*' unhide
add path 'dsp*' unhide
^D
$ doas service jail start librewolf
Install Librewolf in the Jail
I’m using Librewolf as a binary package.
My host is using X11 and so does the Jail; things may vary if you’re using Wayland. I don’t know anything about Wayland so you’re on your own on this. Sorry :-)
To get a decent rendering look, you may install standard fonts.
To prevent messing up with the X11 (and D-Bus etc) session, I have the Jail keep temporary files untouched on Jail restart.
$ doas jexec librewolf sysrc clear_tmp_enable="NO"
$ doas jexec librewolf sysrc clear_tmp_X="NO"
$ doas pkg -j librewolf install \
librewolf twemoji-color-font-ttf webfonts \
xorg mesa-libs mesa-dri
$ doas jexec librewolf pw groupmod video -m joel
Tuning the Jail
To enable GPU rendering, the Jail needs access to the proper devices. This is configured in the DEVFS control configuration file.
$ doas vi /etc/devfs.rules
[devfsrules_desktop_jail=80]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add path 'mixer*' unhide
add path 'dsp*' unhide
add path dri unhide
add path dri/* unhide
add path drm unhide
add path drm/* unhide
add path pci unhide
$ doas service devfs restart
To have D-Bus work properly, Librewolf rendered in a coherent way with the rest of the host desktop environment and gain access to your desired shared folders and files, the Jail configuration has to be amended. Files and directories from the host are mounted to the Jail workspace. Not all resources need write access. My Librewolf configuration looks like this:
$ doas vi /etc/jail.conf.d/librewolf.conf
librewolf {
host = inherit;
ip4 = inherit;
devfs_ruleset = "80";
mount += "/home/joel/.cache/mesa_shader_cache $path/home/joel/.cache/mesa_shader_cache nullfs rw 0 0";
mount += "/home/joel/.config/fontconfig $path/home/joel/.config/fontconfig nullfs ro 0 0";
mount += "/home/joel/.config/gtk-3.0 $path/home/joel/.config/gtk-3.0 nullfs ro 0 0";
mount += "/home/joel/.librewolf $path/home/joel/.librewolf nullfs rw 0 0";
mount += "/home/joel/.local/share/fonts $path/home/joel/.local/share/fonts nullfs ro 0 0";
mount += "/home/joel/.local/share/icons $path/home/joel/.local/share/icons nullfs ro 0 0";
mount += "/home/joel/.local/share/themes $path/home/joel/.local/share/themes nullfs ro 0 0";
mount += "/home/joel/.login_conf $path/home/joel/.login_conf nullfs ro 0 0";
mount += "/home/joel/.Xauthority $path/home/joel/.Xauthority nullfs ro 0 0";
mount += "/home/joel/Téléchargements $path/home/joel/Téléchargements nullfs rw 0 0";
mount += "/home/joel/Public $path/home/joel/Public nullfs ro 0 0";
mount += "/tmp $path/tmp nullfs rw 0 0";
mount += "/var/run/dbus $path/var/run/dbus nullfs rw 0 0";
mount += "/var/run/user $path/var/run/user nullfs rw 0 0";
}
Resources need to exist in the Jail workspace before being made available.
$ mkdir -p \
/jails/librewolf/home/joel/.cache/mesa_shader_cache \
/jails/librewolf/home/joel/.config/fontconfig \
/jails/librewolf/home/joel/.config/gtk-3.0 \
/jails/librewolf/home/joel/.librewolf \
/jails/librewolf/home/joel/.local/share/fonts \
/jails/librewolf/home/joel/.local/share/icons \
/jails/librewolf/home/joel/.local/share/themes
$ touch \
/jails/librewolf/home/joel/.login_conf \
/jails/librewolf/home/joel/.Xauthority
$ mkdir -p \
/jails/librewolf/home/joel/Téléchargements \
/jails/librewolf/home/joel/Public
$ doas mkdir -p /jails/librewolf/var/run/user
$ doas service jail restart librewolf
Librewolf can now be started using:
$ doas jexec -u joel librewolf librewolf
The KeePassXC browser extension only fully works if Firefox is
enabled in KeePassXC and a ~/.mozilla/native-messaging-hosts/
directory exists. For it to work with Librewolf and other Firefox
clones
,
a configuration file has to be created:
$ doas pkg -j librewolf install keepassxc
$ doas jexec -u joel librewolf sh
$ mkdir -p ~/.librewolf/native-messaging-hosts
$ cat > ~/.librewolf/native-messaging-hosts/org.keepassxc.keepassxc_browser.json
{
"allowed_extensions": [ "keepassxc-browser@keepassxc.org" ],
"description": "KeePassXC integration with native messaging support",
"name": "org.keepassxc.keepassxc_browser",
"path": "/usr/local/bin/keepassxc-proxy",
"type": "stdio"
}
Using Librewolf
The jexec
command must be run as root. One simple way to use Librewolf
without having to enter the root password is to create a script that can
be run by the unprivileged user. Another script will use doas
to call
jexec
and run Librewolf.
$ doas vi /usr/local/bin/librewolf
#!/bin/sh
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
_u="$(whoami)"
_b="$(basename $0)"
exec doas /usr/local/bin/jbrowsers "$_u" "$_b" "$_b" "$@"
$ doas chmod 0755 /usr/local/bin/librewolf
$ doas vi /usr/local/bin/jbrowsers
#!/bin/sh
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
if [ $# -lt 3 ]; then
echo "usage: $0 user jail browser [extra arguments]"
exit 1
fi
if [ "$2" != "librewolf" ] || [ "$3" != "librewolf" ]; then
echo "I'm sorry Dave, I can't do that."
exit 2
fi
exec jexec -U "$@"
$ doas chmod 0755 /usr/local/bin/jbrowsers
$ doas vi /usr/local/bin/doas.conf
(...)
permit keepenv nopass joel as root cmd /usr/local/bin/jbrowsers
Then, to have a Librewolf icon in your Desktop Environment menu, create
a .desktop
file:
$ doas vi /usr/local/share/applications/librewolf.desktop
[Desktop Entry]
Version=1.0
Name=Librewolf Web Browser
Name[fr]=Navigateur Web Librewolf
Comment=Browse the World Wide Web
Comment[fr]=Naviguer sur le Web
GenericName=Web Browser
GenericName[fr]=Navigateur Web
Keywords=Internet;WWW;Browser;Web;Explorer
Keywords[fr]=Internet;WWW;Browser;Web;Explorer;Fureteur;Surfer;Navigateur
Exec=/usr/local/bin/librewolf %U
Terminal=false
Type=Application
Icon=librewolf
Categories=GNOME;GTK;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall;
StartupNotify=true
Actions=NewWindow;NewPrivateWindow;
[Desktop Action NewWindow]
Name=Open a New Window
Name[fr]=Ouvrir une nouvelle fenêtre
Exec=/usr/local/bin/librewolf -new-window
[Desktop Action NewPrivateWindow]
Name=Open a New Private Window
Name[fr]=Ouvrir une nouvelle fenêtre de navigation privée
Exec=/usr/local/bin/librewolf -private-window
The Librewolf icon should now be in the relevant category of you DE
menu.
It is also possible to launch it from a terminal using: gtk-launch librewolf
.
The web browser now has limited files access. And by using Librewolf, you have to comply to:
You give Mozilla all rights necessary to operate Firefox, including processing data as we describe in the Firefox Privacy Notice, as well as acting on your behalf to help you navigate the internet. When you upload or input information through Firefox, you hereby grant us a nonexclusive, royalty-free, worldwide license to use that information to help you navigate, experience, and interact with online content as you indicate with your use of Firefox.
Have fun and browse safe!