Skip to main content

roj (Run On Jail)

roj is a simple command-line tool that runs a command (login shell by default) in the given jail, either locally or over SSH.

Requirements

Python 3.10 or newer.

The host whose jails you are addressing must be FreeBSD, since roj drives jls(8) and jexec(8) there. The machine you run roj from need only be POSIX: with -H/--host everything is wrapped in ssh(1), so driving a FreeBSD jail host from Linux or macOS works. Windows is not supported.

jexec(8) needs root. If you are not root on the jail host, sudo(8) must be installed there and you must be allowed to run jexec through it; see Privilege Escalation below.

Installation

pip install roj

Examples:

roj abc

Runs a login shell in the local jail named abc.

roj -H adx ldap1 ps axl

Runs ps axl in the jail named ldap1 on the remote SSH host adx.

roj

Shows the jails on the local host.

roj -H pbsp

Shows the jails on the remote SSH host pbsp.

iocage Compatibility

The iocage jail manager uses the ioc- prefix in its jail names. To maintain compatibility with iocage, by default roj shows and accepts jail names without the ioc- prefix.

Except if there is a conflict, then this prefix stripping behavior is disabled. For example, if there is a jail ioc-xyz and there is also another jail xyz, then the former is shown as and must be specified as ioc-test.

This behaviour can be disabled using the -f/--full flag.

SSH Host (-H/--host) Config

The hostname given to -H/--host is provided verbatim to OpenSSH ssh(1) so the name is subject to the usual configuration settings. For example, to use a shorthand alias, ex: roj -Hadx:

Host adx
        HostName adx-florence.bop.gov

SSH Pseudo TTY Allocation

Just like OpenSSH ssh(1), by default login shells are run with a pseudo TTY, and explicit commands are run without one. This behavior can be overridden with --tty/--no-tty (or -t/-T, as with ssh(1)).

Privilege Escalation (sudo)

jexec(8) requires root, so roj runs it under sudo(8) when the user it would otherwise run as is not root. jls(8) is never run under sudo: listing jails does not need privileges.

There are three states:

  • By default the decision is automatic. Locally, roj sudoes when its own effective uid is not 0. Remotely, the decision is made on the far side by the jail host's /bin/sh, since which user an SSH session lands as is not knowable from here.
  • --sudo/-S always runs jexec under sudo, with no uid check.
  • --no-sudo never does, which is exactly the pre-0.4.0 behavior.

roj never passes -n, so a password prompt is always allowed to happen; if it cannot, sudo itself says so and fails:

sudo: a terminal is required to read the password; either use ssh's -t option
or configure an askpass helper
sudo: a password is required

Whether there is a terminal to prompt on is up to ssh, which allocates a pseudo TTY only when asked with -t -- the default for a login shell, but not for an explicit command. So to let sudo prompt for a password while running an explicit command over SSH, pass -t:

roj -H adx -t ldap1 ps axl

For unattended use -- cron, scripts, anything with neither a terminal nor an askpass helper -- give the invoking user a NOPASSWD entry for jexec in sudoers(5) on the jail host:

alice ALL = (root) NOPASSWD: /usr/sbin/jexec

Bash Completion

To use Bash completion support of roj:

complete -C 'roj --bash-complete' roj

It takes connection-related options (-H/--host and -u/--user) so the following works as expected:

alias roj1='roj --host=server1'
complete -C `roj1 --bash-complete` roj1

Development

The dev toolchain is managed by uv, and uv.lock is committed and authoritative.

uv sync                          # create .venv from uv.lock
uv run pytest                    # run the tests
uv run --python 3.14 pytest      # ...on any supported version; uv fetches it
uv run ruff check .              # lint
uv run ruff format .             # format ("--check" to verify only)
uv build                         # build the sdist and wheel

If you change [project] or [dependency-groups] in pyproject.toml, regenerate the lockfile with uv lock and commit it: CI runs uv lock --check and fails on a stale one.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

roj-0.4.0.tar.gz (14.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

roj-0.4.0-py3-none-any.whl (7.3 kB view details)

Uploaded Python 3

File details

Details for the file roj-0.4.0.tar.gz.

File metadata

  • Download URL: roj-0.4.0.tar.gz
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for roj-0.4.0.tar.gz
Algorithm Hash digest
SHA256 302421df36484e0018339b1fac0fcbdfcd226aeb171c2a12ab2563089a430865
MD5 a8f14d440942532a6d18a97b687108ab
BLAKE2b-256 4dc11884db39cf1df91af777619177c0aebc09a1582972adbc45027c2ea434c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for roj-0.4.0.tar.gz:

Publisher: release.yml on astralblue/roj

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file roj-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: roj-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 7.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for roj-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ce2163f96683e19490f43d3be7b909c4f0f9f8249447effb2c833c75b2a9bf3e
MD5 49e58f93ed1ddaa9711d764eda65ec6f
BLAKE2b-256 aab74f4383945a10e7781f8218de46cfe21c23f7d6ad7340c0d0d91df07c8953

See more details on using hashes here.

Provenance

The following attestation bundles were made for roj-0.4.0-py3-none-any.whl:

Publisher: release.yml on astralblue/roj

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.2

2 files

0.1.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page