This section demonstrates a minimal, reproducible workflow using
jailmgr, jailctl, and NetBSD base components.
The example provisions a constrained HTTP service inside a jail, starts it, inspects runtime state, and exposes metrics.
1. Bootstrap
Prepare the host for jail operation.
This step:
- Loads the
secmodel_jailkernel module - Ensures it is configured for automatic loading on boot
- Prepares base filesystem layers
- Creates default configuration files
- Initializes the jail data directory layout
2. Create Jail
Create a jail named web with:
- HTTP daemon bound to port 8080
- Medium hardening profile
- Reserved listening port 8080
- Structured logging
vhost# jailmgr create -a -x '/usr/libexec/httpd -I 8080 -X -f -s /var/www/mysite' -l medium -r 8080 -f local3 -o info -e err -t jail-web web
Created jail web
vhost#
3. Ephemeral Provisioning
Execute commands inside the jail from the host, without altering its persistent configuration.
The jail is entered temporarily, the commands are run, and control returns to the host.
vhost# jailmgr apply --ephemeral web <<'APPLY'
mkdir -p /var/www/mysite
echo "<html>Hello NetBSD!</html>" > /var/www/mysite/index.html
APPLY
4. Start All Jails
Each jail configuration contains an autostart setting
that can be enabled or disabled individually.
The --all option operates only on jails where autostart is active.
vhost# jailmgr start --all
Started jail web
vhost#
5. Supervision Model
When started in supervise mode, jailctl daemonizes itself on the host
and becomes the parent process for the workload running inside the jail.
All processes started within the jail are descendants of the
jailctl supervise process.
From the host perspective, these processes remain fully visible in the standard process table. There is no hidden runtime or separate process namespace.
Host process tree:
vhost# ps axd
....
8252 ? Ss 0:00.00 |-- jailctl: jailctl supervise jail=web jid=3
6488 ? Ss 0:00.01 | `-- /usr/libexec/httpd -I 8080 -X -f -s /var/www/mysite
Enter jail context:
vhost# jailctl exec web
vhost# whoami
root
vhost# ps axd
PID TTY STAT TIME COMMAND
6488 ? Is 0:00.01 /usr/libexec/httpd -I 8080 -X -f -s /var/www/mysite
7117 pts/1 S 0:00.01 /bin/sh -i
5572 pts/1 O+ 0:00.00 - ps -axd
vhost#
Inside the jail context, even the root user can only see processes belonging to that jail.
Cross-jail process visibility is denied by the kernel. The host context (jid 0) remains the only global view.
6. Runtime Statistics
Snapshot telemetry per jail is maintained inside the kernel and exposed through the control interface.
vhost# jailctl stats
ID NAME CPU1S CPU10S PROC REFS VMEM
3 web 0 0.0 1 2 154025984
7. Prometheus-Compatible Metrics Endpoint
jailctl stats can emit Prometheus-compatible metrics.
The -P flag switches to Prometheus exposition format.
The -h flag prepends a minimal HTTP header.
This makes it possible to expose the metrics endpoint using only
base system facilities (for example via inetd), without requiring
a dedicated exporter daemon.
vhost# jailctl stats -P -h
HTTP/1.1 200 OK
Content-Type: text/plain
# TYPE jail_cpu_usage_ticks_1s gauge
# TYPE jail_cpu_usage_ticks_10s_avg gauge
# TYPE jail_processes gauge
# TYPE jail_references gauge
# TYPE jail_vmem_bytes gauge
jail_cpu_usage_ticks_1s{jid="3",name="web",root="/var/jailmgr/jails/web/root"} 0
jail_cpu_usage_ticks_10s_avg{jid="3",name="web",root="/var/jailmgr/jails/web/root"} 0
jail_processes{jid="3",name="web",root="/var/jailmgr/jails/web/root"} 1
jail_references{jid="3",name="web",root="/var/jailmgr/jails/web/root"} 2
jail_vmem_bytes{jid="3",name="web",root="/var/jailmgr/jails/web/root"} 154025984
Result
- Base-system HTTP daemon
- Snapshot-based observability
- Supervised execution
- Ephemeral provisioning
- Observable via structured metrics
- No container runtime
- No UID remapping
- No full virtualization
This is process isolation as a disciplined, inspectable system primitive.