Skip to main content

Pre-built nsjail executable and library for Python developers

Project description

python-nsjail

Prebuilt nsjail executables packaged as Python wheels with a simple Python API

CI GitHub tags PyPI version PyPI - Python Version PyPI - Implementation PyPI - Status PyPI - License

Overview

Just install and use — no compilation required. python-nsjail provides prebuilt nsjail binaries as Python wheels, making the powerful Linux namespace sandbox immediately available.

System Requirements

  • OS: Linux only
  • Kernel: Linux 5.10+ (some nsjail features require newer kernel syscalls)
  • Permissions: Using nsjail requires CAP_SYS_ADMIN or root
  • Python: Python 3.9+

Platform Compatibility

Platform libc Compatible With CPU Requirement
manylinux_2_34_x86_64 glibc 2.34 Ubuntu 22.04+, Debian 12+, RHEL 9+ x86-64-v2* (SSE4.2, POPCNT)
manylinux_2_34_aarch64 glibc 2.34 ARM64 systems ARM64 (v8+)
musllinux_1_2_x86_64 musl 1.2 Alpine Linux, other musl-based x86-64-v2* (SSE4.2, POPCNT)
musllinux_1_2_aarch64 musl 1.2 Alpine Linux ARM64 ARM64 (v8+)

⚠️ x86-64-v2 Note:
The x86_64 wheels are built with manylinux_2_34 containers which use x86-64-v2 by default. This requires a CPU from ~2010 or later (supports SSE4.2 and POPCNT instructions). Most modern systems support this. If you need to run on older x86-64 hardware (pre-2010), please use the source distribution or build from source.

Installation

pip install python-nsjail

Now run:

nsjail --help

You got nsjail installed!

Where is the nsjail binary?

The installation location depends on how you install:

Virtual environment (recommended):

python -m venv .venv
source .venv/bin/activate
pip install python-nsjail
# Binary: .venv/bin/nsjail

User install:

pip install --user python-nsjail
# Binary: ~/.local/bin/nsjail

System install (requires root):

pip install python-nsjail
# Binary: /usr/local/bin/nsjail

Verify Installation

nsjail --help

and the status(in python environment's scripts directory):

nsjail-status

Output:

nsjail status:
  System PATH:   /usr/bin/nsjail
  Bundled:       /path/to/bundled/nsjail
  Script:        /path/to/wrapper/nsjail

Package version: 0.1.0
Bundled nsjail:  3.6

Getting the Binary Path from Python

If you need the nsjail binary path in your scripts:

from nsjail import bundled_binary

nsjail_path = bundled_binary()
print(nsjail_path)  # /absolute/path/to/nsjail

Or use locate_nsjail() which respects the NSJAIL environment variable and checks system paths:

from nsjail import locate_nsjail

nsjail_path = locate_nsjail()  # Returns path with priority: env var > system > bundled

Priority:

  1. NSJAIL environment variable (if set)
  2. System paths: /usr/local/bin, /usr/bin
  3. Bundled binary (fallback)

Python API

The library provides simple functions for creating nsjail subprocesses. Both synchronous and asynchronous APIs are available.

Basic Usage

Async API:

import asyncio
import subprocess
from nsjail import async_create_nsjail, NsjailOptions

async def main():
    # Basic usage - output to terminal
    proc = await async_create_nsjail(
        command=["/bin/echo", "hello"],
        options=NsjailOptions(chroot="/"),
    )
    await proc.wait()

    # Capture output
    proc = await async_create_nsjail(
        command=["/bin/cat", "/etc/hostname"],
        options=NsjailOptions(chroot="/", user="nobody"),
        stdout=subprocess.PIPE,
    )
    output = await proc.stdout.read()
    print(output.decode())

asyncio.run(main())

Sync API:

import subprocess
from nsjail import create_nsjail, NsjailOptions

# Capture output synchronously
proc = create_nsjail(
    command=["/bin/echo", "hello"],
    options=NsjailOptions(chroot="/"),
    stdout=subprocess.PIPE,
)
output, _ = proc.communicate()
print(output.decode())

Stream Merging

For processes that output to both stdout and stderr, use merge_streams:

import asyncio
import subprocess
from nsjail import async_create_nsjail, merge_streams, NsjailOptions

async def main():
    proc = await async_create_nsjail(
        command=["/bin/sh", "-c", "echo out; echo err >&2"],
        options=NsjailOptions(chroot="/"),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    async for source, chunk in merge_streams(proc):
        if source == "stdout":
            print(f"stdout: {chunk.decode()}")
        else:
            print(f"stderr: {chunk.decode()}", file=sys.stderr)

asyncio.run(main())

Using nsenter

Enter an existing container's namespace with async_create_nsenter:

import asyncio
import subprocess
from nsjail import async_create_nsenter

async def main():
    # Run 'ip addr' inside container 1234's network namespace
    proc = await async_create_nsenter(
        target_pid=1234,
        namespaces=["net"],
        command=["ip", "addr"],
        stdout=subprocess.PIPE,
    )
    output = await proc.stdout.read()
    print(output.decode())

asyncio.run(main())

Inspect Command Arguments

For debugging or testing, you can build the nsjail arguments without executing:

from nsjail import build_nsjail_args, NsjailOptions

args = build_nsjail_args(
    options=NsjailOptions(chroot="/", user="nobody"),
    config_file="/path/to/config.cfg",
)
print("nsjail", *args, "--", "/bin/echo", "hello")
# Output: nsjail --chroot / --user nobody --config /path/to/config.cfg -- /bin/echo hello

Passing Additional Arguments

All *args and **kwargs are passed directly to the underlying subprocess creation functions:

import subprocess
from nsjail import async_create_nsjail, NsjailOptions

# Pass cwd, env, and other subprocess.Popen / asyncio.create_subprocess_exec arguments
proc = await async_create_nsjail(
    command=["/bin/sh", "-c", "echo $FOO"],
    options=NsjailOptions(chroot="/"),
    stdout=subprocess.PIPE,
    cwd="/tmp",
    env={"FOO": "value"},
)

NsjailOptions

Configure nsjail with NsjailOptions:

from nsjail import NsjailOptions

options = NsjailOptions(
    chroot="/srv/jail",           # Chroot directory
    user=65534,                    # Run as user (UID)
    group=65534,                   # Run as group (GID)
    hostname="sandbox",            # Set hostname
    cwd="/tmp",                    # Working directory inside jail
    env={"HOME": "/tmp"},          # Environment variables
    bindmount=["/tmp:/tmp"],       # Read-write bind mounts
    bindmount_ro=["/lib:/lib"],    # Read-only bind mounts
    tmpfsmount=["/tmp"],           # Temporary filesystem mounts
    time_limit=60,                 # Wall time limit in seconds
    memory_limit=512,              # Memory limit in MB
    # ... see NsjailOptions for all options
)

Environment Variable

NSJAIL - Override the nsjail binary path (for Python API only)

export NSJAIL=/custom/path/to/nsjail

Supports ~ and $VAR expansion:

export NSJAIL=~/local/bin/nsjail
export NSJAIL=$XDG_DATA_HOME/nsjail/bin/nsjail

API Reference

Async Functions

  • async_create_nsjail(command, options=None, config_file=None, *args, **kwargs) - Create async nsjail subprocess
  • async_create_nsenter(target_pid, namespaces, command, options=None, *args, **kwargs) - Create async nsenter subprocess
  • merge_streams(proc, chunk_size=8192, stdout=True, stderr=True) - Merge stdout/stderr streams

Sync Functions

  • create_nsjail(command, options=None, config_file=None, *args, **kwargs) - Create sync nsjail subprocess
  • create_nsenter(target_pid, namespaces, command, options=None, *args, **kwargs) - Create sync nsenter subprocess

Helper Functions

  • build_nsjail_args(options=None, config_file=None) - Build nsjail command-line arguments
  • build_nsenter_args(target_pid, namespaces, options=None) - Build nsenter command-line arguments

Classes

  • NsjailOptions - nsjail configuration options
  • NsenterOptions - nsenter configuration options

Locator Functions

  • locate_nsjail() - Find nsjail binary (respects NSJAIL env var)
  • bundled_binary() - Get bundled nsjail binary path

Building from Source

For development or building from source, see CONTRIBUTING.md.

License

  • nsjail: Apache-2.0 (see google/nsjail)
  • python-nsjail packaging: Apache-2.0

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

python_nsjail-0.3.0a1-py3-none-musllinux_1_2_x86_64.whl (3.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

python_nsjail-0.3.0a1-py3-none-musllinux_1_2_aarch64.whl (3.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

python_nsjail-0.3.0a1-py3-none-manylinux_2_34_x86_64.whl (1.9 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

python_nsjail-0.3.0a1-py3-none-manylinux_2_34_aarch64.whl (1.7 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ ARM64

File details

Details for the file python_nsjail-0.3.0a1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0a1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6591641fa9a1aadf91393f0345ac9bbc9df78b925129ee58a51227937d81d54c
MD5 dae1e90f2273e2f650555ee528950c47
BLAKE2b-256 c5541856f79edfc6ffa81348804f6c35cb69e25a35fd9a67b84576c464dd02f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0a1-py3-none-musllinux_1_2_x86_64.whl:

Publisher: build-and-publish.yml on tanbro/python-nsjail

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

File details

Details for the file python_nsjail-0.3.0a1-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0a1-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 6ed13ac929af0d38fe87f21c1f75f109cd55fc0d82baec9f02bd9dcaa8850e0c
MD5 c5103393588f95ebb71612075daf52fb
BLAKE2b-256 4a4938c57934e28443a8054ecd1c1add6e3e5cb750272fec29e05c4f771eb448

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0a1-py3-none-musllinux_1_2_aarch64.whl:

Publisher: build-and-publish.yml on tanbro/python-nsjail

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

File details

Details for the file python_nsjail-0.3.0a1-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0a1-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 d1c4f41de7be8ff4d34e3ac0c852c94165618e05202efe5482fb5c96ae03eefe
MD5 24a3ee1a44d538d1728c8ae2954bde12
BLAKE2b-256 db363329cf874e30acd2e5dff3a8fdf8dcd673ec573abbf832ec772064d85298

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0a1-py3-none-manylinux_2_34_x86_64.whl:

Publisher: build-and-publish.yml on tanbro/python-nsjail

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

File details

Details for the file python_nsjail-0.3.0a1-py3-none-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0a1-py3-none-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 2427dc08847f72bc7994fe41c03ba9c38bae1140e06cca839cdfcb2d60bf6ad9
MD5 003324d7cedf29d5a448965f8214a280
BLAKE2b-256 555dae1189efdde93fb5a96ed75985f06507f7889bfeec8799cf2cc523fcc4a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0a1-py3-none-manylinux_2_34_aarch64.whl:

Publisher: build-and-publish.yml on tanbro/python-nsjail

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page