FreeBSD jails are a lightweight, secure way to isolate processes and services, similar to Linux containers but older and natively integrated into the FreeBSD kernel. With jails, you can run multiple independent environments on a single host – each with its own users, files, network stack, and processes.
In this post, we’ll walk through creating and configuring a jail on FreeBSD 14.3-RELEASE arm64 from scratch, and then demonstrate installing and running Nginx inside it.
Why Use Jails?
Jails are useful for:
- Running services (like Nginx, PostgreSQL, or BIND) in isolation.
- Improving security by containing applications.
- Testing and development without affecting the host.
- Lightweight virtualization without the overhead of VMs.
Step 1: Enable Jail Support
FreeBSD includes jail functionality by default. Enable it so it starts on boot:
sysrc jail_enable="YES"
Step 2: Create a Jail Directory
We need a root filesystem for the jail. First, create a directory:
mkdir -p /usr/jails/myjail
Step 3: Fetch the Base System for arm64
Since our host is FreeBSD 14.3-RELEASE arm64, fetch the matching base system:
fetch https://download.freebsd.org/ftp/releases/arm64/aarch64/14.3-RELEASE/base.txz
Extract it into the jail directory:
tar -xpf base.txz -C /usr/jails/myjail
Step 4: Configure the Jail
Add a jail definition in /etc/jail.conf
:
myjail {
host.hostname = myjail.local;
path = /usr/jails/myjail;
ip4.addr = 192.168.1.100;
interface = em0;
persist;
mount.devfs;
allow.raw_sockets = 1;
}
Step 5: Start the Jail
Now start the jail:
service jail start myjail
Check if it’s running:
jls
root@freebsd:~ # jls
JID IP Address Hostname Path
4 192.168.1.100 myjail.local /usr/jails/myjail
Step 6: Enter the Jail
To access the jail, use:
jexec myjail /bin/sh
Step 7: Install Nginx Inside the Jail
First, bootstrap the package manager:
pkg bootstrap
Then install Nginx:
pkg install nginx
Enable Nginx to start on jail boot:
sysrc nginx_enable="YES"
Start the service:
service nginx start
Step 8: Test Nginx with curl
From inside the jail:
curl http://127.0.0.1
You should see the Nginx default welcome page HTML.
From the host system (replace with your jail IP):
curl http://192.168.1.100
If everything is configured correctly, you’ll get the same response.
Optional: Share the Host’s IP Instead of Assigning a New One
By default, jails are usually given their own IP address (e.g., ip4.addr = em0|192.168.1.100
).
However, you might want your jail to share the host’s IP and simply run services on a different port (similar to how Docker containers can map ports).
This can be done with the ip4=inherit
option.
1. Configure Jail to Inherit the Host IP
Edit /etc/jail.conf
and update your jail configuration:
myjail {
path = /usr/jails/myjail;
host.hostname = myjail.local;
ip4 = inherit; # Share host’s IP instead of assigning a new one
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
}
2. Configure Nginx to Listen on a Different Port
Since both the host and jail now share the same IP, you need to avoid port conflicts.
For example, configure nginx in the jail to listen on port 8080:
server {
listen 8080;
server_name localhost;
location / {
root /usr/local/www/nginx;
index index.html;
}
}
Restart nginx inside the jail:
service nginx restart
3. Test the Setup
On the host machine:
curl http://127.0.0.1:8080
Or from another machine on the network, replacing <host-ip>
with the actual IP of your host:
curl http://<host-ip>:8080
With this setup:
- The host keeps its SSH service accessible (default port 22).
- The jail shares the host’s IP but exposes nginx on port 8080 (or another free port of your choice).
Step 9: Manage Jails
- Stop a jail:
service jail stop myjail
- Restart a jail:
service jail restart myjail
- List running jails:
jls
Optional: Use iocage
If you want an easier jail manager, install iocage
Example usage:
iocage fetch release=14.3-RELEASE
iocage create -r 14.3-RELEASE -n webjail ip4_addr="em0|192.168.1.101/24"
iocage start webjail
iocage
handles fetching the correct base system, simplifying jail lifecycle management.
With just a few steps, you can set up a working jail on FreeBSD 14.3 arm64. Jails are secure, lightweight, and flexible – perfect for running multiple isolated environments on the same machine.
In this example, we built a jail, installed Nginx, and successfully tested it with curl
. Whether you manage jails manually or with iocage
, FreeBSD makes it straightforward to create safe, container-like environments for your services.