3 minutes, 25 seconds
Host Your Own Services With FreeBSD Jail: Initial Jail Setup

In previous post we have prepared our jail host to be jail-friendly. In this one we will set up our first jail.

We are writing update to this article, check back soon.

Create Required Folders

All of our jails will reside under /usr/jail. This directory does not exist on vanilla FreeBSD installation therefore we need to create it.

mkdir /usr/jail

Also, bsdinstall, script which we will be using to create our jails, fetches jailhost's OS version for jail, and puts it into /usr/freebsd-dist. However, we want to put distribution files into separate folders for each OS version. Let's create folder for 13.0-RELEASE amd64:

mkdir -p /usr/freebsd-dist/13_0:x86:64

Setting Environment For bsdinstall

We will now create environment file which we will be sourcing every time we want to install 13.0-RELEASE amd64 jail, with the following contents:

# jailhost.example.org:/root/bsdinstall-13_0:x86:64.env

setenv BSDINSTALL_DISTSITE "https://download.freebsd.org/ftp/releases/amd64/amd64/13.0-RELEASE/"
setenv BSDINSTALL_DISTDIR "/usr/freebsd-dist/13_0:x86.64/"

Jail Creation

It is time to install our first jail. In next chapter about Poudriere, this jail will become our custom package repository, therefore it is appropriate to name it pkg.example.org.

source ~/bsdinstall-13_0:x86:64.env
bsdinstall jail /usr/jail/pkg.example.org

Familiar bsdinstall wizard will:

  • ask for optional components to install (I de-select them all)
  • fetch and extract distribution files
  • ask for root password (it should be different from the one on jail host)
  • ask for any services to be started at boot time (I de-select them all)
  • ask to add any users (I add user marko with default UID of 1001, default group marko, additional groups wheel and operator, tcsh as shell, and strong password)

Passwords should be different between jails, and most importantly between jail host and jails.

Jail Deletion

Not that we need to delete our jail immediately after we created it, but if anything went wrong we can just wipe it and start again. As some files inside the jail have immutable flag set, their deletion with rm -rf will fail. In order to be able to delete jail this flag needs to be removed first.

chflags -R noschg /usr/jail/pkg.example.org
rm -rf /usr/jail/pkg.example.org

jail.conf Creation

All the parameters of our jails will be set through /etc/jail.conf:

Make sure to always edit highlighted lines according to your environment.

You can safely use copy button in code blocks - it will copy only text and commands, not line numbers and terminal prompts.

# jailhost.example.org:/etc/jail.conf

path           = "/usr/jail/${host.hostname}";
exec.start     = "/bin/sh /etc/rc";
exec.stop      = "/bin/sh /etc/rc.shutdown";

pkg_example_org {
  host.hostname    = pkg.example.org;
  host.domainname  = example.org;
  ip4.addr         = 'lo1|';
  ip4.addr        += 'em0|';

In order to start jails at host's boot time, I need to enable the feature in host's rc.conf:

sysrc jail_enable="YES"

Jails are started, stopped or restarted in same fashion as any other services in FreeBSD, with service <servicename> (start|stop|restart). Without additional arguments, this would start / stop / restart all the jails declared in jail.conf. For starting / stopping / restarting single jail, we need to pass its name as an argument to the command.

Let's start our first jail:

service jail start pkg.example.org

We can see the list of all running jails with jls command:


...which should show output similar to:

JID  IP Address      Hostname                      Path
  1      pkg.example.org               /usr/jail/pkg.example.org

Assuming our jail is running we can log into it by passing jid and path to shell executable to jexec command:

jexec 1 /bin/tcsh

Notice prompt changed

freebsd-version -u

Some admins don't like to enable ssh access to jails. Instead, they ssh exclusively to host, and then jexec to jails. As for myself, I like to have ssh access to my jails. Throughout this tutorial series, I will be logging into my jails by means of ssh, but before enabling it in jails' rc.conf, do not forget to edit their sshd_config so that it binds only to specified IP address, as described in previous chapter.

All of my jails start with the following rc.conf as default template:

# pkg.example.org:/etc/rc.conf

cron_flags="$cron_flags -J 15"

We can exit jail's shell and return to host's shell by typing exit. After jail restart (check above if you forgot how), we can ssh into it and continue with its configuration and usage as usual.