FreeBSD/jails.md

Thu, 07 Sep 2017 10:36:42 +0200

author
Stéphane P.
date
Thu, 07 Sep 2017 10:36:42 +0200
changeset 9
e542763af261
parent 7
c32b5c002aad
child 10
8aea03aa0825
permissions
-rw-r--r--

FreeBSD: change place of the warning in poudriere.md

FreeBSD jails howto
===================

This guide will let you create your own jails for FreeBSD.

In this guide, we will build jails from sources.

What are jails?
---------------

Jails are confined environments that run on host kernels. They are similar to
chroots but have much more features.

Fetching source tree
--------------------

In this guide we will assume that we are running FreeBSD 11.1-RELEASE, to fetch
the source tree, you need this following URL:

    svn://svn.FreeBSD.org/base/releng/<VERSION>

In our case:

    svnlite co svn://svn.FreeBSD.org/base/releng/11.1 /usr/src

Customizing the build
---------------------

The source tree can be built with and without a lot of options. This is tweaked
in the `src.conf(5)` file.

Removing options will let you build lighter jails, for example I use the
following one:

    # /etc/src.conf
    WITHOUT_APM=yes
    WITHOUT_AMD=yes
    WITHOUT_AUTHPF=yes
    WITHOUT_BLUETOOTH=yes
    WITHOUT_CTM=yes
    WITHOUT_FLOPPY=yes
    WITHOUT_GAMES=yes
    WITHOUT_IPFILTER=yes
    WITHOUT_IPFW=yes
    WITHOUT_IPX=yes
    WITHOUT_NDIS=yes
    WITHOUT_OBJC=yes
    WITHOUT_PORTSNAP=yes
    WITHOUT_PPP=yes
    WITHOUT_PROFILE=yes
    WITHOUT_RESCUE=yes
    WITHOUT_WIRELESS=yes

See the manual page to know what they control.

Build the source
----------------

To build the source, use these commands:

    cd /usr/src
    make buildworld

Note: this only builds the source tree and does not install anything.

The jail template
-----------------

To avoid doing the same step again and again each time we build a jail, we will
create a template one that we will clone.

We will create that jail in **/jails/template** dataset.

    zfs create zroot/jails
    zfs create zroot/jails/template

And now install everything in that template directory.

    cd /usr/src
    make DESTDIR=/jails/template installworld
    make DESTDIR=/jails/template distribution

Bringing networking
-------------------

There are two ways to provide networking in jails, you can use real address IP
or using virtual interfaces. We will do the latter option using 10.0.0.x
addresses.

### Create a lo1 interface

Add the following into your **/etc/rc.conf**:

    # /etc/rc.conf
    cloned_interface="lo1"
    pf_enabled="YES"

### Enable NAT and pf

Then we add NAT support using pf, add the following into **/etc/pf.conf**:

Adjust **em0** to match your real interface.

    # /etc/pf.conf
    jails="10.0.0.0/24"
    
    set skip on { lo0, lo1 }
    nat on em0 from $jails to any -> (em0)

Now reboot or create your interface by hand.

Jail configuration in jail.conf(5)
----------------------------------

To configure jail, we will use the `jail.conf(5)` file located in
**/etc/jail.conf**.

The file supports basic variables expansion for shorter jail definitions.

### Common configuration

The following will apply to all jail.

    # /etc/jail.conf
    mount.devfs="1";
    interface="lo1";
    exec.start="sh /etc/rc";
    exec.stop="sh /etc/rc.shutdown";
    path="/jails/$name";

### Example with template configuration

For each jail, I recommend using the same value for the jail directory
(**/jails/name**) and the jail id (in **/etc/rc.conf**).

Configure our template jail to assign a hostname and address.

    # /etc/jail.conf
    template {
        ip4.addr="10.0.0.1";
        host.hostname="template.local";
    }

Enabling jails in rc.conf(5)
----------------------------

If you want to start all jails, just keep `jail_list` empty, otherwise fill it
with the wanted list.

    # /etc/rc.conf
    jail_enable="yes"

Now start the jail template:

    service jail start template

If everything is correct you should get the following output:

    JID  IP Address      Hostname                      Path
      1  10.0.0.1        template.local                /jails/template

Customizing jail template
-------------------------

Before cloning our template jail, first customize it by installing some packages
and change some settings.

### Install some packages

Note: each jail has its own package repository, you need to adjust
**jails/template/etc/pkg/** repository files if you want to use something else.

    pkg -j template install vim zsh

### Change locales

We use **en_US.UTF-8** to enable UTF-8 support. 

    vim /jails/template/etc/login.conf

In the `default:` class, add the following options before `umask:`, like this:

    :ignoretime@:\
    :lang=en_US.UTF-8:\
    :charset=UTF-8:\
    :umask=022:

Note: don't forget the antislash.

Now run:

    jexec template cap_mkdb /etc/login.conf

### Change root password (optional)

    jexec template passwd

### Change root shell (optional)

    jexec template pw usermod root -s /usr/local/bin/zsh

Template snapshot
-----------------

Now that we have set some common configuration in our template jail, create a
snapshot that we will clone each time we want a new jail.

### Snapshot the template

    zfs snapshot zroot/jails/template@11.1-20170829

You can list your snapshots like this:

    zfs list -t snapshot
    NAME                                       USED  AVAIL  REFER  MOUNTPOINT
    zroot/jails/template@11.1-20170829            0      -    23K  -

Example: web server
-------------------

Now that we have finished our template jail, let's create a new one for a basic
webserver.

### Clone the template

    zfs clone zroot/jails/template@11.1-20170829 zroot/jails/www

### Configure it in jail.conf(5)

Add the following to the **/etc/jail.conf**:

    # /etc/jail.conf
    www {
        host.hostname="www.local";
        ip4.addr="10.0.0.2";
    }

Start it using `service jail start www`

### Enable port redirection

Web servers usually bind on ports 80 (HTTP) and 443 (HTTPS), configure the
**/etc/pf.conf** to redirect those ports to the jail.

We use variables for better understanding.

    # /etc/pf.conf (whole file)
    jails="10.0.0.0/24"
    
    jail_www="10.0.0.2"
    ports_www="{ 80, 443 }"
    
    nat on em0 from $jails to any -> (em0)
    rdr pass on em0 proto tcp to port $ports_www -> $jail_www

Reload the rules

    service pf reload

### Install nginx

Install `www/nginx` in the www jail:

    pkg -j www install nginx

Enable it in `rc.conf(5)` file.

    # /jails/www/etc/rc.conf
    nginx_start="YES"

And start it.

    jexec www service start nginx

Now, any attempt to connect to your machine should redirect to the nginx jail.

mercurial