FreeBSD exposes two main api for managing jails. The old (and easier) one is based on the jail() function.

It is available since FreeBSD 4 and allows you to set the rootfs, the hostname and one ore more ipv4/ipv6 addresses

Two options are needed for running a uWSGI instance in a jail: –jail and –jail-ip4/–jail-ip6 (effectively they are 3 if you use IPv6)

--jail<rootfs>[hostname][jailname]

--jail-ip4<address> (can be specified multiple times)

--jail-ip6<address> (can be specified multiple times)

Showing how to create the rootfs for your jail is not the objective of this document, but personally i hate rebuilding from sources, so generally
i simply explode the base.tgz file from an official repository and chroot() to it to make the fine tuning.

An important thing you have to remember is that the ip addresses you attach to a jail must be available in the system (as aliases). As always we tend to abuse uWSGI facilities.
In our case the –exec-pre-jail hook will do the trick

[uwsgi]; create the jail with /jails/001 as rootfs and 'foobar' as hostnamejail=/jails/001 foobar; create the alias on 'em0'exec-pre-jail=ifconfig em0 192.168.0.40 alias; attach the alias to the jailjail-ip4=192.168.0.40; bind the http-socket (we are now in the jail)http-socket=192.168.0.40:8080; load the application (remember we are in the jail)wsgi-file=myapp.wsgi; drop privilegesuid=kratosgid=kratos; common optionsmaster=trueprocesses=2

FreeBSD 8 introdiced a new advanced api for managing jails. Based on the jail_set() syscall, libjail exposes dozens of features
and allows fine-tuning of your jails. To use the new api you need the –jail2 option (aliased as –libjail)

--jail2<key>[=value]

Each –jail2 option maps 1:1 with a jail attribute so you can basically tune everything !

[uwsgi]; create the jail with /jails/001 as rootfsjail2=path=/jails/001; set hostname to 'foobar'jail2=host.hostname=foobar; create the alias on 'em0'exec-pre-jail=ifconfig em0 192.168.0.40 alias; attach the alias to the jailjail2=ip4.addr=192.168.0.40; bind the http-socket (we are now in the jail)http-socket=192.168.0.40:8080; load the application (remember we are in the jail)wsgi-file=myapp.wsgi; drop privilegesuid=kratosgid=kratos; common optionsmaster=trueprocesses=2

The /dev filesystem is not mounted in the jail, but you can need it for literally hundreds of reasons.

Two main approaches are available: mounting it in the /dev/ directory of the roots before creating the jail, or allowing the jail to mount it

[uwsgi]; avoid re-mounting the file system every timeif-not-exists=/jails/001/dev/zero exec-pre-jail = mount -t devfs devfs /jails/001/devendif=; create the jail with /jails/001 as rootfsjail2=path=/jails/001; set hostname to 'foobar'jail2=host.hostname=foobar; create the alias on 'em0'exec-pre-jail=ifconfig em0 192.168.0.40 alias; attach the alias to the jailjail2=ip4.addr=192.168.0.40; bind the http-socket (we are now in the jail)http-socket=192.168.0.40:8080; load the application (remember we are in the jail)wsgi-file=myapp.wsgi; drop privilegesuid=kratosgid=kratos; common optionsmaster=trueprocesses=2

or (allow the jail itself to mount it)

[uwsgi]; create the jail with /jails/001 as rootfsjail2=path=/jails/001; set hostname to 'foobar'jail2=host.hostname=foobar; create the alias on 'em0'exec-pre-jail=ifconfig em0 192.168.0.40 alias; attach the alias to the jailjail2=ip4.addr=192.168.0.40; allows mount of devfs in the jailjail2=enforce_statfs=1jail2=allow.mountjail2=allow.mount.devfs; ... and mount itif-not-exists=/dev/zero exec-post-jail = mount -t devfs devfs /devendif=; bind the http-socket (we are now in the jail)http-socket=192.168.0.40:8080; load the application (remember we are in the jail)wsgi-file=myapp.wsgi; drop privilegesuid=kratosgid=kratos; common optionsmaster=trueprocesses=2

Reloading (or binary patching) is a bit annoying to manage as uWSGI need to re-exec itself, so you need a copy of the binary, plugins and the config file
in your jail (unless you can sacrifice graceful reload and simply delegate the Emperor to respawn the instance)

Another approach is (like with devfs) mounting the directory with the uwsgi binary (and the eventual plugins) in the jail itself and instruct
uWSGI to use this new path with –binary-path

Each jail can be referenced by a unique name (optional) or its “jid”. This is similar to a “pid”, as you can use it
to send commands (and updates) to an already running jail. The –jidfile <file> option allows you to store the jid in a file
for use with external applications.