FreeBSD.software
Home/Guides/Bastille on FreeBSD: Jail Manager Review
review·2026-04-09·9 min read

Bastille on FreeBSD: Jail Manager Review

Review of Bastille jail manager on FreeBSD: installation, creating and managing jails, templates, networking, ZFS integration, and comparison with iocage and pot.

Bastille on FreeBSD: Jail Manager Review

Bastille is a jail management framework for FreeBSD that brings container-like workflows to the jail ecosystem. It uses templates for repeatable deployments, integrates with ZFS, and provides a clean CLI. This review covers installation, jail lifecycle management, networking, templates, ZFS integration, and how Bastille compares to iocage and pot. If you manage FreeBSD jails and want something more structured than raw jail.conf, Bastille deserves evaluation.

For background on FreeBSD jails themselves, see our FreeBSD jails guide. For a broader comparison of jail managers, see best jail manager for FreeBSD.

What Bastille Brings to the Table

FreeBSD jails are powerful but managing them manually involves repetitive configuration: creating directory trees, extracting base systems, writing jail.conf entries, configuring networking, and maintaining updates. Bastille automates all of this.

Key features:

  • Template system for declarative jail configuration
  • ZFS-aware with clone-based jail creation
  • VNET networking support
  • Thin and thick jail support
  • Import/export for jail migration
  • Firewall integration (PF and IPFW)
  • Active development and responsive maintainer

Installation

Package Install

sh
pkg install bastille

Ports Install

sh
cd /usr/ports/sysutils/bastille make install clean

Initial Configuration

Bastille's configuration lives in /usr/local/etc/bastille/bastille.conf. Review and adjust:

sh
# /usr/local/etc/bastille/bastille.conf # Base directory for all Bastille data bastille_prefix="/usr/local/bastille" # ZFS support bastille_zfs_enable="YES" bastille_zfs_zpool="zroot" # Default networking bastille_network_loopback="bastille0" bastille_network_shared="" # Default FreeBSD release bastille_release="14.2-RELEASE"

Enable the service:

sh
sysrc bastille_enable="YES"

Setting Up the Network Interface

Bastille uses a cloned loopback interface for jail IP addresses by default:

sh
sysrc cloned_interfaces="lo1" sysrc ifconfig_lo1_name="bastille0" service netif cloneup

If using PF, add NAT rules for jail traffic in /etc/pf.conf:

sh
ext_if="em0" bastille_if="bastille0" nat on $ext_if from ($bastille_if:network) to any -> ($ext_if) # Allow jail traffic pass quick on $bastille_if

Reload PF:

sh
pfctl -f /etc/pf.conf

Bootstrapping a Release

Before creating jails, you need a FreeBSD release to base them on:

sh
bastille bootstrap 14.2-RELEASE update

This downloads the FreeBSD base system and applies pending security patches. The files are stored under /usr/local/bastille/releases/14.2-RELEASE/. On ZFS, this is a dedicated dataset.

You can bootstrap multiple releases:

sh
bastille bootstrap 13.4-RELEASE update bastille bootstrap 14.2-RELEASE update

Creating Jails

Basic Jail Creation

sh
bastille create webserver 14.2-RELEASE 10.0.0.1

This creates a jail named "webserver" based on FreeBSD 14.2, with IP 10.0.0.1 on the bastille0 interface. On ZFS, Bastille clones the release dataset, making creation nearly instant.

Thick vs Thin Jails

By default, Bastille creates thin jails that share the base system via nullfs mounts. This saves disk space but means jails share the same base binaries.

For thick jails (full independent copy):

sh
bastille create --thick dbserver 14.2-RELEASE 10.0.0.2

Thick jails use more disk but can be independently updated and modified at the base level.

VNET Jails

For jails that need their own network stack (e.g., running DHCP clients, custom routing):

sh
bastille create -V vnetjail 14.2-RELEASE em0

VNET jails get a virtual epair interface bridged to the specified physical interface. They appear as independent hosts on the network.

Jail Lifecycle Management

Starting and Stopping

sh
bastille start webserver bastille stop webserver bastille restart webserver

Console Access

sh
bastille console webserver

This opens a shell inside the jail. Equivalent to jexec webserver /bin/sh.

Running Commands

sh
bastille cmd webserver pkg update bastille cmd webserver pkg install -y nginx

Listing Jails

sh
bastille list

Output includes jail name, status, IP address, and resource usage.

Destroying Jails

sh
bastille destroy webserver

On ZFS, this destroys the associated dataset. The operation is clean and complete.

Templates

Templates are Bastille's strongest feature. They define a sequence of commands to configure a jail declaratively.

Template Structure

A Bastille template is a directory containing a Bastillefile:

sh
# Example Bastillefile for an Nginx jail PKG nginx SYSRC nginx_enable=YES CP usr/local/etc/nginx/nginx.conf usr/local/etc/nginx/nginx.conf SERVICE nginx start

Built-in Commands

| Command | Description |

|---------|-------------|

| PKG | Install packages |

| SYSRC | Set rc.conf variables |

| CP | Copy files into the jail |

| CMD | Run arbitrary commands |

| SERVICE | Manage services |

| MOUNT | Mount filesystems |

| FSTAB | Add fstab entries |

| RDR | Port redirection (PF) |

| INCLUDE | Include another template |

Applying Templates

sh
bastille template webserver bastillebsd/nginx

This fetches and applies the nginx template from the BastilleBSD repository. You can also apply local templates:

sh
bastille template webserver /path/to/my/template

Custom Templates

Create a directory structure:

sh
mkdir -p /usr/local/bastille/templates/myorg/postgres

Write the Bastillefile:

sh
# /usr/local/bastille/templates/myorg/postgres/Bastillefile PKG postgresql16-server postgresql16-client SYSRC postgresql_enable=YES CMD /usr/local/etc/rc.d/postgresql initdb SERVICE postgresql start CMD psql -U postgres -c "ALTER USER postgres PASSWORD 'changeme';"

Apply it:

sh
bastille create dbserver 14.2-RELEASE 10.0.0.3 bastille template dbserver myorg/postgres

Template Composition

Templates can include other templates:

sh
# Bastillefile INCLUDE myorg/base-config INCLUDE myorg/monitoring-agent PKG nginx SYSRC nginx_enable=YES SERVICE nginx start

This enables layered configurations: a base template for common settings (DNS, NTP, users), a monitoring template for your agent, and service-specific configuration on top.

ZFS Integration

Bastille's ZFS support is well-implemented and gives you meaningful operational advantages.

Dataset Layout

When ZFS is enabled, Bastille creates:

shell
zroot/bastille zroot/bastille/releases zroot/bastille/releases/14.2-RELEASE zroot/bastille/jails zroot/bastille/jails/webserver zroot/bastille/templates

Snapshots

sh
# Snapshot a jail zfs snapshot zroot/bastille/jails/webserver@pre-upgrade # Rollback if something breaks zfs rollback zroot/bastille/jails/webserver@pre-upgrade

Export and Import

Bastille can export jails as compressed archives:

sh
bastille export webserver

This creates a file in /usr/local/bastille/backups/ that can be imported on another host:

sh
bastille import webserver.xz

On ZFS, export uses zfs send under the hood, which is efficient and consistent.

Updating Jails

Updating the Base Release

sh
bastille update 14.2-RELEASE

This fetches and applies security patches to the release. For thin jails, all jails based on this release get the updates immediately (they share the base via nullfs).

Upgrading Between Releases

sh
bastille upgrade 14.1-RELEASE 14.2-RELEASE

Package Updates Inside Jails

sh
# Update packages in a specific jail bastille cmd webserver pkg upgrade -y # Update packages in all running jails bastille cmd ALL pkg upgrade -y

Firewall Integration

PF Port Redirection

Bastille integrates with PF for port forwarding:

sh
# In a Bastillefile RDR tcp 80 80 RDR tcp 443 443

Or manually:

sh
bastille rdr webserver tcp 80 80 bastille rdr webserver tcp 443 443

This adds redirect rules to PF, forwarding traffic from the host's external IP to the jail.

IPFW Support

If you use IPFW instead of PF, Bastille supports it via configuration:

sh
# In bastille.conf bastille_network_pf_ext_if="" # Clear PF settings

You then manage IPFW rules manually or via templates using CMD directives.

Comparison with Alternatives

Bastille vs iocage

iocage was the dominant jail manager for years but development has stalled. Bastille is actively maintained and has a clearer design.

| Feature | Bastille | iocage |

|---------|----------|--------|

| Active development | Yes | Minimal |

| Template system | Yes (Bastillefiles) | No |

| ZFS support | Yes | Yes |

| VNET support | Yes | Yes |

| Thick/thin jails | Both | Primarily thick |

| Documentation | Good | Dated |

| Learning curve | Low | Medium |

Bastille vs pot

pot is another modern jail manager with a focus on orchestration (Nomad integration). If you need Nomad/Consul integration for orchestrated workloads, pot is worth considering. For standalone jail management, Bastille's template system is more practical.

Bastille vs Raw jail.conf

If you manage 1-3 jails and want maximum control, raw jail.conf is fine. Once you manage more than 5 jails, or need repeatable deployments, Bastille saves time and reduces errors. The template system alone justifies the dependency.

Production Tips

Resource Limits

Use rctl to limit jail resource consumption:

sh
bastille cmd webserver rctl -a jail:webserver:memoryuse:deny=2G bastille cmd webserver rctl -a jail:webserver:cputime:sigterm=3600

Enable RACCT in the kernel:

sh
echo 'kern.racct.enable=1' >> /boot/loader.conf

Monitoring

Monitor jail resource usage:

sh
bastille top webserver

Or use rctl -u jail:webserver for detailed resource accounting.

Backup Strategy

With ZFS, snapshot-based backups are the most efficient approach:

sh
# Daily snapshot script for jail in $(bastille list -q); do zfs snapshot "zroot/bastille/jails/${jail}@daily-$(date +%Y%m%d)" done # Prune snapshots older than 30 days zfs list -t snapshot -o name -H | grep "bastille/jails" | while read snap; do # Add date parsing and pruning logic done

Verdict

Bastille is the best jail manager currently available for FreeBSD. It is actively maintained, well-documented, and the template system provides genuine value for repeatable deployments. ZFS integration works correctly, VNET support is solid, and the CLI is intuitive.

The only weakness is that the ecosystem of community templates is still growing. You will likely write custom templates for your specific needs. But the framework for doing so is clean and well-designed.

Rating: 8/10 -- The best option in its category. Minor deductions for a still-maturing template ecosystem and occasional rough edges with VNET configuration on complex network topologies.

Frequently Asked Questions

Can I run Docker inside a Bastille jail?

No. Docker requires a Linux kernel. FreeBSD jails are an OS-level virtualization mechanism, not a Linux container runtime. If you need Docker, use bhyve to run a Linux VM, or use podman with Linux compatibility.

How do I give a jail internet access?

Configure NAT in PF (as shown in the installation section). The jail uses the bastille0 loopback interface, and PF NATs traffic to the external interface. Ensure the jail has correct DNS configuration in /usr/local/bastille/jails/JAILNAME/root/etc/resolv.conf.

Can I migrate jails between hosts?

Yes. Use bastille export on the source and bastille import on the destination. Both hosts must run compatible FreeBSD versions. For live migration, you will need a shared ZFS pool or manual zfs send | zfs receive workflow.

How do I access a service running in a jail from outside?

Use PF port redirection via bastille rdr, or configure the jail with a VNET interface on a routable network. The PF approach is simpler for most use cases.

Does Bastille support IPv6?

Yes. Assign IPv6 addresses when creating jails:

sh
bastille create webserver 14.2-RELEASE 10.0.0.1 fd00::1

How many jails can I run on a single host?

The practical limit depends on memory and CPU. Thin jails share the base system and add minimal overhead (a few MB per idle jail). Production deployments commonly run 20-50 jails on a single host. With adequate resources, hundreds are possible.

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.