This is an old revision of the document!


Jailing GUI Applications

This is a short tutorial on how to run GUI applications jailed. This is done primarily for Firefox but the same principle can be applied for any other application.

We start by creating a basic jail that depends on your favorite jail abstraction tool. But to unhide all the abstracted details that those tools often do, we're going to do it all manually, and based on ZFS, so feel free to adapt the tasks for whatever jail management tool you're using.

To begin with, we'll dedicate zroot/jails as the base dataset for all jail deployments, and create a basejail in zroot/jails/basejail. The basejail method allows us to simply zfs clone it into target jail dataset, which is the most efficient way to share the base jail among other jails. Updating them all then requires updating the basejail and re-creating jail roots. Here's how.

# zfs create -o compress=lz4 -o atime=off zroot/jails
# zfs create zroot/jails/basejail
# bsdinstall jail /zroot/jails/basejail

Here we used the bsdinstall method for convenience. Otherwise downloading and unpacking base.txz and configuring it should suffice. At this point we'd configure the basejail for pkg, like the location of your Poudriere repo if you have it. No other configuration is required for the base as the jails will basically run a single process.

So we snapshot it and create our Firefox jail filesystem:

# zfs snapshot zroot/jails/basejail@latest
# zfs create zroot/jails/firefox
# zfs clone zroot/jails/basejail@latest zroot/jails/firefox/root
# zfs create zroot/jails/firefox/var
# zfs create zroot/jails/firefox/tmp
# zfs create zroot/jails/firefox/home
# rsync -a /zroot/jails/firefox/root/var/ /zroot/jails/firefox/var/
# zfs set mountpoint=/zroot/jails/firefox/root/var zroot/jails/firefox/var
# zfs set mountpoint=/zroot/jails/firefox/root/tmp zroot/jails/firefox/tmp
# zfs set mountpoint=/zroot/jails/firefox/root/usr/home zroot/jails/firefox/home

For extra security we want our jail to run with minimum require privilege, so we set some properties on these datasets, which should make obvious why we separated them like this. Of course, these rules are not applicable to every application, as some, unfortunately would like to write or execute to/from paths they shouldn't. For firefox, these suffice, tho'.

# zfs set setuid=off exec=off zroot/jails/firefox/var
# zfs set setuid=off exec=off zroot/jails/firefox/tmp
# zfs set setuid=off exec=off zroot/jails/firefox/home

At this point it's worth observing that when base is to be update, all we need to do is update the basejail and create a new snapshot for cloning. With that, and separate var/home/tmp dirs, it's trivial to update the jails' bases, just zfs destroy root dataset and re-clone it from basejail. This will require unmounting and re-mounting the other datasets, but it can all be easily scripted for simple maintenance.

Next, with the filesystem in place, we install the packages. xauth and firefox are the base minimum, while liberation-fonts-ttf is recommended addition for some nice fonts in Firefox.

pkg -c /zroot/jails/firefox/root install firefox xauth liberation-fonts-ttf

Next, we need to bootstrap launching firefox. The idea here is that all it takes to “launch firefox” is to launch its jail, and when the browser is closed, the jail should shut down too. This is achieved relatively simply. To make bootstrapping easier, we'll now launch the jail and run the commands in it. But first, we need to set up the jail.conf definition of it:

# /etc/jail.conf

allow.nomount;
exec.clean;
mount.devfs;
host.hostname = "$name.your-host-name.lan";
path = "/zroot/jails/${name}/root";
#securelevel = 3;

firefox {
    ip4.addr = "10.0.0.2";
    #exec.start = "/bin/sh /home/firefox/run-firefox";
    #exec.jail_user = "firefox";
    persist;
    devfs_ruleset = 5;
}

At this point, we comment out the exec. directives, and uncomment the persist directive because we want to get inside the jail with no processes running, to bootstrap it. But before we do that, there are two more undefined items here, the devfs ruleset and jail's ip address. So, let's handle those first.

The devfs ruleset is required to allow audio devices in the jail, so the applications can play audio. We copy the default ruleset for jails (ruleset number 4) from /etc/defaults/devfs.rules and add audio devices, into /etc/devfs.rules:

[devfsrules_desktop_jail=5]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add path 'mixer*' unhide
add path 'dsp*' unhide

Basically we just added mixer* and dsp* devices in addition to the default jails ruleset.

  • jailingguiapplications.1501851984.txt.gz
  • Last modified: 2017/08/04 13:06
  • by VladimirKrstulja