Add new sysutils/ezjail section. Reviewed on IRC, -doc, and with

individuals through email.  Particular thanks to Glen Barber for his
experience and patience.
This commit is contained in:
Warren Block 2014-08-23 17:54:21 +00:00
parent 53814f7852
commit c405269a35
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=45496

View file

@ -591,9 +591,10 @@ jail_<replaceable>www</replaceable>_devfs_enable="YES" # mount devfs in
<note>
<para>Simpler solutions exist, such as
<package>sysutils/ezjail</package>, which provides an easier
method of administering &os; jails and is not as sophisticated
as this setup.</para>
<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>
@ -982,4 +983,637 @@ jail_www_devfs_enable="YES"</programlisting>
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;&nbsp;10-STABLE, the latest
RELEASE version of &os;&nbsp;-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;&nbsp;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>