Back to main page

The Quick-N-Dirty Guide to ezjail in FreeBSD

We already have a QND guide to using jails in FreeBSD. The ezjail program's scripts make updating a jail simpler, as well as making it easier to maintain multiple jails. Although this guide will only cover installing a single jail, simply repeat the steps for new jails. Note that both this and the jail page are only for FreeBSD.

The program is installed from ports. As it consists of a few shell scripts, installation is quite quick.
cd /usr/ports/sysutils/ezjail; make install clean

Configuring ezjail

As updating (or installing) ezjail can involve doing the time consuming buildworld, I usually update the host system first. Hopefully, you are familiar with updating a FreeBSD system. If not, see my page on updating a FreeBSD system. Once this is done, you can create your first jail.

As the man page says, beginners sometimes get confused here. The command is not to create, it is to update. We will assume that you have recently updated the host system. You start with the command
ezjail-admin update -i

The -i flag means that you are installing the jail's world, not building it first. You will now have a directory /usr/jails with three subdirectories, basejail, flavours and newjail. The basejail is how ezjail saves space, putting many things in there so that each new jail doesen't need /bin /boot /sbin and all the rest. Flavours are something that I haven't used and the newjail is a template for any jails created. Note that if you haven't recently updated your host system, (and after updating your host system in the future) you will want to use ezjail-admin update with the -b flag, rather than -i. This also holds true if you do a buildworld on the host system after a long interval.

The ezjail-admin man page points out that it is considered to be a good practice to run ezjail-admin update each time you update your host system with make buildworld and make installworld.

Now that the basejail has been made, let's make our first new jail. In this case, it's going to be used as a webserver, so we'll call it apachejail.

We create a second IP address for it. If the host system is 192.168.1.230, we can make the jail 192.168.1.231. With a network card called fxp0
ifconfig fxp0 alias 192.168.1.231 netmask 0xffffffff

Assuming we will always be running this jail, a line should be added to /etc/rc.conf on the host system.
ifconfig_fxp0_alias0="inet 192.168.1.231/32"
If one uses the polling option on the main interface, it can be used here as well by adding the word polling to the end of the ifconfig line.
ifconfig_fxp0_alias0="inet 192.168.1.231/32 polling"

Now we create our new jail
ezjail-admin create apachejail 192.168.1.231

Once the jail is created, you will find a file on the host system /usr/local/etc/ezjail/apachejail. It will have much of what you would put in the host's /etc/rc.conf if you were creating a normal jail.
export jail_apachejail_hostname="apachejail"
export jail_apachejail_ip="192.168.1.231"
export jail_apachejail_rootdir="/usr/jails/apachejail"
export jail_apachejail_exec="/bin/sh /etc/rc"
export jail_apachejail_mount_enable="YES"
export jail_apachejail_devfs_enable="YES"
export jail_apachejail_devfs_ruleset="devfsrules_jail"
export jail_apachejail_procfs_enable="YES"
export jail_apachejail_fdescfs_enable="YES"

Depending upon how you're planning to set up apache, you might want to change the hostname. This will depend how the outside world will be accessing your website. Regardless of what the hostname is, when you set up apache, be sure to include the hostname in the jail's /etc/hosts file or apache won't start. This is a page about ezjail, not apache, but you should at least have, assuming you left the hostname as apachejail
127.0.0.1	apachejail

in the jail's /etc/hosts

The next step is to begin configuring the jail. Much of this is the same as a regular jail. One of the first things I do is copy the host machine's /etc/resolv.conf to the jail's /etc, so that once I'm in the jail, I can reach the outside world. On the host machine
cp /etc/resolv.conf /usr/jails/apachejail/etc/

Enter the jail the same way you would a normal FreeBSD jail. At this point, you can use anything for the hostname, however, what you type will become the jail's temporary hostname. You will have to use an FQDN, fully qualified name, so you can simply stick example.com on the end. If you already have a domain name that you're planning to use, however, use that. First, start or restart ezjail. If you're going to be running ezjail each time you boot, first enable it in /etc/rc.conf. Add the line
ezjail_enable="YES"

Now, start the jail.
/usr/local/etc/rc.d/ezjail.sh start

That will only work if you've already added ezjail_enable="YES" to /etc/rc.conf. If you haven't yet added that line use forcestart instead.
/usr/local/etc/rc.d/ezjail forcestart

Now, enter the jail. jail /usr/jails/apachejail apachejail.example.com 192.168.1.231 /bin/sh

This will put you in the jail as root.

At this point, I go back to the jail man page and do similar configuration to that given on our jail page. I edit the jail's /etc/rc.conf.
rpc_bind_enable="NO"
network_interfaces=""
sshd_enable="YES"
sendmail_enable="NO"
defautrouter="192.168.1.1"
early_late_divider="NETWORKING"

The early_late_divider entry can be found in man(5) rc.conf. It is sometimes necessary in a jail for a jailed apache (or other services) to start at boot.

I give root a password, different than root's password on the host machine. I also add a user, making the user a member of the wheel group so that he will be able to do most of what root does. Remember, a jail is more or less a virtual O/S operating on your host machine, so the commands are the same as they would be on a normal FreeBSD system.

In the jail, I can add packages I want with pkg_add -r. At this point, I just install sudo, bash and apache22.
pkg_add -r sudo bash apache22

(I want bash for the user, as I've gotten used to its features that are lacking in sh, specifically tab completion.)

With sudo installed, I configure the jail's /usr/local/etc/sudoers to allow the user to do what I need done. As this is going to run apache, I make sure that I've put an entry in the jail's /etc/hosts as mentioned above. We're going to call this virtual server apachejail.example.com so my jail's /etc/hosts will have the line
127.0.0.1	apachejail.example.com		apachejail

Now I can exit the jail, by simply typing exit at a command prompt.

It's time to restart the jail. I'll be running it at boot, so I add the line mentioned above
ezjail_enable="YES" 
to /etc/rc.conf and then restart the jail.

/usr/local/etc/rc.d/ezjail.sh restart

You should see a message that the jail has started. Now, I can simply ssh to it as the new user and use sudo to do the rest of the configuration. If my user name in the jail is scott then I would simply do
ssh scott@192.168.1.231

You might want to add an entry on the host machine's /etc/hosts for the jail.
192.168.1.231	apachejail.example.com	apachejail

The jail is now configured. I'm ready to add apache. While in the jail
sudo pkg_add -r apache22

After this, I configure apache. One thing that needs to be done is add the following to the host machine's /boot/loader.conf. (Not the jail's loader.conf).
accf_http_load="YES"

Otherwise, one gets an error on startup (though apache will still run.)

Like the QND jail page, this isn't a page about apache. My own setup is extremely simple, no php or cgi. I add a line to the jail's /etc/rc.conf
enable_apache22="YES"

I only make a few changes to the default configuration files. With apache22, rather than a VirtualHosts configuration being in httpd.conf, there's an Include extra/httpd-vhosts.conf file.

Now I'll restart the jail. From the host machine
sudo /usr/local/etc/rc.d/ezjail.sh restart

(Again, that only works if ezjail_enable="YES" is already in /etc/rc.conf. If not then use forcerestart.)

Hopefully, when you start the jail, you will see that apache has also started. You should be able to see httpd running from the host system or while in the jail with top or pgrep.

Using ports

Although ezjail enables you to keep a ports tree in the base jail which is linked to all jails, I haven't used it. I simply make use of null_fs to temporarily mount the host system's ports tree. For example, if I want to upgrade apache in my apachejail, from the host system I would do
mount_nullfs /usr/ports /usr/jails/apachejail/usr/ports

Then, I can ssh into the jail, and install ports as I usually would. Once the port is installed, I exit the jail and umount /usr/ports from the jail's /usr/ports.

This is one reason I find it best to run ezjail-admin update as soon as I update a host system. If I've gotten lazy and updated my host system, as well as its ports, mount the ports tree in the jail as detailed above, then, for example, do a portupgrade of apache while within the jail, I've sometimes run into trouble with libexec mismatches.

So, make it a habit to run ezjail-admin update as soon as you've run a make world on the host system.

References

The ezjail home page, man(5) ezjail, man(1) ezjail-admin, man(5) ejzail.conf, man(8) jail, the QND jail page

Back to main page