Status and roadmap

What works, and what does not yet

JailOps is under active development. It has not reached a stable release and has not been security audited. Treat it as something to try on a scratch pool, not something to put in front of production workloads.

How to read this page. Most of the code is exercised on Linux against fakes of zfs, jail and pfctl. A set of mechanisms has been run on a real FreeBSD 15.1 host (an arm64 test host; amd64 has not been tested), and only that set is marked verified, with the limits stated in each row. Verified means a prototype ran, not that the finished product is proven or audited. Anything not listed as verified has not been proven on FreeBSD.

Status of each JailOps capability
CapabilityStatusNotes
Jail lifecycle
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Create, start, stop, restart, delete, snapshots, copies, exec and shell (with a terminal), for thin and thick jails. Tested on Linux against fakes of zfs, jail and pfctl, and run on FreeBSD 15.1 arm64 with the daemon as an unprivileged user and the root helper on a socket: create from an image generation, start, stop, exec in FreeBSD and Alpine jails. Freezing a jail is not implemented and answers unsupported.
Jail system calls from pure Go
Verified on FreeBSD 15.1 (arm64)
jail_set, jail_get and jail_remove work from pure Go through x/sys, and results and enumeration equal jls. LOCAL_PEERCRED peer checks work. Lowering a jail's securelevel from the host is not refused by the kernel, so nothing relies on that.
Image generations and thin jails
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Immutable pkgbase generations, thin jails as ZFS clones, persistent datasets. A prototype built a userland with pkg -r, started a thin jail and ran pkg install in it on FreeBSD 15.1. The persistent path list is not final: how /var/db/pkg behaves after a root swap is open.
Jail upgrade and rollback scopes
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Upgrade with an /etc three-way merge, root swap and health check; rollback scopes root, data and all with data-loss confirmation. The mechanism (etcupdate on pkgbase generations, zfs rename root swap, root rollback keeping data) ran on FreeBSD 15.1. The account databases are merged by JailOps itself.
Managed bridges, IPAM, address ranges
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
VNET bridges, deterministic allocation from explicit ranges, routed IPv6, no DHCP, RA or SLAAC. Rendering is pure and golden-tested. On FreeBSD 15.1 a jail on a managed bridge got its address, reached its gateway and, through the NAT anchor, the internet. A dual-stack bridge (a /24 with NAT and a /80 carved from a routed /64) also worked: jails got an IPv4 and an IPv6 address automatically, reached the internet over both, and the host reached them. Not yet verified: traffic into a jail from the internet, several networks per jail, amd64.
PF anchors per jail
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Anchors load, replace and flush without touching the administrator's ruleset; replacement is atomic (200 reloads under sampling, never empty or mixed); syntax errors are rejected and the old ruleset stays. Tables are anchor-local, and pfctl -n accepts an undefined table, so the renderer proves every table is defined. Nested anchors are evaluated only when every parent anchor contains anchor "*", and the renderer emits it.
Isolation of projects on a shared bridge
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
On the arm64 test host, PF filtered traffic between projects on a shared bridge, and a per-jail source-address table at the member interface dropped a jail sourcing another jail's address. The private bridge-member flag blocks all member-to-member traffic, including within a project, so it is an option for routed setups, off by default. Only ordinary tools were used: active attacks (forged ARP, NDP, router advertisements, DHCP) were not automated, and Ethernet-level protection (ARP, NDP, MAC spoofing) is not covered and is still open. A shared bridge is not a full security boundary.
IPv6 NDP proxy mode
Experimental
Built-in proxy for upstreams that treat addresses as on-link (a switched /64). Off by default. Unproven on FreeBSD; routed mode does not depend on it.
Linux jails (Alpine, Debian)
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)Experimental
An Alpine 3.22 minirootfs ran as a jail on FreeBSD 15.1 arm64 under the Linuxulator: apk update and apk add openssh nginx worked, nginx served a page, sshd answered, and a ZFS rollback repaired a broken root. It needs kern.elf64.fallback_brand=3, which JailOps manages. Debian 13 (trixie, glibc 2.41) built with debootstrap (the release signature is always checked) and ran the same way: apt-get update and install worked, and both jails had IPv4 and IPv6 connectivity. Not yet verified: amd64, other glibc distributions, behaviour under load. Managed updates and package provisioning support Alpine only. Linux jails stay experimental.
Chunk repository and backup node
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Client-side encryption, zstd, content-defined chunking, keyless jailops-backupd on a directory or S3 (tested against an in-process S3 fake), retention, garbage collection, verification, quarantine, PostgreSQL control plane. Tested on Linux; on FreeBSD the node ran against PostgreSQL and a directory repository and served a host over mutual TLS. Not yet run on FreeBSD: S3, retention and garbage collection against real data.
Backup and restore from a host
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
A running jail was backed up from its ZFS snapshot to a backup node (the second backup uploaded 1.3 KiB), verified at three depths (deep, extract and full, which boots the backup as a jail of its own and removes it), and restored as a new jail that kept its owners, modes and files and started. The daemon is not root: file agents of the privileged helper, confined by chroot to one checked directory, read the snapshot and write the restored jail. Capture assumptions were checked earlier: snapshot metadata (including extended attributes, NFSv4 ACLs and file flags) matched a live stat, and inode and ctime were stable across snapshots, rollback and send. zfs diff does not report added or removed hard-link names, so the accelerator rescans modified directories and multi-link files. A snapshot that is destroyed during a read fails with ENXIO, so capture holds it.
ZFS replication between trusted hosts
Verified on FreeBSD 15.1 (arm64)Planned
The ZFS behaviours it relies on ran on the arm64 test host: clone sends, send -R, bookmarks as incremental bases, holds, resume tokens, raw sends of encrypted datasets. recv accepts an incremental on top of a newer receiver snapshot without -F, so guid continuity is enforced by JailOps. JailOps' replication code is a library and is not yet exposed through the API or CLI.
REST API, operations, events, authentication
Implemented, tested with fakes
Routes, permission table, tokens, mTLS pinning, sessions, audit log. Contract and authorization-matrix tests run against fakes.
CLI jailops
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Command tree covered by golden tests, and used against a real daemon on FreeBSD for the flows above (images, networks, projects, jails, exec and shell, labels, backups).
Go SDK and in-memory fake server
Implemented, tested with fakes
Separate module, standard library only.
Web consoles (host and backup node)
Implemented, tested with fakes
Vue 3 apps with unit tests and browser tests in demo mode, with light and dark themes and phone layouts. They are embedded in the daemons. The jail terminal of the host console was driven by a browser against a daemon on FreeBSD; the other pages have only run in demo mode. The consoles are under active change.
Hub mode
Implemented, tested with fakes
Registry of hosts, forwarding with --host over pinned mTLS. Tested against fakes.
jailops-sync
Implemented, tested with fakes
validate, render, plan, drift, sync --apply, adopt, prune-check, rollouts, age secrets, apply log.
Managed updates
Implemented, tested with fakes
Update policy per jail (manual, notify, managed), checks, explicit apply with a snapshot, history, and the same through jailops-sync rollouts. Tested with fakes; the package and generation updates have not been run on a real jail yet.
Cluster mode with Raft
Planned
The Raft library is chosen (hashicorp/raft, after running both candidates on FreeBSD), the cluster mode is not built. Replicated fleet metadata. The Raft library has not been chosen yet.
Self-healing fleets
Planned
A direction under discussion, not a capability, and not scheduled. Automatic promotion of stateful workloads will not happen without fencing, and asynchronous replication does not mean zero data loss.
CARP
Planned
May be offered later as an optional networking feature. JailOps does not build failover on it.
WebAuthn and OIDC sign-in
Planned
Planned after the first stable release.
FreeBSD pkg packaging
Implemented, tested with fakesVerified on FreeBSD 15.1 (arm64)
Three packages (jailops-client, jailops, jailops-backupd), rc.d scripts, jailops-priv init and a signed pkg repository are built by scripts and a release workflow. On a clean FreeBSD 15.1 machine the whole flow ran from the packages: install, setup, services, image, jail, backup, restore. The public repository at pkg.jailops.net is not live yet, so there is no published package.

Roadmap

The design plans work in milestones, with no dates. Each milestone is meant to be released as a 0.x version, and 1.0 is planned only when all of them pass their tests.

  1. M1, core. Generations, thin and thick jails, lifecycle, snapshots, rollback, daemon and privileged helper, API, SDK, CLI, packaging.
  2. M2, network and firewall. Bridges, VNET, IPAM, routed and proxy IPv6, PF anchors, doctor, web console.
  3. M3, Linux jails. Alpine and Debian (both proven on arm64 only so far).
  4. M4, backup. Chunk repository, backup node, retention, restore and restore tests, S3, and replication between trusted hosts.
  5. M5, hub. Mutual TLS, remotes, cold moves between hosts.
  6. M6, fleet. jailops-sync, rollouts, age secrets, adopting live objects into the repository.
  7. M7, cluster mode. Raft-replicated fleet metadata.

Not on the roadmap: virtual machines, OCI containers, live migration, non-ZFS storage.