Blackship vs The Galaxy: FreeBSD Jail Managers Compared

Every few months, someone asks on the FreeBSD forums: “Which jail manager should I use?” The answers are always the same: “CBSD if you want everything. Bastille if you want simple. iocage if… wait, is iocage still maintained?”
Here’s the actual breakdown.
The Contenders¶
Docker/Podman (Linux-first, FreeBSD adapters)¶
What they are: OCI container runtimes that can use jails as their isolation primitive on FreeBSD.
The good: You get the entire Docker/OCI ecosystem. Images from Docker Hub. Compose files. The tooling your team already knows.
The brutal truth: You’re running Linux container tooling on a BSD system. Podman uses ocijail under the hood. Containerd uses runj. Both work, but you’re adding abstraction layers on top of jails instead of using jails directly. Also, no VNET support in OCI containers on FreeBSD. No ZFS integration beyond basic image layers.
Use when: Your team speaks Docker and you need portability over performance.
Bastille¶
What it is: Shell-based jail automation. Zero dependencies. Docker-like templates called “Bastillefile”.
The good: Simple, well-documented, active development. Recent versions (1.0+) handle both -V and -B VNET jails dynamically. Dual-stack networking (IPv4+IPv6). DHCP support. The naming convention for epairs (e0a_jailname, e0b_jailname) is genuinely smart.
The brutal truth: It’s shell scripts. For simple jails, that’s fine. For complex orchestration with health checks, circuit breakers, and dependency graphs? You’ll be layering scripts on top of scripts.
Use when: You want straightforward jail management without learning a new paradigm.
CBSD¶
What it is: The everything tool. Jails, bhyve VMs, QEMU, Xen. Web UI. Clustering. CARP/HAST integration.
The good: If you need it, CBSD probably has it. People run 150+ VMs with it. Rock solid. SQLite backend. Great support from the maintainer (Ole). Been around since 2013.
The brutal truth: It’s massive. Users are split into two camps: “CBSD is awesome” and “CBSD is too complicated.” The learning curve is real. If you just need jails, you’re carrying a lot of VM infrastructure you’ll never use.
Use when: You’re building a full virtualization platform with jails AND bhyve VMs, or you need clustering features.
iocage¶
What it was: The ZFS-first jail manager that everyone loved around 2016-2018.
The brutal truth: Development stalled. The Python rewrite fragmented the community. People still use it, but “is iocage maintained?” is a legitimate question.
Use when: You have legacy iocage jails and migration would be painful.
pot¶
What it is: Lightweight jail manager focused on simplicity.
The good: Minimal, does what it says.
The brutal truth: Limited feature set compared to CBSD or even Bastille.
Use when: You want minimal and your needs are minimal.
Blackship: What’s Different¶
I built Blackship because existing tools fell into two camps:
- Too simple: No dependency management, no health checks, no state machine lifecycle
- Too complex: Web UIs and clustering when I just need jails
Blackship is the middle ground. Here’s what it actually does differently:
State Machine Lifecycle¶
Every jail has explicit states: Stopped → Starting → Running → Stopping → Failed. Invalid transitions are rejected at runtime with clear errors. No more “is this jail actually running or in some weird half-state?”
blackship up web
# Stopped → Starting → (hooks run) → Running
blackship down web
# Running → Stopping → (hooks run) → Stopped
Dependency Graphs (petgraph)¶
Define dependencies. Blackship figures out the order.
[[jails]]
name = "app"
depends_on = ["cache", "database"]
[[jails]]
name = "cache"
[[jails]]
name = "database"
Start order: database → cache → app
Stop order: app → cache → database
Not rocket science, but you’d be surprised how many tools don’t do this.
Circuit Breakers + Exponential Backoff¶
The Warden supervisor doesn’t just restart crashed jails blindly. It uses:
- Exponential backoff (1s → 2s → 4s → … → 60s max)
- Circuit breaker (after 5 failures, stop trying for 5 minutes)
- Per-jail restart state tracking
No more restart loops hammering your system.
Jailfile Templates¶
Docker-like build syntax:
FROM 15.0-RELEASE
ARG NGINX_VERSION=1.24
RUN pkg install -y nginx-${NGINX_VERSION}
RUN sysrc nginx_enable=YES
COPY nginx.conf /usr/local/etc/nginx/nginx.conf
EXPOSE 80/tcp
CMD /usr/local/sbin/nginx -g 'daemon off;'
Or TOML if you prefer:
[metadata]
name = "nginx-jail"
from = "15.0-RELEASE"
[[instructions]]
type = "run"
command = "pkg install -y nginx"
ZFS First-Class¶
Not bolted on. Designed around ZFS.
# Snapshot before risky operation
blackship snapshot create web pre-update
# Something broke?
blackship down web
blackship snapshot rollback web pre-update --force
blackship up web
# Clone for testing
blackship clone web@pre-update web-test
# Export with ZFS send (fast)
blackship export web -o backup.zfs --zfs-send
VNET + PF Integration¶
Bridge-based networking with epair interfaces. PF anchors for port forwarding (no editing /etc/pf.conf).
blackship network create default --subnet 10.0.1.0/24 --gateway 10.0.1.1 --bridge blackship0
blackship expose web -p 80
blackship expose web -p 443 -I 192.168.1.100 # Bind to specific IP
Health Checks That Matter¶
All command-based. Exit 0 = healthy. Simple.
[[jails.healthcheck.checks]]
name = "http"
command = "curl -sf http://localhost:8080/health"
target = "jail"
interval = 30
timeout = 10
retries = 3
The Honest Comparison Table¶
| Feature | Docker/Podman | Bastille | CBSD | Blackship |
|---|---|---|---|---|
| FreeBSD Native | Adapter layer | Yes | Yes | Yes |
| VNET Support | No | Yes | Yes | Yes |
| ZFS Integration | Basic | Manual | Yes | First-class |
| Dependency Ordering | Compose | No | Manual | Automatic |
| State Machine | Implicit | No | No | Explicit |
| Health Checks | Yes | Manual | Yes | Built-in |
| Circuit Breaker | No | No | No | Yes |
| Jailfile/Template | Dockerfile | Bastillefile | Templates | Jailfile |
| bhyve VMs | No | No | Yes | No |
| Web UI | Portainer | No | Yes | No |
| Complexity | Medium | Low | High | Medium |
When to Use What¶
Use Docker/Podman if your team already knows Docker and you need image portability.
Use Bastille if you want simple jail management with minimal learning curve.
Use CBSD if you’re building a full virtualization platform with jails + VMs + clustering.
Use Blackship if you want:
- State machine lifecycle with clean transitions
- Automatic dependency ordering
- Circuit breaker protection against restart loops
- ZFS-first design without the VM overhead
- Docker-like build templates without the Docker abstraction layer
The Real Difference¶
Most jail managers treat jails as file systems with networking attached. Start the jail, hope for the best, restart on crash.
Blackship treats jails as state machines with lifecycle hooks, health monitoring, and resilience patterns. The same patterns you’d use for production microservices, applied to FreeBSD jails.
That’s the pitch. Use what fits your workflow.
cargo install blackship
🔗 Interstellar Communications
No transmissions detected yet. Be the first to establish contact!
Related Posts
Blackship: A FreeBSD Jail Orchestrator That Understands State
Announcing Blackship - declarative jail management with dependency graphs, state machines, circuit breakers, and ZFS-first design.
Blackship Architecture: State Machines, Dependency Graphs, and Resilience Patterns
How Blackship uses explicit state machines, topological ordering, circuit breakers, and lifecycle hooks to manage FreeBSD jails reliably.
Helmsman: Stop Writing AGENTS.md That Lies to Half Your Models
Your static instruction file works for Opus and breaks for Haiku. Helmsman serves model-aware instructions that adapt to capability tiers, environment, and project context.