jaildaemon – A fixed command-line interface for FreeBSD jails to their host system



Virtual FreeBSD jail based server environments can not easily trigger actions in the host system, most prominently restarting themselves (if they kill -1 everything, they usually stay shut down) and trigger actions like routing table updates, triggering zfs snapshots or rollbacks and configuring tun/tap-Devices (as an openvpnd would).

There are several less-than-optimal solutions for that problem: granting forced-command ssh access to jails, polling some Jail-state from within the host system or dig some proprietary socket holes through the Jail's barrier, exposing a root-shell attack vector to the outside world.

jaildaemon aims to solve the problem in a simple and straight forward way while trying to minimize the attack surface for adversaries from the Jail and the network. It is a tiny daemon running in the host system that forks a probe process with a single associated command on demand, attaches it to a single jail and (optionally) assigns it a verbose proctitle. When the Jail's root user sends a SIGHUP to this probe process, it dies with a magic exit code, signalling the daemon to execute the associated command (in host context). You can chose to have the daemon restart the probe process after the command is executed (e.g. when it triggers updating routing tables) or just wait for it to be restarted by the Jail management tool (e.g. when using /usr/local/etc/rc.d/ezjail restart shell.foo.com as a reboot helper).


You can always get the latest version of jaildaemon, use git clone git://erdgeist.org/jaildaemon or the legacy view cvs -d :pserver:anoncvs@cvs.erdgeist.org:/home/cvsroot co jaildaemon with an empty password to check it out. There is a jaildaemon tarball, but no versioning yet. You can scroll through the source at *jaildaemon* gitweb or *jaildaemon* cvsweb (deprecated). Typing make install installs the binary in your ${PREFIX}/bin (or /usr/local, if none is set) and the rc-script to ${PREFIX}/etc/rc.d/.

A tight integration with ezjail is, of course, following soon.


Start the daemon as root with jaildaemon -D, with optional parameters p and f to request the pidfile being written or to specify a different controlling command unix domain socket location (that is used by jaildaemon when run in client mode to communicate with the server, and defaults to /var/run/jaildaemon.pipe), respectively.

If you installed the package, you can just enable jaildaemon in your /etc/rc.conf, by adding jaildaemon_enable=YES. It should then start at reboot, or when you run /usr/local/etc/rc.d/jaildaemon start.

Start a new probe process in a Jail (in this example jid 23) to trigger the execution of the script:

/usr/local/bin/parse_route_config -s /usr/jails/shell.foo.com/

while identifying as 'route config update' in the jail and respawn:

jaildaemon -j 23 -c '/usr/local/bin/parse_route_config -s /usr/jails/shell.foo.com/' -t 'route config update' -r

From within the jail (ezjail-admin console shell.foo.com) trigger the command by pkill -HUP -f 'route config update'.

Start a (non-spawning) Jail reboot trigger:

jaildaemon -j 23 -c '/usr/local/etc/rc.d/ezjail restart shell.foo.com' -t REBOOT

Now, from within that Jail, reboot via pkill -HUP -f REBOOT.

Version history

  • Version 0.2:
    • Fixed a bug where jaildaemon when run from /etc/rc would ignore SIGHUP by default.
    • You can now make the probe drop into another uid, so that non-root-processes can trigger actions, as well.
    • Allow jaildaemon to accept the jailname for the -j parameter, as well.


jaildaemon was written by Dirk Engling with lots of help from sg and is considered beer ware.