A service jail puts one rc.d service, such as Nginx, inside its own small jail with one line in rc.conf. You do not need a jail folder, a jail.conf file, or a second copy of FreeBSD. In this guide, you will learn to build a FreeBSD 15 service jail for Nginx, choose between pkgbase and distribution sets, open the ports with pf, and test the isolation.
How to Isolate Nginx with a FreeBSD 15 Service Jail
Table of Contents
- Prerequisites
- FreeBSD Jail Types: Service, Thick, and Thin
- How to Choose a FreeBSD Base System Method
- Install Nginx on the Host
- Deploy a FreeBSD 15 Service Jail for Nginx
- Allow Nginx Traffic Through the pf Firewall
- Verify the FreeBSD Service Jail Isolation
- Update the FreeBSD Host and Nginx
- Fix Nginx Bind and Network Problems on FreeBSD
- Conclusion

Prerequisites
Before you build a FreeBSD 15 service jail for Nginx, you need:
- A fresh FreeBSD 15.1 server with root access and console access.
- A non-root admin user and key-based SSH.
- A public IPv4 address.
- Ports 80 and 443 free on the host.
If you need a server, a Linux VPS plan from PerLod lists FreeBSD as an available system. Check that version 15.1 is offered for your plan before you order.
If you have not done the base setup yet, you can follow our FreeBSD 15.1 setup guide.
FreeBSD Jail Types: Service, Thick, and Thin
This table shows how a FreeBSD 15 service jail for Nginx differs from the older jail types. All three use the FreeBSD jail system. The difference is in the files and the setup work.
A service jail is not a small virtual machine. It shares the host file system, so it does not hide /etc or /home. It limits what the service can see and do. It cannot see other processes, and it only gets the network access you give it.
Use a service jail when the daemon should run on the host with less power. Use a thick or thin jail when you need a separate file system, its own IP, or its own packages.
How to Choose a FreeBSD Base System Method
Your FreeBSD 15 service jail for Nginx uses the host's base system, so this choice affects the whole server. You make it once. There are two ways to install and update the base system:
pkgbase: the base system is a set of packages from the FreeBSD-base repository. You update it withpkg. The 15.1 installer usespkgbaseby default, and the old distribution-set install is still available.- Distribution sets: the classic
base.txzinstall. You update it withfreebsd-update.
You can check which one your server uses with the commands below:
If you see packages such as FreeBSD-runtime, the host uses pkgbase. If the list is empty, it uses distribution sets. Do not mix the two update tools on one system. For a new server, pkgbase is the better choice because one tool updates both the base system and Nginx.
Install Nginx on the Host
Because the service jail uses the host files, you must install Nginx in the normal way:
Then, create a test page so you can see the result later:
The nginx -t command must report that the syntax is OK. The default config listens on port 80 and runs workers as the www user.
Deploy a FreeBSD 15 Service Jail for Nginx
At this point, you must set the service variables with sysrc. The nginx_svcj setting turns on the jail. The nginx_svcj_options setting gives it network access. Nginx does not ship a default network option, so you must set it:
The net_basic option allows IPv4 and IPv6 access and lets the jail bind to ports below 1024, such as 80 and 443. Without it, the service gets no network access.
Now start Nginx and look at the jail with:
You should see a jail named svcj-nginx with the path /. This is the FreeBSD 15 service jail for Nginx you just created, and rc.d built it for you at start time.
Limit the Jail to One IP
By default, the jail can see every address on the host. To limit it to one IPv4 address, you can use netv4 and nginx_svcj_ipaddrs. Replace the example address with your own:
Make sure Nginx does not listen on an address that the jail cannot see. With netv4, the jail only sees the IPv4 address in the list. Note that netv4 and netv6 cannot be combined. Use net_basic for both.
Allow Nginx Traffic Through the pf Firewall
A FreeBSD 15 service jail for Nginx uses the same network as the host. So the host's pf firewall controls its traffic, and you do not need NAT or rdr rules. A thick or thin jail on a private network works differently and needs those rules.
For a full walkthrough of pf rules, you can read our FreeBSD pf firewall setup guide. Below is a short ruleset that is enough for this web server.
Keep your server console open. A wrong rule can lock you out of SSH. Run route -n get default to find your network interface, and change vtnet0 below if yours has a different name:
No output from pfctl -nf means the syntax is correct. If your provider uses DHCP, you must add a rule that allows DHCP replies. Then, enable pf and load the rules:
Also, check that your provider firewall allows TCP ports 80 and 443.
Verify the FreeBSD Service Jail Isolation
Now you can verify that your FreeBSD 15 service jail for Nginx works and is isolated. First, you must test that Nginx answers. Run this on the server and then from another computer:
You should get an HTTP 200 reply. Then, check the jail:
The Nginx processes should show the jail ID of svcj-nginx, not 0. The master process runs as root, and the workers run as www.
Now enter the jail and check what you can see:
You should only see Nginx processes. SSH, the shell, and other services are not visible. This proves the process isolation.
Note: Keep in mind that the file system is shared. If someone hacks Nginx, they can still read any file the www user can read. You must set private files to mode 600 or 640 and give them a different owner. Also, keep your Nginx config clean.
Update the FreeBSD Host and Nginx
Upgrading a FreeBSD 15 service jail for Nginx is simple. There is no separate jail root to rebuild. You must update the host, then restart the service.
To update Nginx, you can run these commands:
If your host uses pkgbase, update the base system with these commands:
If your host uses distribution sets, update the base system with these commands:
Read the prompts before you accept any change. Before a major upgrade, read the official upgrade notes for your release. After the reboot, run freebsd-version -kru and jls to confirm the jail is back.
Later, you may add a thick or thin jail on a pkgbase host. Do this only if you need a separate file system. To install the jail's base system, run:
To update it, run:
Fix Nginx Bind and Network Problems on FreeBSD
Most problems come from the _svcj_options setting or the IP list. You can use this table to find the cause.
You can run these commands to find the problem:
If another program on the host already listens on all addresses for a port, Nginx cannot use that port. Run sockstat and look for *:80.
If Nginx must connect to other servers, for example as a reverse proxy, the jail needs net_basic or netv4. Also, pf must allow outgoing traffic.
If your proxy only talks to a backend on the same server, use 127.0.0.1. The rule set skip on lo0 already allows this traffic.
To turn off the service jail, run these commands:
Conclusion
At this point, you have a working FreeBSD 15 service jail for Nginx. Nginx runs in its own jail named svcj-nginx. It only gets the network access you gave it, and the host pf firewall filters its traffic.
A service jail limits processes and privileges, but it does not hide files. Use pkgbase for easy updates. Use a thick or thin jail when you need a separate file system.
If you plan to run many jails or heavy traffic, a physical server gives you full control of CPU, disks, and network. You can look at PerLod dedicated server hosting after you confirm FreeBSD support with the provider.
For more details about jail types, you can check the FreeBSD docs on jails.
It is a jail that rc.d creates for one service. You can turn it on with name_svcj=YES in rc.conf.
No. Everything is set in rc.conf with sysrc.
Use pkgbase on new servers. Use freebsd-update only if the host was installed from distribution sets.
Yes. Base services are ready for it, and most others work with net_basic.