Tips for IOCAGE jail installation scripts

Not open for further replies.


Nov 1, 2016
Here is a example script that creates a simple "testjail" with iocage. This script may give you some practical hints, especially if you are writing installation scripts for iocage jails.

For example, you can execute commands in the jail with

iocage exec <jail> <command>

There is also another way to execute scripted commands in the jail. Take a look at the section that starts with cat << EOF | ...
This technique let's you do fairly advanced iocage jail installations easily directly from your script.

The way I find the JAILROOT in the script, that is, the path to the root directory of the jail in the FreeNAS directory tree, is not the most elegant way. I would like to know some simpler way to figure out the JAILROOT directory.

It is quite easy to split your script file into multiple sections, which you can output anyway you want. This script creates a rc.d script in the jail from some lines at the end of the script file.


if [ "$(id -u)" != "$(id -u root)" ]; then
	echo "You must be root to run this script."
	exit 1

# Let's create a testjail
iocage create -n testjail -r "11.1-RELEASE"

# Let's execute commands in the testjail.
# Everything between the cat-line and the line starting
# with EOF will be executed inside the testjail
cat << EOF | iocage console testjail
	echo "Hello from"

# The root directory of the testjail can be found at
JAILROOT="$(iocage get jail_zfs_dataset testjail 2>/dev/null | sed -rn 's/(.*)\/data$/\1\/root/p')"
[ -n "$JAILROOT" ] && JAILROOT="/mnt/$JAILROOT" 

# Now JAILROOT is the root directory of the jail
# or it is "" if the root directory could not be determined.

if [ -d "$JAILROOT" ]; then
	# Let's create a dummy rc.d script in the testjail.
	# The contents of the rc.d file is located near 
	# the end of THIS file after the divider line.
	sed '1,/--divider--$/d' "$0" > "$JAILROOT/etc/rc.d/dummy"
	chmod 555 "$JAILROOT/etc/rc.d/dummy"
	# or alternatively:
	# iocage exec testjail "chmod 555 /etc/rc.d/dummy"

	# Let's start the dummy service in the testjail
	iocage exec testjail "service dummy start"

# This script must end before the divider line.
exit 0

# After the divider line are the contents of a dummy rc.d script

. /etc/rc.subr


dummy_start() {
	echo "Hello, I'm a dummy service"

load_rc_config $name
run_rc_command "$1"

The testjail is now created. You can access the command line of the testjail with
iocage console testjail

and you can delete the testjail with
iocage destroy testjail

As in a script file "$0" refers to the script file itself, the following one-liners give you any section you want from your script file. Just make sure that your divider lines are unique, and no other lines end in the dividers. Not even comment lines! Also, your script MUST exit before the divider lines begin.


# Lines before div1 i.e. the script itself
sed '/--div1--$/,$d' "$0"

# Lines between div1 and div2
awk '/--div1--$/{flag=1;next}/--div2--$/{flag=0}flag' "$0"

# Lines after div2
sed '1,/--div2--$/d' "$0"

# Must exit before the divs
exit 0

These lines are
between div1 and div2

This line comes after div2,
and so does this.

I hope these examples can help you to write even better installation scripts for the iocage jails.


Feb 24, 2012
Great tips, thank you! Has anyone figured out exactly how to escape special characters with iocage exec?

For example, the following does not work, but if I run it in an iocage console, no problems:

# cat << EOF | iocage console transmission
?  sed -E -i 's|"rpc-whitelist":.*|"rpc-whitelist": "192.168.1.*,",|g' /config/transmission-home/settings.json

root@transmission:~ # sed -E 's|"rpc-whitelist":.*|"rpc-whitelist": "192.168.1.*,",|g' /config/transmission-home/settings.json


Hall of Famer
Aug 16, 2011
Has anyone figured out exactly how to escape special characters with iocage exec?
A backslash should generally do it. But why use cat << EOF in your first example?
iocage exec transmission sed -E -i 's|"rpc-whitelist":.\*|"rpc-whitelist": "192.168.1.\*,",|g' /config/transmission-home/settings.json
Not open for further replies.