Skip to content

Releases: hyphatech/jailrun

v0.9.0

30 Mar 12:51

Choose a tag to compare

Jailrun takes the wheel 🫡

This release drops Bastille and introduces smarter provisioning.

Highlights

  • Jailrun now manages jails directly: Bastille was useful early on, but Jailrun has grown past the point where that abstraction still makes sense. Jailrun now needs direct control over how jails are created, cloned, templated, and managed throughout their full lifecycle. Owning the jail process directly unlocks the flexibility and transparency Jailrun is aiming for, without workarounds or hacky tricks.
  • Smarter provisioning: Provisioning now only re-runs the parts of the config that actually changed, which can save a lot of time on repeated runs. When you do want to force a full reprovision regardless of the current jail state, jrun up --provision does exactly that, similar to the existing jrun start --provision behaviour.
  • A cleaner, more declarative up: The up flow has been refactored from the ground up. It is now not only smarter, but also much cleaner internally and more declarative, which should make future improvements easier to build and reason about.
  • Playbooks converted into roles: All playbooks have been revisited and converted into roles. This makes the provisioning setup cleaner today and gives Jailrun a more flexible foundation for future features.
  • Fixed Monit restart behaviour: Changing an exec block in config now correctly triggers Monit restart logic, so updating executable parameters takes effect immediately as expected.

Upgrading

Jailrun now fully controls its own jails. They live in a dedicated /usr/local/jailrun/jails dataset and rely only on native jail primitives and ZFS features. If you already have provisioned jails, the simplest upgrade path is to purge the VM and recreate them from scratch.

v0.8.0

23 Mar 14:44

Choose a tag to compare

Stable mesh, status grows up ⚡️

This release graduates mesh networking out of experimental, ships a significantly reworked status command, and brings a round of documentation and polish across the board.

Highlights

  • Mesh networking for everyone: Yggdrasil-based mesh networking is no longer experimental — it is an official, supported part of Jailrun. Every jail gets a unique, globally reachable IPv6 address, and a public relay is now available at relay.jail.run to make mesh connectivity work out of the box without any extra setup. Read more: https://jail.run/reference/mesh/
  • Reworked jrun status: The status command has been significantly overhauled. It now supports --live for real-time monitoring and jail-scoped status so you can drill into a single jail instead of getting a wall of output. The new --show flag gives you granular control over what is displayed — ip, services, or all for now, with more sections coming in future releases: https://jail.run/reference/jrun-status
  • Extensive docs and a more polished experience: A lot of effort went into documentation and smoothing rough edges across the whole tool. If something confused you before, it might just work now. Or not.

Upgrading

If you already have Jailrun installed, run jrun start --provision to re-provision the VM. Your existing jails will also need to be recreated to get their mesh identities.

v0.7.0

19 Mar 13:18

Choose a tag to compare

Meet snapshots 📸

This release introduces snapshot support as a first-class feature, along with a few usability improvements and fixes.

Highlights

  • New snapshot command: Added jrun snapshot with create, rollback, list, and delete actions, making ZFS snapshots easy to use in everyday workflows. Read more: https://jail.run/tutorials/snapshots/

  • Dropped pause: Removed the pause command to keep the CLI minimal.

  • Cleaner output by default: Replaced verbose Ansible stdout with progress bars and status indicators. Use JRUN_DEBUG to see full verbose output.

  • Fixed Yggdrasil identity on clone: Cloned jails now get a new Yggdrasil identity instead of reusing the cloned original.

  • Better docs, better UX: Continued improvements across documentation and overall user experience.

v0.6.1

17 Mar 19:36

Choose a tag to compare

Before the next leap

This is a smaller follow-up release focused on stabilizing the new networking model, cleaning up rough edges, and preparing the ground for upcoming "pairing" feature.

Highlights

  • Groundwork for upcoming mesh networking: Added some of the prerequisites needed for future mesh support, including pairing logic, peer discovery foundations and access control.

  • Fixed DNS discovery from inside the VM: The VM can now correctly resolve and reach jails by name.

  • New DNS naming convention: Local jail DNS names now use jail-name.local.jrun, which leaves room for upcoming remote and mesh-aware names like jail-name.peer-id.jrun.

  • Fixed resolv.conf generation: Resolved an issue where the generated resolv.conf could get reset to the default during bootstrap.

  • Per-jail PF enabled: Packet filter support is now enabled per jail, giving us a better foundation for more granular networking behavior.

Linux is different

  • BIOS/OVMF VARS probing on start: Fixed a Linux issue where VMs could fail to survive restart.

  • OVMF VARS cleanup on stop/start: Fixed a Linux issue where stale VARS state could cause the VM to hang.

v0.6.0

13 Mar 12:53

Choose a tag to compare

VNET, mesh networking, and FreeBSD host support

This release is a huge milestone, bringing Jailrun one step closer to remote targets and mesh networking.

Highlights

  • All jails are now bridged VNET jails: This is a foundational networking change that unlocks features we want to build next and gives each jail a more complete and flexible network stack.

  • Experimental mesh networking with Yggdrasil: Each jail now has its own unique, globally reachable mesh identity with its own IPv6 address, and jrun status now shows IPv6 alongside IPv4. This is still early and not yet broadly useful day-to-day, but it lays the groundwork for future "Remote targets" support from the roadmap.

  • FreeBSD host support: Yep! Jailrun now supports FreeBSD itself as a host system. Just like on macOS and Linux, the base system is still virtualized with QEMU, which means you are effectively running FreeBSD jails inside a FreeBSD VM on a FreeBSD host. One day, FreeBSD hosts should be able to switch to bhyve instead of QEMU.

  • Jail names are now shadowed internally: Bastille’s VNET jail naming rules are too restrictive for real-world use, so Jailrun now keeps an internal shadow name for each jail. That means you can still use conventional names like hypha-postgres-16, but under the hood they become generated IDs like j523d40ff4d16. Jailrun resolves this mapping automatically everywhere, so you should not notice any difference.

Minor changes

  • Disabled SRV mirror discovery: SRV-based mirror discovery has been disabled because it proved unreliable in practice.

  • Cleaner and more scoped reconciliation: port forwards, mounts, executables, and DNS reconciliation are now more tightly scoped and more robust. This should reduce side effects, avoid unnecessary downtime, and make provisioning faster.

Upgrading

  • Since all jails are now bridged VNET jails, this release changes core jail networking behavior. If you already have provisioned jails, the simplest path is to purge and recreate all of them. Sorry.

v0.5.1

11 Mar 18:54

Choose a tag to compare

Minor release, not-so-minor changes

0.5.1 is a focused release with a few important usability and infrastructure changes. The biggest one is a switch from /etc/hosts fanout to real DNS-based jail discovery, alongside a more practical pause / down workflow and softer monit defaults.

Highlights

  • Better host portability on Linux: QEMU BIOS path detection is now more robust across Linux distributions instead of assuming a single fixed OVMF location. This should make jrun behave more consistently across supported hosts. JRUN_QEMU_BIOS can still be used to override the detected firmware path when needed. (#7)

  • Real DNS for jail discovery: local_unbound is now used instead of /etc/hosts fanout for cross-jail name resolution. Jails now discover each other under the .jrun domain.

  • pause / down: these commands no longer require a config path, only jail names. If names are not provided, jrun now offers an interactive wizard to pick from running jails. This feels more natural in day-to-day use, covers more cases, and aligns with the upcoming snapshot command.

Upgrading

  • Cross-jail discovery changed: because jail-to-jail name resolution now goes through local_unbound and the .jrun domain, previously provisioned jails will not carry over cleanly. If you already have provisioned jails, the simplest path is to purge and recreate all of them. Sorry.

v0.5.0

09 Mar 11:57

Choose a tag to compare

Step closer to perfection

0.5.0 is all about a stable and clean codebase, with a few recently discovered issues fixed and some new handy features to push the boundaries even further.

Highlights

  • jrun cmd: run a command inside a jail directly from the host. Arguments are shell-quoted automatically, so jrun cmd jailname psql -U postgres -c 'SELECT version()' just works — no interactive session needed.

  • hub:// playbook shorthand: reference playbooks from Jailrun Hub without spelling out the full GitHub URL. url = "hub://nginx/rolling" resolves to the right playbook automatically. Pinning to a tag works too: hub://nginx/rolling@v1.0.0.

  • jrun start --provision: re-run base provisioning on an already-booted VM without restarting it.

Fixes & improvements

  • Clock drift resolved. ntpd is now enabled by default inside the VM, fixing time skew that could accumulate over long sessions. (#3)

  • SSH port conflicts handled. The SSH port is now derived from shared state and resolved early. If the default port is busy, jrun probes for the next free one instead of failing. (#2)

  • Leaner base provisioning. The base playbook has been optimised a bit for FreeBSD under QEMU.

  • Shell internals refactored. The interactive shell now reuses the Click command registry as its source of truth, making it easier to add new commands without duplicating logic.

v0.4.0

06 Mar 19:26

Choose a tag to compare

CLI from 2026

0.4.0 is all about the experience.

Highlights

  • Interactive shell: run jrun with no arguments to enter a persistent session with autocomplete and guided wizards for every command.
  • Consistent UI language: every output line now follows a clear visual convention across all commands, interactive and standalone.
  • Polished wizards: up, down, pause, ssh — all guide you through config and jail selection interactively, with live jail discovery over SSH.

v0.3.0

05 Mar 13:44

Choose a tag to compare

Now we're talking!

A bigger step forward: smoother provisioning, nicer ergonomics, and a bit more on top.

Highlights

  • Fixed RDR provisioning order for Bastille: resolves a case where pf rules could end up empty.
  • Nice jrun status --tree: a tree view for those who don't like tables.
  • Per-exec environment variables: set env vars directly on executables:
exec {
  imagor {
    cmd = "imagor";
    env {
      IMAGOR_UNSAFE = "1";
    }
  }
}
  • Monit config reload fixed: changes to executable configs now take effect.
  • New command jrun pause: stop a jail without tearing it down.
  • Super-handy jrun jail ssh <jail_name>: jump straight into a jail via SSH.
  • Testing framework upgrade: now uses jrun-native operations instead of bastille cmd calls from the VM.
  • QEMU runner now supports 3 modes: server | tty | graphic! This unlocks graphical environment setups.

Desktop mode (XFCE)

Provision a FreeBSD VM with an XFCE desktop using a custom base config and ready-to-go playbook from the Hub:

base {
  setup {
    xfce { type = "ansible"; url = "https://github.com/hyphatech/jailrun-hub/blob/main/playbooks/xfce/latest/playbook.yml"; }
  }
}

Bring it up in one command:

jrun start --base base.ucl --mode graphic

Enjoy XFCE (user / password: hypha / hypha)!

Reliability & maintenance

  • More robust up and start pipelines.
  • General codebase cleanup to make it shiny.

v0.2.2

04 Mar 10:37

Choose a tag to compare

First stable release 🎉

jrun is now ready to be installed and used. Everything works end-to-end (until it doesn't).

Highlights

  • One-command setupjrun start downloads FreeBSD and boots a VM with SSH access. jrun ssh or jrun console to get in.
  • Jail lifecycle management — create, clone, update, and tear down jails with jrun up and jrun down. Dependency resolution is automatic.
  • UCL config format — define jails, mounts, port forwards, setup playbooks, and supervised processes in clean, human-readable config files.
  • Host directory sharing — mount directories from your host into jails via 9p. File changes are reflected instantly in both directions.
  • Port forwarding — expose jail services on your host. Traffic is routed through FreeBSD's pf firewall.
  • Ansible provisioning — run playbooks during jail setup. Supports local files and remote URLs from jailrun-hub.
  • Jail cloning — use base to clone one jail from another. Powered by ZFS snapshots — fast and cheap on disk.
  • Process supervision — supervised processes inside jails via monit, with automatic restarts and configurable healthchecks.
  • Testing fixturesjailrun.testing.postgres and jailrun.testing.redis provide pytest fixtures that spin up real services in jails for your test suite.
  • Base config — optional VM-level config (--base flag) for custom mounts, port forwards, and provisioning on the host VM itself.

Install

See the README for full instructions.

macOS:

brew tap hyphatech/jailrun
brew install jailrun

Linux:

pipx install jailrun