Virtualization is something I've been interested in for some
time, dabbling with VMWare on Windows, and eagerly awaiting
Xen+BSD and AMD's Pacifica-enabled chips. FreeBSD's jail feature
gives many of the same benefits but with relatively little overhead,
as long as you're interested in working with the same version of
FreeBSD in your "virtual" system as your "host" is running.
Jails are a great way to isolate software - for security
reasons, to run different versions of the same package, or just to
allow yourself a sandbox to mess with that you can easily wipe out
and recreate in a few seconds.
The man page for jail describes how to setup a jail by hand, which seems
a bit involved. Luckily I stumbled across
ezjail, which
makes creating jails a breeze. Once it's setup, you can create and "boot"
a fully functioning jail with just three commands. ezjail arranges things so
most of the FreeBSD userland is shared between the jails, and the files
unique to each jail take up as little as 2mb.
The initial setup is basically:
- install the port in
sysutils/ezjail
- Add
ezjail_enable="YES"
to /etc/rc.conf
- edit
/usr/local/etc/ezjail.conf
to set where you want
your jails created. (In my case I used /data/jails
)
- make sure your
/usr/src
tree is complete
- run
ezjail-admin update
That last command can take a lot of time (maybe hours), since it does
a full make buildworld
, make installworld
.
If you've already built your world,
there's a -i
parameter for skipping that step and just doing the
make installworld
.
Once that's all done, in your jail directory there is a basejail
which contains
about 130+mb of files that will be shared between jails, newjail
which is a
skeleton containing about 2mb of files that gets copied to any new jails you create, and
flavours
which is basically another set of skeleton directories that get copied
over the newjail
skeleton when your jail is created.
At this point, you can create and boot a jail with:
ifconfig lo0 alias 127.66.0.1 netmask 255.255.255.255
or similar
to give one of your network interfaces an IP the jail can use.
ezjail create myjail 127.66.0.1
creates a new directory
(/data/jails/myjail
in my case) that's a copy of newjail
and sets a
few other things up.
-
/usr/local/etc/rc.d/ezjail.sh start myjail
At this point the jail is up and running. You can "log into" it by first finding
out the integer id of the jail with jls
, and then running
jexec <jail-id> /bin/sh
There are a few things that are missing in this barebones install, mainly no
/etc/resolv.conf
so domain name lookups don't work, no
/etc/localtime
so time in the jail shows as UTC.
You can fix these problems and add your own customizations easily by using a flavour
(don't mess with the newjail
template directory).
You can stop and wipe out your jail with
/usr/local/etc/rc.d/ezjail.sh stop myjail
ezjail-admin delete -w myjail
Then, to make a new flavour and make a jail using that flavour, something like
cd /data/jails/flavours
cp -pr default myflavour
cd myflavour/etc
cp -p /etc/resolv.conf .
cp -p /etc/localtime .
ezjail-admin create -f myflavour myjail 127.66.0.1
/usr/local/etc/rc.d/ezjail.sh start myjail
At this point, you've created a new jail with your customizations, and would use jls
again to find the jail-id, and jexec
to start a shell inside the running jail.
A flavour may also contain packages you wish to install upon jail creation, and commands to
execute when the jail is created. Check out the ezjail.flavour
file in your flavour directory. I've used it to install common useful things like bash
,
vim
, gmake
, and libiconv
and gettext
which take
a long time to build that you don't want to repeat for every jail.