Run isolated services in FreeBSD jails
Jails are FreeBSD's original — and still excellent — isolation primitive: a service runs in its own filesystem and process space with its own IP, sharing the host kernel with almost no overhead. It's the "one clean environment per service" model, years before containers made it fashionable, and it's a genuine reason to pick FreeBSD. This gets you jails running with Bastille, the friendliest management tool.
Install and bootstrap Bastille
pkg install bastille
sysrc bastille_enable=YES
bastille bootstrap 14.2-RELEASE # match your host release
Give jails an internal network
Put jails on a private range behind the host and let pf handle NAT and port forwarding. Create a loopback for them and add NAT to /etc/pf.conf:
sysrc cloned_interfaces+=lo1
sysrc ifconfig_lo1="inet 10.10.0.1/24"
service netif cloneup
# in /etc/pf.conf, then: pfctl -f /etc/pf.conf
nat on $ext_if from 10.10.0.0/24 to any -> ($ext_if)
rdr pass on $ext_if proto tcp to port 80 -> 10.10.0.10 port 80
rdr pass on $ext_if proto tcp to port 443 -> 10.10.0.10 port 443
Create and use a jail
bastille create web 14.2-RELEASE 10.10.0.10 lo1
bastille pkg web install nginx
bastille sysrc web nginx_enable=YES
bastille service web nginx start
bastille console web # drop into a shell inside the jail
Each jail is a clean slate: a compromised or broken service in one jail can't touch the others or the host. Snapshot the whole VPS from the portal before big changes and you have instant rollback for the lot.
Why jails on a VPS
You get container-style separation — a database jail, a web jail, a mail jail — without a second layer of virtualization, all on one FreeBSD VPS with full root. Pair them with the pf firewall for network isolation and you have a tidy, defensible multi-service host.