individuals through email. Particular thanks to Glen Barber for his experience and patience.
1619 lines
60 KiB
XML
1619 lines
60 KiB
XML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!--
|
|
The FreeBSD Documentation Project
|
|
|
|
$FreeBSD$
|
|
-->
|
|
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="jails">
|
|
<info>
|
|
<title>Jails</title>
|
|
|
|
<authorgroup>
|
|
<author><personname><firstname>Matteo</firstname><surname>Riondato</surname></personname><contrib>Contributed
|
|
by </contrib></author>
|
|
</authorgroup>
|
|
</info>
|
|
|
|
<indexterm><primary>jails</primary></indexterm>
|
|
|
|
<sect1 xml:id="jails-synopsis">
|
|
<title>Synopsis</title>
|
|
|
|
<para>Since system administration is a difficult task, many tools
|
|
have been developed to make life easier for the administrator.
|
|
These tools often enhance the way systems are installed,
|
|
configured, and maintained. One of the tools which can be used
|
|
to enhance the security of a &os; system is
|
|
<firstterm>jails</firstterm>. Jails have been available since
|
|
&os; 4.X and continue to be enhanced in their usefulness,
|
|
performance, reliability, and security.</para>
|
|
|
|
<para>Jails build upon the &man.chroot.2; concept, which is used
|
|
to change the root directory of a set of processes, creating a
|
|
safe environment, separate from the rest of the system.
|
|
Processes created in the chrooted environment can not access
|
|
files or resources outside of it. For that reason, compromising
|
|
a service running in a chrooted environment should not allow the
|
|
attacker to compromise the entire system. However, a chroot has
|
|
several limitations. It is suited to easy tasks which do not
|
|
require much flexibility or complex, advanced features. Over
|
|
time many ways have been found to escape from a chrooted
|
|
environment, making it a less than ideal solution for securing
|
|
services.</para>
|
|
|
|
<para>Jails improve on the concept of the traditional chroot
|
|
environment in several ways. In a traditional chroot
|
|
environment, processes are only limited in the part of the file
|
|
system they can access. The rest of the system resources,
|
|
system users, running processes, and the networking subsystem
|
|
are shared by the chrooted processes and the processes of the
|
|
host system. Jails expand this model by virtualizing access to
|
|
the file system, the set of users, and the networking subsystem.
|
|
More fine-grained controls are available for tuning the access
|
|
of a jailed environment. Jails can be considered as a type of
|
|
operating system-level virtualization.</para>
|
|
|
|
<para>A jail is characterized by four elements:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>A directory subtree: the starting point from which a
|
|
jail is entered. Once inside the jail, a process is not
|
|
permitted to escape outside of this subtree.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A hostname: which will be used by the jail.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>An <acronym>IP</acronym> address: which is assigned to
|
|
the jail. The <acronym>IP</acronym> address of a jail is
|
|
often an alias address for an existing network
|
|
interface.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A command: the path name of an executable to run inside
|
|
the jail. The path is relative to the root directory of the
|
|
jail environment.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Jails have their own set of users and their own <systemitem
|
|
class="username">root</systemitem> account which are limited
|
|
to the jail environment. The <systemitem
|
|
class="username">root</systemitem> account of a jail is not
|
|
allowed to perform operations to the system outside of the
|
|
associated jail environment.</para>
|
|
|
|
<para>This chapter provides an overview of jail terminology are
|
|
how to use &os; jails. Jails are a powerful tool for system
|
|
administrators, but their basic usage can also be useful for
|
|
advanced users.</para>
|
|
|
|
<para>After reading this chapter, you will know:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>What a jail is and what purpose it may serve in &os;
|
|
installations.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>How to build, start, and stop a jail.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The basics of jail administration, both from inside and
|
|
outside the jail.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<important>
|
|
<para>Jails are a powerful tool, but they are not a security
|
|
panacea. While it is not possible for a jailed process to
|
|
break out on its own, there are several ways in which an
|
|
unprivileged user outside the jail can cooperate with a
|
|
privileged user inside the jail to obtain elevated privileges
|
|
in the host environment.</para>
|
|
|
|
<para>Most of these attacks can be mitigated by ensuring that
|
|
the jail root is not accessible to unprivileged users in the
|
|
host environment. As a general rule, untrusted users with
|
|
privileged access to a jail should not be given access to the
|
|
host environment.</para>
|
|
</important>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="jails-terms">
|
|
<title>Terms Related to Jails</title>
|
|
|
|
<para>To facilitate better understanding of parts of the &os;
|
|
system related to jails, their internals and the way they
|
|
interact with the rest of &os;, the following terms are used
|
|
further in this chapter:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>&man.chroot.8; (command)</term>
|
|
<listitem>
|
|
<para>Utility, which uses &man.chroot.2; &os; system call to
|
|
change the root directory of a process and all its
|
|
descendants.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>&man.chroot.2; (environment)</term>
|
|
<listitem>
|
|
<para>The environment of processes running in a
|
|
<quote>chroot</quote>. This includes resources such as
|
|
the part of the file system which is visible, user and
|
|
group IDs which are available, network interfaces and
|
|
other IPC mechanisms, etc.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>&man.jail.8; (command)</term>
|
|
<listitem>
|
|
<para>The system administration utility which allows
|
|
launching of processes within a jail environment.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>host (system, process, user, etc.)</term>
|
|
<listitem>
|
|
<para>The controlling system of a jail environment. The
|
|
host system has access to all the hardware resources
|
|
available, and can control processes both outside of and
|
|
inside a jail environment. One of the important
|
|
differences of the host system from a jail is that the
|
|
limitations which apply to superuser processes inside a
|
|
jail are not enforced for processes of the host
|
|
system.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>hosted (system, process, user, etc.)</term>
|
|
<listitem>
|
|
<para>A process, user or other entity, whose access to
|
|
resources is restricted by a &os; jail.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="jails-build">
|
|
<title>Creating and Controlling Jails</title>
|
|
|
|
<para>Some administrators divide jails into the following two
|
|
types: <quote>complete</quote> jails, which resemble a real &os;
|
|
system, and <quote>service</quote> jails, dedicated to one
|
|
application or service, possibly running with privileges. This
|
|
is only a conceptual division and the process of building a jail
|
|
is not affected by it. When creating a <quote>complete</quote>
|
|
jail there are two options for the source of the userland: use
|
|
prebuilt binaries (such as those supplied on an install media)
|
|
or build from source.</para>
|
|
|
|
<para>To install the userland from installation media, first
|
|
create the root directory for the jail. This can be done by
|
|
setting the <varname>DESTDIR</varname> variable to the proper
|
|
location. The command to use depends on which shell is being
|
|
used.</para>
|
|
|
|
<para>When using &man.sh.1;:</para>
|
|
|
|
<screen>&prompt.root; <userinput>export DESTDIR=<replaceable>/here/is/the/jail</replaceable></userinput></screen>
|
|
|
|
<para>If <command>csh</command>/<command>tcsh</command> is used,
|
|
execute this instead:</para>
|
|
|
|
<screen>&prompt.root; <userinput>setenv DESTDIR <replaceable>/here/is/the/jail</replaceable></userinput></screen>
|
|
|
|
<para>Mount the install media as covered in &man.mdconfig.8;
|
|
when using the install ISO:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mount -t cd9660 /dev/`mdconfig -f cdimage.iso` /mnt</userinput></screen>
|
|
|
|
<para>Extract the binaries from the tarballs on the install media
|
|
into the declared destination. Minimally, only the base set
|
|
needs to be extracted, but a complete install can be performed
|
|
when preferred.</para>
|
|
|
|
<para>To install just the base system, run the next command when
|
|
using &os; 9.x or newer:</para>
|
|
|
|
<screen>&prompt.root; <userinput>tar -xf /mnt/freebsd_install/usr/freebsd_dist/base.txz -C $DESTDIR</userinput></screen>
|
|
|
|
<para>On &os; 8.x systems, use this command instead:</para>
|
|
|
|
<screen>&prompt.root; <userinput>/mnt/8.<replaceable>4</replaceable>-RELEASE/base/install.sh</userinput></screen>
|
|
|
|
<para>To install everything but the kernel, issue this
|
|
command:</para>
|
|
|
|
<para>When using &man.sh.1; on &os; 9.x and newer, issue this
|
|
command:</para>
|
|
|
|
<screen>&prompt.root; <userinput>for <replaceable>sets</replaceable> in BASE DOC GAMES PORTS; do (tar -xf /mnt/FREEBSD_INSTALL/USR/FREEBSD_DIST/$<replaceable>sets</replaceable>.TXZ -C $DESTDIR</userinput></screen>
|
|
|
|
<para>When using &os; 8.x, run this:</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /mnt/8.<replaceable>4</replaceable>-RELEASE; for <replaceable>dir</replaceable> in base catpages dict doc games info manpages ports; do (cd $<replaceable>dir</replaceable>; ./install.sh) ; done</userinput></screen>
|
|
|
|
<para>If <command>csh</command>/<command>tcsh</command> is used on
|
|
&os; 9.x and newer, execute this command:</para>
|
|
|
|
<screen>&prompt.root; <userinput>foreach <replaceable>sets</replaceable> ( BASE DOC GAMES PORTS )
|
|
tar -xf /mnt/FREEBSD_INSTALL/USR/FREEBSD_DIST/$sets.TXZ -C $DESTDIR
|
|
done</userinput></screen>
|
|
|
|
<para>On &os; 8.x, run this command:</para>
|
|
|
|
<screen>&prompt.root; <userinput>foreach <replaceable>dir</replaceable> ( base catpages dict doc games info manpages ports )
|
|
cd /mnt/8.<replaceable>4</replaceable>-RELEASE/$dir; ./install.sh
|
|
done</userinput></screen>
|
|
|
|
<para>The &man.jail.8; manual page explains the procedure for
|
|
building a jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>setenv D <replaceable>/here/is/the/jail</replaceable></userinput>
|
|
&prompt.root; <userinput>mkdir -p $D</userinput> <co xml:id="jailpath"/>
|
|
&prompt.root; <userinput>cd /usr/src</userinput>
|
|
&prompt.root; <userinput>make buildworld</userinput> <co xml:id="jailbuildworld"/>
|
|
&prompt.root; <userinput>make installworld DESTDIR=$D</userinput> <co xml:id="jailinstallworld"/>
|
|
&prompt.root; <userinput>make distribution DESTDIR=$D</userinput> <co xml:id="jaildistrib"/>
|
|
&prompt.root; <userinput>mount -t devfs devfs $D/dev</userinput> <co xml:id="jaildevfs"/></screen>
|
|
|
|
<calloutlist>
|
|
<callout arearefs="jailpath">
|
|
<para>Selecting a location for a jail is the best starting
|
|
point. This is where the jail will physically reside within
|
|
the file system of the jail's host. A good choice can be
|
|
<filename
|
|
class="directory">/usr/jail/<replaceable>jailname</replaceable></filename>,
|
|
where <replaceable>jailname</replaceable> is the hostname
|
|
identifying the jail. The
|
|
<filename class="directory">/usr/</filename> file system
|
|
usually has enough space for the jail file system, which for
|
|
<quote>complete</quote> jails is, essentially, a replication
|
|
of every file present in a default installation of the &os;
|
|
base system.</para>
|
|
</callout>
|
|
|
|
<callout arearefs="jailbuildworld">
|
|
<para>If you have already rebuilt your userland using
|
|
<command>make world</command> or
|
|
<command>make buildworld</command>, you can skip this step
|
|
and install your existing userland into the new jail.</para>
|
|
</callout>
|
|
|
|
<callout arearefs="jailinstallworld">
|
|
<para>This command will populate the directory subtree chosen
|
|
as jail's physical location on the file system with the
|
|
necessary binaries, libraries, manual pages and so
|
|
on.</para>
|
|
</callout>
|
|
|
|
<callout arearefs="jaildistrib">
|
|
<para>The <buildtarget>distribution</buildtarget> target for
|
|
<application>make</application> installs every needed
|
|
configuration file. In simple words, it installs every
|
|
installable file of
|
|
<filename class="directory">/usr/src/etc/</filename> to the
|
|
<filename class="directory">/etc</filename> directory of the
|
|
jail environment:
|
|
<filename class="directory">$D/etc/</filename>.</para>
|
|
</callout>
|
|
|
|
<callout arearefs="jaildevfs">
|
|
<para>Mounting the &man.devfs.8; file system inside a jail is
|
|
not required. On the other hand, any, or almost any
|
|
application requires access to at least one device,
|
|
depending on the purpose of the given application. It is
|
|
very important to control access to devices from inside a
|
|
jail, as improper settings could permit an attacker to do
|
|
nasty things in the jail. Control over &man.devfs.8; is
|
|
managed through rulesets which are described in the
|
|
&man.devfs.8; and &man.devfs.conf.5; manual pages.</para>
|
|
</callout>
|
|
</calloutlist>
|
|
|
|
<para>Once a jail is installed, it can be started by using the
|
|
&man.jail.8; utility. The &man.jail.8; utility takes four
|
|
mandatory arguments which are described in the <xref
|
|
linkend="jails-synopsis"/>. Other arguments may be specified
|
|
too, e.g., to run the jailed process with the credentials of a
|
|
specific user. The
|
|
<option><replaceable>command</replaceable></option> argument
|
|
depends on the type of the jail; for a
|
|
<emphasis>virtual system</emphasis>,
|
|
<filename>/etc/rc</filename> is a good choice, since it will
|
|
replicate the startup sequence of a real &os; system. For a
|
|
<emphasis>service</emphasis> jail, it depends on the service or
|
|
application that will run within the jail.</para>
|
|
|
|
<para>Jails are often started at boot time and the &os;
|
|
<filename>rc</filename> mechanism provides an easy way to do
|
|
this.</para>
|
|
|
|
<procedure>
|
|
<step>
|
|
<para>A list of the jails which are enabled to start at boot
|
|
time should be added to the &man.rc.conf.5; file:</para>
|
|
|
|
<programlisting>jail_enable="YES" # Set to NO to disable starting of any jails
|
|
jail_list="<replaceable>www</replaceable>" # Space separated list of names of jails</programlisting>
|
|
|
|
<note>
|
|
<para>Jail names in <varname>jail_list</varname> should
|
|
contain alphanumeric characters only.</para>
|
|
</note>
|
|
</step>
|
|
|
|
<step>
|
|
<para>For each jail listed in <varname>jail_list</varname>, a
|
|
group of &man.rc.conf.5; settings, which describe the
|
|
particular jail, should be added:</para>
|
|
|
|
<programlisting>jail_<replaceable>www</replaceable>_rootdir="/usr/jail/www" # jail's root directory
|
|
jail_<replaceable>www</replaceable>_hostname="<replaceable>www</replaceable>.example.org" # jail's hostname
|
|
jail_<replaceable>www</replaceable>_ip="192.168.0.10" # jail's IP address
|
|
jail_<replaceable>www</replaceable>_devfs_enable="YES" # mount devfs in the jail</programlisting>
|
|
|
|
<para>The default startup of jails configured in
|
|
&man.rc.conf.5;, will run the <filename>/etc/rc</filename>
|
|
script of the jail, which assumes the jail is a complete
|
|
virtual system. For service jails, the default startup
|
|
command of the jail should be changed, by setting the
|
|
<varname>jail_<replaceable>jailname</replaceable>_exec_start</varname>
|
|
option appropriately.</para>
|
|
|
|
<note>
|
|
<para>For a full list of available options, please see the
|
|
&man.rc.conf.5; manual page.</para>
|
|
</note>
|
|
</step>
|
|
</procedure>
|
|
|
|
<para>&man.service.8; can be used to start or stop a jail by hand,
|
|
if an entry for it exists in
|
|
<filename>rc.conf</filename>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>service jail start <replaceable>www</replaceable></userinput>
|
|
&prompt.root; <userinput>service jail stop <replaceable>www</replaceable></userinput></screen>
|
|
|
|
<para>A clean way to shut down a &man.jail.8; is not available at
|
|
the moment. This is because commands normally used to
|
|
accomplish a clean system shutdown cannot be used inside a jail.
|
|
The best way to shut down a jail is to run the following command
|
|
from within the jail itself or using the &man.jexec.8; utility
|
|
from outside the jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>sh /etc/rc.shutdown</userinput></screen>
|
|
|
|
<para>More information about this can be found in the &man.jail.8;
|
|
manual page.</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="jails-tuning">
|
|
<title>Fine Tuning and Administration</title>
|
|
|
|
<para>There are several options which can be set for any jail, and
|
|
various ways of combining a host &os; system with jails, to
|
|
produce higher level applications. This section
|
|
presents:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Some of the options available for tuning the behavior
|
|
and security restrictions implemented by a jail
|
|
installation.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Some of the high-level applications for jail management,
|
|
which are available through the &os; Ports Collection, and
|
|
can be used to implement overall jail-based
|
|
solutions.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<sect2 xml:id="jails-tuning-utilities">
|
|
<title>System Tools for Jail Tuning in &os;</title>
|
|
|
|
<para>Fine tuning of a jail's configuration is mostly done by
|
|
setting &man.sysctl.8; variables. A special subtree of sysctl
|
|
exists as a basis for organizing all the relevant options: the
|
|
<varname>security.jail.*</varname> hierarchy of &os; kernel
|
|
options. Here is a list of the main jail-related sysctls,
|
|
complete with their default value. Names should be
|
|
self-explanatory, but for more information about them, please
|
|
refer to the &man.jail.8; and &man.sysctl.8; manual
|
|
pages.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><varname>security.jail.set_hostname_allowed:
|
|
1</varname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><varname>security.jail.socket_unixiproute_only:
|
|
1</varname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><varname>security.jail.sysvipc_allowed:
|
|
0</varname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><varname>security.jail.enforce_statfs:
|
|
2</varname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><varname>security.jail.allow_raw_sockets:
|
|
0</varname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><varname>security.jail.chflags_allowed:
|
|
0</varname></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><varname>security.jail.jailed: 0</varname></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>These variables can be used by the system administrator of
|
|
the <emphasis>host system</emphasis> to add or remove some of
|
|
the limitations imposed by default on the <systemitem
|
|
class="username">root</systemitem> user. Note that there
|
|
are some limitations which cannot be removed. The
|
|
<systemitem class="username">root</systemitem> user is not
|
|
allowed to mount or unmount file systems from within a
|
|
&man.jail.8;. The <systemitem
|
|
class="username">root</systemitem> inside a jail may not
|
|
load or unload &man.devfs.8; rulesets, set firewall rules, or
|
|
do many other administrative tasks which require modifications
|
|
of in-kernel data, such as setting the
|
|
<varname>securelevel</varname> of the kernel.</para>
|
|
|
|
<para>The base system of &os; contains a basic set of tools for
|
|
viewing information about the active jails, and attaching to a
|
|
jail to run administrative commands. The &man.jls.8; and
|
|
&man.jexec.8; commands are part of the base &os; system, and
|
|
can be used to perform the following simple tasks:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Print a list of active jails and their corresponding
|
|
jail identifier (<acronym>JID</acronym>),
|
|
<acronym>IP</acronym> address, hostname and path.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Attach to a running jail, from its host system, and
|
|
run a command inside the jail or perform administrative
|
|
tasks inside the jail itself. This is especially useful
|
|
when the <systemitem class="username">root</systemitem>
|
|
user wants to cleanly shut down a jail. The &man.jexec.8;
|
|
utility can also be used to start a shell in a jail to do
|
|
administration in it; for example:</para>
|
|
|
|
<screen>&prompt.root; <userinput>jexec <replaceable>1</replaceable> tcsh</userinput></screen>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-tuning-admintools">
|
|
<title>High-Level Administrative Tools in the &os; Ports
|
|
Collection</title>
|
|
|
|
<para>Among the many third-party utilities for jail
|
|
administration, one of the most complete and useful is
|
|
<package>sysutils/jailutils</package>. It is a set of small
|
|
applications that contribute to &man.jail.8; management.
|
|
Please refer to its web page for more information.</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-updating">
|
|
<title>Keeping Jails Patched and up to Date</title>
|
|
|
|
<para>Jails should be kept up to date from the host operating
|
|
system as attempting to patch userland from within the jail
|
|
may likely fail as the default behaviour in FreeBSD is to
|
|
disallow the use of &man.chflags.1; in a jail which prevents
|
|
the replacement of some files. It is possible to change this
|
|
behavior but it is recommended to use &man.freebsd-update.8;
|
|
to maintain jails instead. Use <option>-b</option> to specify
|
|
the path of the jail to be updated.</para>
|
|
|
|
<screen>&prompt.root; <userinput>freebsd-update -b <replaceable>/here/is/the/jail</replaceable> fetch</userinput>
|
|
&prompt.root; <userinput>freebsd-update -b <replaceable>/here/is/the/jail</replaceable> install</userinput></screen>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="jails-application">
|
|
<info>
|
|
<title>Updating Multiple Jails</title>
|
|
|
|
<authorgroup>
|
|
<author>
|
|
<personname>
|
|
<firstname>Daniel</firstname>
|
|
<surname>Gerzo</surname>
|
|
</personname>
|
|
<contrib>Contributed by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
<authorgroup>
|
|
<author>
|
|
<personname>
|
|
<firstname>Simon</firstname>
|
|
<surname>L. B. Nielsen</surname>
|
|
</personname>
|
|
<contrib>Based upon an idea presented by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
<authorgroup>
|
|
<author>
|
|
<personname>
|
|
<firstname>Ken</firstname>
|
|
<surname>Tom</surname>
|
|
</personname>
|
|
<contrib>And an article written by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
</info>
|
|
|
|
<para>The management of multiple jails can become problematic
|
|
because every jail has to be rebuilt from scratch whenever it is
|
|
upgraded. This can be time consuming and tedious if a lot of
|
|
jails are created and manually updated.</para>
|
|
|
|
<para>This section demonstrates one method to resolve this issue
|
|
by safely sharing as much as is possible between jails using
|
|
read-only &man.mount.nullfs.8; mounts, so that updating is
|
|
simpler. This makes it more attractive to put single services,
|
|
such as <acronym>HTTP</acronym>, <acronym>DNS</acronym>, and
|
|
<acronym>SMTP</acronym>, into individual jails. Additionally,
|
|
it provides a simple way to add, remove, and upgrade
|
|
jails.</para>
|
|
|
|
<note>
|
|
<para>Simpler solutions exist, such as
|
|
<application>ezjail</application>, which provides an easier
|
|
method of administering &os; jails but is less versatile than
|
|
this setup. <application>ezjail</application> is covered in
|
|
more detail in <xref linkend="jails-ezjail"/>.</para>
|
|
</note>
|
|
|
|
<para>The goals of the setup described in this section are:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Create a simple and easy to understand jail structure
|
|
that does not require running a full installworld on each
|
|
and every jail.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Make it easy to add new jails or remove existing
|
|
ones.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Make it easy to update or upgrade existing jails.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Make it possible to run a customized &os; branch.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Be paranoid about security, reducing as much as
|
|
possible the possibility of compromise.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Save space and inodes, as much as possible.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>This design relies on a single, read-only master template
|
|
which is mounted into each jail and one read-write device per
|
|
jail. A device can be a separate physical disc, a partition, or
|
|
a vnode backed memory device. This example uses read-write
|
|
<application>nullfs</application> mounts.</para>
|
|
|
|
<para>The file system layout is as follows:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>The jails are based under the
|
|
<filename>/home</filename> partition.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each jail will be mounted under the
|
|
<filename>/home/j</filename> directory.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The template for each jail and the read-only partition
|
|
for all of the jails is
|
|
<filename>/home/j/mroot</filename>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A blank directory will be created for each jail under
|
|
the <filename>/home/j</filename> directory.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each jail will have a <filename>/s</filename> directory
|
|
that will be linked to the read-write portion of the
|
|
system.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each jail will have its own read-write system that is
|
|
based upon <filename>/home/j/skel</filename>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The read-write portion of each jail will be created in
|
|
<filename>/home/js</filename>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<!-- Insert an image or drawing here to illustrate the example. -->
|
|
|
|
<sect2 xml:id="jails-service-jails-template">
|
|
<title>Creating the Template</title>
|
|
|
|
<para>This section describes the steps needed to create the
|
|
master template.</para>
|
|
|
|
<para>It is recommended to first update the host &os; system to
|
|
the latest -RELEASE branch using the instructions in <xref
|
|
linkend="makeworld"/>. Additionally, this template uses the
|
|
<package>sysutils/cpdup</package> package or port and
|
|
<application>portsnap</application> will be used to download
|
|
the &os; Ports Collection.</para>
|
|
|
|
<procedure>
|
|
<step>
|
|
<para>First, create a directory structure for the read-only
|
|
file system which will contain the &os; binaries for the
|
|
jails. Then, change directory to the &os; source tree and
|
|
install the read-only file system to the jail
|
|
template:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mkdir /home/j /home/j/mroot</userinput>
|
|
&prompt.root; <userinput>cd /usr/src</userinput>
|
|
&prompt.root; <userinput>make installworld DESTDIR=/home/j/mroot</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Next, prepare a &os; Ports Collection for the jails as
|
|
well as a &os; source tree, which is required for
|
|
<application>mergemaster</application>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /home/j/mroot</userinput>
|
|
&prompt.root; <userinput>mkdir usr/ports</userinput>
|
|
&prompt.root; <userinput>portsnap -p /home/j/mroot/usr/ports fetch extract</userinput>
|
|
&prompt.root; <userinput>cpdup /usr/src /home/j/mroot/usr/src</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Create a skeleton for the read-write portion of the
|
|
system:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mkdir /home/j/skel /home/j/skel/home /home/j/skel/usr-X11R6 /home/j/skel/distfiles</userinput>
|
|
&prompt.root; <userinput>mv etc /home/j/skel</userinput>
|
|
&prompt.root; <userinput>mv usr/local /home/j/skel/usr-local</userinput>
|
|
&prompt.root; <userinput>mv tmp /home/j/skel</userinput>
|
|
&prompt.root; <userinput>mv var /home/j/skel</userinput>
|
|
&prompt.root; <userinput>mv root /home/j/skel</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Use <application>mergemaster</application> to install
|
|
missing configuration files. Then, remove the extra
|
|
directories that <application>mergemaster</application>
|
|
creates:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mergemaster -t /home/j/skel/var/tmp/temproot -D /home/j/skel -i</userinput>
|
|
&prompt.root; <userinput>cd /home/j/skel</userinput>
|
|
&prompt.root; <userinput>rm -R bin boot lib libexec mnt proc rescue sbin sys usr dev</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Now, symlink the read-write file system to the
|
|
read-only file system. Ensure that the symlinks are
|
|
created in the correct <filename>s/</filename> locations
|
|
as the creation of directories in the wrong locations will
|
|
cause the installation to fail.</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /home/j/mroot</userinput>
|
|
&prompt.root; <userinput>mkdir s</userinput>
|
|
&prompt.root; <userinput>ln -s s/etc etc</userinput>
|
|
&prompt.root; <userinput>ln -s s/home home</userinput>
|
|
&prompt.root; <userinput>ln -s s/root root</userinput>
|
|
&prompt.root; <userinput>ln -s s/usr-local usr/local</userinput>
|
|
&prompt.root; <userinput>ln -s s/usr-X11R6 usr/X11R6</userinput>
|
|
&prompt.root; <userinput>ln -s s/distfiles usr/ports/distfiles</userinput>
|
|
&prompt.root; <userinput>ln -s s/tmp tmp</userinput>
|
|
&prompt.root; <userinput>ln -s s/var var</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>As a last step, create a generic
|
|
<filename>/home/j/skel/etc/make.conf</filename> containing
|
|
this line:</para>
|
|
|
|
<programlisting>WRKDIRPREFIX?= /s/portbuild</programlisting>
|
|
|
|
<para>This makes it possible to compile &os; ports inside
|
|
each jail. Remember that the ports directory is part of
|
|
the read-only system. The custom path for
|
|
<literal>WRKDIRPREFIX</literal> allows builds to be done
|
|
in the read-write portion of every jail.</para>
|
|
</step>
|
|
</procedure>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-service-jails-creating">
|
|
<title>Creating Jails</title>
|
|
|
|
<para>The jail template can now be used to setup and configure
|
|
the jails in <filename>/etc/rc.conf</filename>. This example
|
|
demonstrates the creation of 3 jails: <literal>NS</literal>,
|
|
<literal>MAIL</literal> and <literal>WWW</literal>.</para>
|
|
|
|
<procedure>
|
|
<step>
|
|
<para>Add the following lines to
|
|
<filename>/etc/fstab</filename>, so that the read-only
|
|
template for the jails and the read-write space will be
|
|
available in the respective jails:</para>
|
|
|
|
<programlisting>/home/j/mroot /home/j/ns nullfs ro 0 0
|
|
/home/j/mroot /home/j/mail nullfs ro 0 0
|
|
/home/j/mroot /home/j/www nullfs ro 0 0
|
|
/home/js/ns /home/j/ns/s nullfs rw 0 0
|
|
/home/js/mail /home/j/mail/s nullfs rw 0 0
|
|
/home/js/www /home/j/www/s nullfs rw 0 0</programlisting>
|
|
|
|
<para>To prevent
|
|
<application>fsck</application> from checking
|
|
<application>nullfs</application> mounts during boot and
|
|
<application>dump</application> from backing up the
|
|
read-only nullfs mounts of the jails, the last two
|
|
columns are both set to <literal>0</literal>.</para>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Configure the jails in
|
|
<filename>/etc/rc.conf</filename>:</para>
|
|
|
|
<programlisting>jail_enable="YES"
|
|
jail_set_hostname_allow="NO"
|
|
jail_list="ns mail www"
|
|
jail_ns_hostname="ns.example.org"
|
|
jail_ns_ip="192.168.3.17"
|
|
jail_ns_rootdir="/usr/home/j/ns"
|
|
jail_ns_devfs_enable="YES"
|
|
jail_mail_hostname="mail.example.org"
|
|
jail_mail_ip="192.168.3.18"
|
|
jail_mail_rootdir="/usr/home/j/mail"
|
|
jail_mail_devfs_enable="YES"
|
|
jail_www_hostname="www.example.org"
|
|
jail_www_ip="62.123.43.14"
|
|
jail_www_rootdir="/usr/home/j/www"
|
|
jail_www_devfs_enable="YES"</programlisting>
|
|
|
|
<para>The
|
|
<varname>jail_<replaceable>name</replaceable>_rootdir</varname>
|
|
variable is set to
|
|
<filename class="directory">/usr/home</filename> instead
|
|
of <filename class="directory">/home</filename> because
|
|
the physical path of <filename
|
|
class="directory">/home</filename> on a default &os;
|
|
installation is <filename
|
|
class="directory">/usr/home</filename>. The
|
|
<varname>jail_<replaceable>name</replaceable>_rootdir</varname>
|
|
variable must <emphasis>not</emphasis> be set to a path
|
|
which includes a symbolic link, otherwise the jails will
|
|
refuse to start.</para>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Create the required mount points for the read-only
|
|
file system of each jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mkdir /home/j/ns /home/j/mail /home/j/www</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Install the read-write template into each jail using
|
|
<package>sysutils/cpdup</package>:</para>
|
|
<!-- keramida: Why is cpdup required here? Doesn't cpio(1)
|
|
already include adequate functionality for performing this
|
|
job *and* have the advantage of being part of the base
|
|
system of FreeBSD? -->
|
|
|
|
<screen>&prompt.root; <userinput>mkdir /home/js</userinput>
|
|
&prompt.root; <userinput>cpdup /home/j/skel /home/js/ns</userinput>
|
|
&prompt.root; <userinput>cpdup /home/j/skel /home/js/mail</userinput>
|
|
&prompt.root; <userinput>cpdup /home/j/skel /home/js/www</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>In this phase, the jails are built and prepared to
|
|
run. First, mount the required file systems for each
|
|
jail, and then start them:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mount -a</userinput>
|
|
&prompt.root; <userinput>service jail start</userinput></screen>
|
|
</step>
|
|
</procedure>
|
|
|
|
<para>The jails should be running now. To check if they have
|
|
started correctly, use <command>jls</command>. Its output
|
|
should be similar to the following:</para>
|
|
|
|
<screen>&prompt.root; <userinput>jls</userinput>
|
|
JID IP Address Hostname Path
|
|
3 192.168.3.17 ns.example.org /home/j/ns
|
|
2 192.168.3.18 mail.example.org /home/j/mail
|
|
1 62.123.43.14 www.example.org /home/j/www</screen>
|
|
|
|
<para>At this point, it should be possible to log onto each
|
|
jail, add new users, or configure daemons. The
|
|
<literal>JID</literal> column indicates the jail
|
|
identification number of each running jail. Use the following
|
|
command to perform administrative tasks in the jail whose
|
|
<acronym>JID</acronym> is <literal>3</literal>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>jexec 3 tcsh</userinput></screen>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-service-jails-upgrading">
|
|
<title>Upgrading</title>
|
|
|
|
<para>The design of this setup provides an easy way to upgrade
|
|
existing jails while minimizing their downtime. Also, it
|
|
provides a way to roll back to the older version should a
|
|
problem occur.</para>
|
|
|
|
<procedure>
|
|
<step>
|
|
<para>The first step is to upgrade the host system. Then,
|
|
create a new temporary read-only template in
|
|
<filename>/home/j/mroot2</filename>.</para>
|
|
|
|
<screen>&prompt.root; <userinput>mkdir /home/j/mroot2</userinput>
|
|
&prompt.root; <userinput>cd /usr/src</userinput>
|
|
&prompt.root; <userinput>make installworld DESTDIR=/home/j/mroot2</userinput>
|
|
&prompt.root; <userinput>cd /home/j/mroot2</userinput>
|
|
&prompt.root; <userinput>cpdup /usr/src usr/src</userinput>
|
|
&prompt.root; <userinput>mkdir s</userinput></screen>
|
|
|
|
<para>The <buildtarget>installworld</buildtarget> creates a
|
|
few unnecessary directories, which should be
|
|
removed:</para>
|
|
|
|
<screen>&prompt.root; <userinput>chflags -R 0 var</userinput>
|
|
&prompt.root; <userinput>rm -R etc var root usr/local tmp</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Recreate the read-write symlinks for the master file
|
|
system:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ln -s s/etc etc</userinput>
|
|
&prompt.root; <userinput>ln -s s/root root</userinput>
|
|
&prompt.root; <userinput>ln -s s/home home</userinput>
|
|
&prompt.root; <userinput>ln -s ../s/usr-local usr/local</userinput>
|
|
&prompt.root; <userinput>ln -s ../s/usr-X11R6 usr/X11R6</userinput>
|
|
&prompt.root; <userinput>ln -s s/tmp tmp</userinput>
|
|
&prompt.root; <userinput>ln -s s/var var</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Next, stop the jails:</para>
|
|
|
|
<screen>&prompt.root; <userinput>service jail stop</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Unmount the original file systems as the read-write
|
|
systems are attached to the read-only system
|
|
(<filename>/s</filename>):</para>
|
|
<!-- keramida: Shouldn't we suggest a short script-based
|
|
loop here, instead of tediously copying the same commands
|
|
multiple times? -->
|
|
|
|
<screen>&prompt.root; <userinput>umount /home/j/ns/s</userinput>
|
|
&prompt.root; <userinput>umount /home/j/ns</userinput>
|
|
&prompt.root; <userinput>umount /home/j/mail/s</userinput>
|
|
&prompt.root; <userinput>umount /home/j/mail</userinput>
|
|
&prompt.root; <userinput>umount /home/j/www/s</userinput>
|
|
&prompt.root; <userinput>umount /home/j/www</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Move the old read-only file system and replace it with
|
|
the new one. This will serve as a backup and archive of
|
|
the old read-only file system should something go wrong.
|
|
The naming convention used here corresponds to when a new
|
|
read-only file system has been created. Move the original
|
|
&os; Ports Collection over to the new file system to save
|
|
some space and inodes:</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /home/j</userinput>
|
|
&prompt.root; <userinput>mv mroot mroot.20060601</userinput>
|
|
&prompt.root; <userinput>mv mroot2 mroot</userinput>
|
|
&prompt.root; <userinput>mv mroot.20060601/usr/ports mroot/usr</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>At this point the new read-only template is ready, so
|
|
the only remaining task is to remount the file systems and
|
|
start the jails:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mount -a</userinput>
|
|
&prompt.root; <userinput>service jail start</userinput></screen>
|
|
</step>
|
|
</procedure>
|
|
|
|
<para>Use <command>jls</command> to check if the jails started
|
|
correctly. Run <command>mergemaster</command> in each jail to
|
|
update the configuration files.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="jails-ezjail">
|
|
<info>
|
|
<title>Managing Jails with
|
|
<application>ezjail</application></title>
|
|
|
|
<authorgroup>
|
|
<author>
|
|
<personname>
|
|
<firstname>Warren</firstname>
|
|
<surname>Block</surname>
|
|
</personname><contrib>Originally contributed by </contrib>
|
|
</author>
|
|
</authorgroup>
|
|
</info>
|
|
|
|
<para>Creating and managing multiple jails can quickly become
|
|
tedious and error-prone. Dirk Engling's
|
|
<application>ezjail</application> automates and greatly
|
|
simplifies many jail tasks. A <emphasis>basejail</emphasis> is
|
|
created as a template. Additional jails use &man.mount.nullfs.8;
|
|
to share many of the basejail directories without using
|
|
additional disk space. Each additional jail takes only a few
|
|
megabytes of disk space before applications are installed.
|
|
Upgrading the copy of the userland in the basejail automatically
|
|
upgrades all of the other jails.</para>
|
|
|
|
<para>Additional benefits and features are described in detail on
|
|
the <application>ezjail</application> web site, <link
|
|
xlink:href="https://erdgeist.org/arts/software/ezjail/"></link>.</para>
|
|
|
|
<sect2 xml:id="jails-ezjail-install">
|
|
<title>Installing <application>ezjail</application></title>
|
|
|
|
<para>Installing <application>ezjail</application> consists of
|
|
adding a loopback interface for use in jails, installing the
|
|
port or package, and enabling the service.</para>
|
|
|
|
<procedure xml:id="jails-ezjail-install-procedure">
|
|
<step>
|
|
<para>To keep jail loopback traffic off the host's loopback
|
|
network interface <literal>lo0</literal>, a second
|
|
loopback interface is created by adding an entry to
|
|
<filename>/etc/rc.conf</filename>:</para>
|
|
|
|
<programlisting>cloned_interfaces="${cloned_interfaces} lo1"</programlisting>
|
|
|
|
<para>The second loopback interface <literal>lo1</literal>
|
|
will be created when the system starts. It can also be
|
|
created manually without a restart:</para>
|
|
|
|
<screen>&prompt.root; <userinput>service netif cloneup</userinput>
|
|
Created clone interfaces: lo1.</screen>
|
|
|
|
<para>Jails can be allowed to use aliases of this secondary
|
|
loopback interface without interfering with the
|
|
host.</para>
|
|
|
|
<para>Inside a jail, access to the loopback address
|
|
<systemitem class="ipaddress">127.0.0.1</systemitem> is
|
|
redirected to the first <acronym>IP</acronym> address
|
|
assigned to the jail. To make the jail loopback
|
|
correspond with the new <literal>lo1</literal> interface,
|
|
that interface must be specified first in the list of
|
|
interfaces and <acronym>IP</acronym> addresses given when
|
|
creating a new jail.</para>
|
|
|
|
<para>Give each jail a unique loopback address in the
|
|
<systemitem
|
|
class="ipaddress">127.0.0.0</systemitem><systemitem
|
|
class="netmask">/8</systemitem> netblock.</para>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Install
|
|
<package role="port">sysutils/ezjail</package>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /usr/ports/sysutils/ezjail</userinput>
|
|
&prompt.root; <userinput>make install clean</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Enable <application>ezjail</application> by adding
|
|
this line to <filename>/etc/rc.conf</filename>:</para>
|
|
|
|
<programlisting>ezjail_enable="YES"</programlisting>
|
|
</step>
|
|
|
|
<step>
|
|
<para>The service will automatically start on system boot.
|
|
It can be started immediately for the current
|
|
session:</para>
|
|
|
|
<screen>&prompt.root; <userinput>service ezjail start</userinput></screen>
|
|
</step>
|
|
</procedure>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-ezjail-initialsetup">
|
|
<title>Initial Setup</title>
|
|
|
|
<para>With <application>ezjail</application> installed, the
|
|
basejail directory structure can be created and populated.
|
|
This step is only needed once on the jail host
|
|
computer.</para>
|
|
|
|
<para>In both of these examples, <option>-p</option> causes the
|
|
ports tree to be retrieved with &man.portsnap.8; into the
|
|
basejail. That single copy of the ports directory will be
|
|
shared by all the jails. Using a separate copy of the ports
|
|
directory for jails isolates them from the host. The
|
|
<application>ezjail</application> <acronym>FAQ</acronym>
|
|
explains in more detail: <link
|
|
xlink:href="http://erdgeist.org/arts/software/ezjail/#FAQ"></link>.</para>
|
|
|
|
<procedure xml:id="jails-ezjail-initialsetup-procedure">
|
|
<step>
|
|
<stepalternatives>
|
|
<step>
|
|
<title>To Populate the Jail with &os;-RELEASE</title>
|
|
|
|
<para>For a basejail based on the &os; RELEASE matching
|
|
that of the host computer, use
|
|
<command>install</command>. For example, on a host
|
|
computer running &os; 10-STABLE, the latest
|
|
RELEASE version of &os; -10 will be installed in
|
|
the jail):</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin install -p</userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<title>To Populate the Jail with
|
|
<command>installworld</command></title>
|
|
|
|
<para>The basejail can be installed from binaries
|
|
created by <buildtarget>buildworld</buildtarget> on
|
|
the host with
|
|
<command>ezjail-admin update</command>.</para>
|
|
|
|
<para>In this example, &os; 10-STABLE has been
|
|
built from source. The jail directories are created.
|
|
Then <buildtarget>installworld</buildtarget> is
|
|
executed, installing the host's
|
|
<filename>/usr/obj</filename> into the
|
|
basejail.</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin update -i -p</userinput></screen>
|
|
|
|
<para>The host's <filename>/usr/src</filename> is used
|
|
by default. A different source directory on the host
|
|
can be specified with <option>-s</option> and a path,
|
|
or set with <varname>ezjail_sourcetree</varname> in
|
|
<filename>/usr/local/etc/ezjail.conf</filename>.</para>
|
|
</step>
|
|
</stepalternatives>
|
|
</step>
|
|
</procedure>
|
|
|
|
<tip>
|
|
<para>The basejail's ports tree is shared by other jails.
|
|
However, downloaded distfiles are stored in the jail that
|
|
downloaded them. By default, these files are stored in
|
|
<filename>/var/ports/distfiles</filename> within each
|
|
jail. <filename>/var/ports</filename> inside each jail is
|
|
also used as a work directory when building ports.</para>
|
|
</tip>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-ezjail-create">
|
|
<title>Creating and Starting a New Jail</title>
|
|
|
|
<para>New jails are created with
|
|
<command>ezjail-admin create</command>. In these examples,
|
|
the <literal>lo1</literal> loopback interface is used as
|
|
described above.</para>
|
|
|
|
<procedure xml:id="jails-ezjail-create-steps">
|
|
<title>Create and Start a New Jail</title>
|
|
|
|
<step>
|
|
<para>Create the jail, specifying a name and the loopback
|
|
and network interfaces to use, along with their
|
|
<acronym>IP</acronym> addresses. In this example, the
|
|
jail is named <literal>dnsjail</literal>.</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin create <replaceable>dnsjail</replaceable> '<replaceable>lo1|127.0.1.1</replaceable>,<replaceable>em0</replaceable>|<replaceable>192.168.1.50</replaceable>'</userinput></screen>
|
|
|
|
<tip xml:id="jails-ezjail-raw-network-sockets">
|
|
<para>Most network services run in jails without
|
|
problems. A few network services, most notably
|
|
&man.ping.8;, use
|
|
<emphasis>raw network sockets</emphasis>. In jails, raw
|
|
network sockets are disabled by default for security.
|
|
Services that require them will not work.</para>
|
|
|
|
<para>Occasionally, a jail genuinely needs raw sockets.
|
|
For example, network monitoring applications often use
|
|
&man.ping.8; to check the availability of other
|
|
computers. When raw network sockets are actually needed
|
|
in a jail, they can be enabled by editing the
|
|
<application>ezjail</application>
|
|
configuration file for the individual jail,
|
|
<filename>/usr/local/etc/ezjail/<replaceable>jailname</replaceable></filename>.
|
|
Modify the <literal>parameters</literal>
|
|
entry:</para>
|
|
|
|
<programlisting>export jail_<replaceable>jailname</replaceable>_parameters="allow.raw_sockets=1"</programlisting>
|
|
|
|
<para>Do not enable raw network sockets unless services in
|
|
the jail actually require them.</para>
|
|
</tip>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Start the jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin start <replaceable>dnsjail</replaceable></userinput></screen>
|
|
</step>
|
|
|
|
<step>
|
|
<para>Use a console on the jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin console <replaceable>dnsjail</replaceable></userinput></screen>
|
|
</step>
|
|
</procedure>
|
|
|
|
<para>The jail is operating and additional configuration can be
|
|
completed. Typical settings added at this point
|
|
include:</para>
|
|
|
|
<procedure>
|
|
<step>
|
|
<title>Set the
|
|
<systemitem class="username">root</systemitem>
|
|
Password</title>
|
|
|
|
<para>Connect to the jail and set the
|
|
<systemitem class="username">root</systemitem> user's
|
|
password:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin console <replaceable>dnsjail</replaceable></userinput>
|
|
&prompt.root; <userinput>passwd</userinput>
|
|
Changing local password for root
|
|
New Password:
|
|
Retype New Password:</screen>
|
|
</step>
|
|
|
|
<step>
|
|
<title>Time Zone Configuration</title>
|
|
|
|
<para>The jail's time zone can be set with &man.tzsetup.8;.
|
|
To avoid spurious error messages, the &man.adjkerntz.8;
|
|
entry in <filename>/etc/crontab</filename> can be
|
|
commented or removed. This job attempts to update the
|
|
computer's hardware clock with time zone changes, but
|
|
jails are not allowed to access that hardware.</para>
|
|
</step>
|
|
|
|
<step>
|
|
<title><acronym>DNS</acronym> Servers</title>
|
|
|
|
<para>Enter domain name server lines in
|
|
<filename>/etc/resolv.conf</filename> so
|
|
<acronym>DNS</acronym> works in the jail.</para>
|
|
</step>
|
|
|
|
<step>
|
|
<title>Edit <filename>/etc/hosts</filename></title>
|
|
|
|
<para>Change the address and add the jail name to the
|
|
<literal>localhost</literal> entries in
|
|
<filename>/etc/hosts</filename>.</para>
|
|
</step>
|
|
|
|
<step>
|
|
<title>Configure <filename>/etc/rc.conf</filename></title>
|
|
|
|
<para>Enter configuration settings in
|
|
<filename>/etc/rc.conf</filename>. This is much like
|
|
configuring a full computer. The host name and
|
|
<acronym>IP</acronym> address are not set here. Those
|
|
values are already provided by the jail
|
|
configuration.</para>
|
|
</step>
|
|
</procedure>
|
|
|
|
<para>With the jail configured, the applications for which the
|
|
jail was created can be installed.</para>
|
|
|
|
<tip>
|
|
<para>Some ports must be built with special options to be used
|
|
in a jail. For example, both of the network monitoring
|
|
plugin packages
|
|
<package role="port">net-mgmt/nagios-plugins</package> and
|
|
<package role="port">net-mgmt/monitoring-plugins</package>
|
|
have a <literal>JAIL</literal> option which must be enabled
|
|
for them to work correctly inside a jail.</para>
|
|
</tip>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-ezjail-update">
|
|
<title>Updating Jails</title>
|
|
|
|
<sect3 xml:id="jails-ezjail-update-os">
|
|
<title>Updating the Operating System</title>
|
|
|
|
<para>Because the basejail's copy of the userland is shared by
|
|
the other jails, updating the basejail automatically updates
|
|
all of the other jails. Either source or binary updates can
|
|
be used.</para>
|
|
|
|
<para>To build the world from source on the host, then
|
|
install it in the basejail, use:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin update -b</userinput></screen>
|
|
|
|
<para>If the world has already been compiled on the host,
|
|
install it in the basejail with:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin update -i</userinput></screen>
|
|
|
|
<para>Binary updates use &man.freebsd-update.8;. These
|
|
updates have the same limitations as if
|
|
&man.freebsd-update.8; were being run directly. The most
|
|
important one is that only -RELEASE versions of &os; are
|
|
available with this method. To update the basejail to the
|
|
latest patched release of the version of &os; on the host
|
|
computer, use:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin update -r</userinput></screen>
|
|
|
|
<para>After updating the basejail, &man.mergemaster.8; can be
|
|
run to update each jail's configuration files.</para>
|
|
|
|
<para>How to use &man.mergemaster.8; depends on the purpose
|
|
and trustworthiness of a jail. If a jail's services or
|
|
users are not trusted, then &man.mergemaster.8; should only
|
|
be run from within that jail:</para>
|
|
|
|
<example xml:id="jails-ezjail-update-mergemaster-untrusted">
|
|
<title>&man.mergemaster.8; on Untrusted Jail</title>
|
|
|
|
<para>Delete the link from the jail's
|
|
<filename>/usr/src</filename> into the basejail and
|
|
create a new <filename>/usr/src</filename> in the jail
|
|
as a mountpoint. Mount the host computer's
|
|
<filename>/usr/src</filename> read-only on the jail's
|
|
new <filename>/usr/src</filename> mountpoint:</para>
|
|
|
|
<screen>&prompt.root; <userinput>rm /usr/jails/<replaceable>jailname</replaceable>/usr/src</userinput>
|
|
&prompt.root; <userinput>mkdir /usr/jails/<replaceable>jailname</replaceable>/usr/src</userinput>
|
|
&prompt.root; <userinput>mount -t nullfs -o ro /usr/src /usr/jails/<replaceable>jailname</replaceable>/usr/src</userinput></screen>
|
|
|
|
<para>Get a console in the jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin console <replaceable>jailname</replaceable></userinput></screen>
|
|
|
|
<para>Inside the jail, run <command>mergemaster</command>.
|
|
Then exit the jail console:</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /usr/src</userinput>
|
|
&prompt.root; <userinput>mergemaster -U</userinput>
|
|
&prompt.root; <userinput>exit</userinput></screen>
|
|
|
|
<para>Finally, unmount the jail's
|
|
<filename>/usr/src</filename>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>umount /usr/jails/<replaceable>jailname</replaceable>/usr/src</userinput></screen>
|
|
</example>
|
|
|
|
<example xml:id="jails-ezjail-update-mergemaster-trusted">
|
|
|
|
<title>&man.mergemaster.8; on Trusted Jail</title>
|
|
|
|
<para>If the users and services in a jail are trusted,
|
|
&man.mergemaster.8; can be run from the host:</para>
|
|
|
|
<screen>&prompt.root; <userinput>mergemaster -U -D /usr/jails/<replaceable>jailname</replaceable></userinput></screen>
|
|
</example>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="jails-ezjail-update-ports">
|
|
<title>Updating Ports</title>
|
|
|
|
<para>The ports tree in the basejail is shared by the other
|
|
jails. Updating that copy of the ports tree gives the other
|
|
jails the updated version also.</para>
|
|
|
|
<para>The basejail ports tree is updated with
|
|
&man.portsnap.8;:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin update -P</userinput></screen>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-ezjail-control">
|
|
<title>Controlling Jails</title>
|
|
|
|
<sect3 xml:id="jails-ezjail-control-stop-start">
|
|
<title>Stopping and Starting Jails</title>
|
|
|
|
<para><application>ezjail</application> automatically starts
|
|
jails when the computer is started. Jails can be manually
|
|
stopped and restarted with <command>stop</command> and
|
|
<command>start</command>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin stop <replaceable>sambajail</replaceable></userinput>
|
|
Stopping jails: sambajail.</screen>
|
|
|
|
<para>By default, jails are started automatically when the
|
|
host computer starts. Autostarting can be disabled
|
|
with <command>config</command>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin config -r norun <replaceable>seldomjail</replaceable></userinput></screen>
|
|
|
|
<para>This takes effect the next time the host computer is
|
|
started. A jail that is already running will not be
|
|
stopped.</para>
|
|
|
|
<para>Enabling autostart is very similar:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin config -r run <replaceable>oftenjail</replaceable></userinput></screen>
|
|
</sect3>
|
|
|
|
<sect3 xml:id="jails-ezjail-control-backup">
|
|
<title>Archiving and Restoring Jails</title>
|
|
|
|
<para>Use <command>archive</command> to create a
|
|
<filename>.tar.gz</filename> archive of a jail. The file
|
|
name is composed from the name of the jail and the current
|
|
date. Archive files are written to the archive directory,
|
|
<filename>/usr/jails/ezjail_archives</filename>. A
|
|
different archive directory can be chosen by setting
|
|
<varname>ezjail_archivedir</varname> in the configuration
|
|
file.</para>
|
|
|
|
<para>The archive file can be copied elsewhere as a backup, or
|
|
an existing jail can be restored from it with
|
|
<command>restore</command>. A new jail can be created from
|
|
the archive, providing a convenient way to clone existing
|
|
jails.</para>
|
|
|
|
<para>Stop and archive a jail named
|
|
<literal>wwwserver</literal>:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin stop <replaceable>wwwserver</replaceable></userinput>
|
|
Stopping jails: wwwserver.
|
|
&prompt.root; <userinput>ezjail-admin archive <replaceable>wwwserver</replaceable></userinput>
|
|
&prompt.root; <userinput>ls /usr/jails/ezjail-archives/</userinput>
|
|
wwwserver-201407271153.13.tar.gz</screen>
|
|
|
|
<para>Create a new jail named
|
|
<literal>wwwserver-clone</literal> from the archive created
|
|
in the previous step. Use the <filename>em1</filename>
|
|
interface and assign a new <acronym>IP</acronym> address to
|
|
avoid conflict with the original:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin create -a /usr/jails/ezjail_archives/wwwserver-201407271153.13.tar.gz <replaceable>wwwserver-clone</replaceable> 'lo1|127.0.3.1,em1|192.168.1.51'</userinput></screen>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="jails-ezjail-example-bind">
|
|
<title>Full Example: <application>BIND</application> in a
|
|
Jail</title>
|
|
|
|
<para>Putting the <application>BIND</application>
|
|
<acronym>DNS</acronym> server in a jail improves security by
|
|
isolating it. This example creates a simple caching-only name
|
|
server.</para>
|
|
|
|
<itemizedlist xml:id="jails-ezjail-example-bind-assumptions">
|
|
<listitem>
|
|
<para>The jail will be called
|
|
<literal>dns1</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The jail will use <acronym>IP</acronym> address
|
|
<literal>192.168.1.240</literal> on the host's
|
|
<literal>re0</literal> interface.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The upstream <acronym>ISP</acronym>'s DNS servers are
|
|
at <literal>10.0.0.62</literal> and
|
|
<literal>10.0.0.61</literal>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The basejail has already been created and a ports tree
|
|
installed.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<example xml:id="jails-ezjail-example-bind-steps">
|
|
<para>Create a cloned loopback interface by adding a line to
|
|
<filename>/etc/rc.conf</filename>:</para>
|
|
|
|
<programlisting>cloned_interfaces="${cloned_interfaces} lo1"</programlisting>
|
|
|
|
<para>Immediately create the new loopback interface:</para>
|
|
|
|
<screen>&prompt.root; <userinput>service netif cloneup</userinput>
|
|
Created clone interfaces: lo1.</screen>
|
|
|
|
<para>Create the jail:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin create dns1 'lo1|127.0.2.1,re0|192.168.1.240'</userinput></screen>
|
|
|
|
<para>Start the jail, connect to a console running on it, and
|
|
perform some basic configuration:</para>
|
|
|
|
<screen>&prompt.root; <userinput>ezjail-admin start dns1</userinput>
|
|
&prompt.root; <userinput>ezjail-admin console dns1</userinput>
|
|
&prompt.root; <userinput>passwd</userinput>
|
|
Changing local password for root
|
|
New Password:
|
|
Retype New Password:
|
|
&prompt.root; <userinput>tzsetup</userinput>
|
|
&prompt.root; <userinput>sed -i .bak -e '/adjkerntz/ s/^/#/' /etc/crontab</userinput>
|
|
&prompt.root; <userinput>sed -i .bak -e 's/127.0.0.1/127.0.2.1/g; s/localhost.my.domain/dns1.my.domain dns1/' /etc/hosts</userinput></screen>
|
|
|
|
<para>Temporarily set the upstream <acronym>DNS</acronym>
|
|
servers in <filename>/etc/resolv.conf</filename> so ports
|
|
can be downloaded:</para>
|
|
|
|
<programlisting>nameserver 10.0.0.62
|
|
nameserver 10.0.0.61</programlisting>
|
|
|
|
<para>Still using the jail console, install
|
|
<package role="port">dns/bind99</package>.</para>
|
|
|
|
<screen>&prompt.root; <userinput>cd /usr/ports/dns/bind99</userinput>
|
|
&prompt.root; <userinput>make -C /usr/ports/dns/bind99 install clean</userinput></screen>
|
|
|
|
<para>Configure the name server by editing
|
|
<filename>/usr/local/etc/namedb/named.conf</filename>.</para>
|
|
|
|
<para>Create an Access Control List (<acronym>ACL</acronym>)
|
|
of addresses and networks that are permitted to send
|
|
<acronym>DNS</acronym> queries to this name server. This
|
|
section is added just before the <literal>options</literal>
|
|
section already in the file:</para>
|
|
|
|
<programlisting>...
|
|
// or cause huge amounts of useless Internet traffic.
|
|
|
|
acl "trusted" {
|
|
192.168.1.0/24;
|
|
localhost;
|
|
localnets;
|
|
};
|
|
|
|
options {
|
|
...</programlisting>
|
|
|
|
<para>Use the jail <acronym>IP</acronym> address in the
|
|
<literal>listen-on</literal> setting to accept
|
|
<acronym>DNS</acronym> queries from other computers on the
|
|
network:</para>
|
|
|
|
<programlisting> listen-on { 192.168.1.240; };</programlisting>
|
|
|
|
<para>A simple caching-only <acronym>DNS</acronym> name server
|
|
is created by changing the <literal>forwarders</literal>
|
|
section. The original file contains:</para>
|
|
|
|
<programlisting>/*
|
|
forwarders {
|
|
127.0.0.1;
|
|
};
|
|
*/</programlisting>
|
|
|
|
<para>Uncomment the section by removing the
|
|
<literal>/*</literal> and <literal>*/</literal> lines.
|
|
Enter the <acronym>IP</acronym> addresses of the upstream
|
|
<acronym>DNS</acronym> servers. Immediately after the
|
|
<literal>forwarders</literal> section, add references to the
|
|
<literal>trusted</literal> <acronym>ACL</acronym> defined
|
|
earlier:</para>
|
|
|
|
<programlisting> forwarders {
|
|
10.0.0.62;
|
|
10.0.0.61;
|
|
};
|
|
|
|
allow-query { any; };
|
|
allow-recursion { trusted; };
|
|
allow-query-cache { trusted; };</programlisting>
|
|
|
|
<para>Enable the service in
|
|
<filename>/etc/rc.conf</filename>:</para>
|
|
|
|
<programlisting>named_enable="YES"</programlisting>
|
|
|
|
<para>Start and test the name server:</para>
|
|
|
|
<screen>&prompt.root; <userinput>service named start</userinput>
|
|
wrote key file "/usr/local/etc/namedb/rndc.key"
|
|
Starting named.
|
|
&prompt.root; <userinput>/usr/local/bin/dig @192.168.1.240 freebsd.org</userinput></screen>
|
|
|
|
<para>A response that includes</para>
|
|
|
|
<screen>;; Got answer;</screen>
|
|
|
|
<para>shows that the new <acronym>DNS</acronym> server is
|
|
working. A long delay followed by a response
|
|
including</para>
|
|
|
|
<screen>;; connection timed out; no servers could be reached</screen>
|
|
|
|
<para>shows a problem. Check the configuration settings and
|
|
make sure any local firewalls allow the new
|
|
<acronym>DNS</acronym> access to the upstream
|
|
<acronym>DNS</acronym> servers.</para>
|
|
|
|
<para>The new <acronym>DNS</acronym> server can use itself for
|
|
local name resolution, just like other local computers. Set
|
|
the address of the <acronym>DNS</acronym> server in the
|
|
client computer's
|
|
<filename>/etc/resolv.conf</filename>:</para>
|
|
|
|
<programlisting>nameserver 192.168.1.240</programlisting>
|
|
|
|
<para>A local <acronym>DHCP</acronym> server can be configured
|
|
to provide this address for a local <acronym>DNS</acronym>
|
|
server, providing automatic configuration on
|
|
<acronym>DHCP</acronym> clients.</para>
|
|
</example>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|