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:

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!