Joblet is a micro-container runtime for running Linux jobs with: Process and filesystem isolation (PID namespace, chroot) Fine-grained CPU, memory, and IO throttling (cgroups v2) Secure job execution with mTLS and RBAC Built-in scheduler, SSE log streaming, and multi-core pinning Ideal for: Agentic AI Workloads (Untrusted code)
Complete guide for building custom runtimes for Joblet using the declarative YAML-based builder.
Joblet uses a declarative runtime builder that enables:
schema_version: "1.0"
name: python-3.11-ml
version: 1.0.0
description: Python 3.11 with machine learning packages
base:
language: python
version: "3.11"
pip:
- numpy
- pandas
- scikit-learn
environment:
PYTHONUNBUFFERED: "1"
rnx runtime validate ./runtime.yaml
# Build on remote server
rnx runtime build ./runtime.yaml
# Or with verbose output
rnx runtime build -v ./runtime.yaml
# Validate before building (comprehensive server-side validation)
rnx runtime validate ./runtime.yaml
rnx job run --runtime=python-3.11-ml python -c "import numpy; print(numpy.__version__)"
# Required: Schema version (must be "1.0")
schema_version: "1.0"
# Required: Runtime name (lowercase, hyphens, dots, max 64 chars)
name: my-runtime
# Required: Semantic version (X.Y.Z)
version: 1.0.0
# Required: Description (max 256 chars)
description: My custom runtime environment
# Required: Base language configuration
base:
language: python # python | java | node | go | rust
version: "3.11" # Language-specific version
# Optional: Python packages to install via pip
pip:
- numpy
- pandas>=2.0.0
- scikit-learn==1.3.2
# Optional: Pip options (e.g., custom index)
pip_options: "--index-url https://pypi.example.com/simple"
# Optional: Node.js packages to install via npm
npm:
- express
- lodash
# Optional: Additional library patterns to copy to isolated runtime
# Use this for system libraries installed via pre_install hooks
libraries:
- libopenblas*
- libgfortran*
# Optional: Environment variables
environment:
PYTHONUNBUFFERED: "1"
MY_VAR: "value"
# Optional: Runtime requirements
requirements:
gpu: false
cuda_version: "12.0"
# Optional: Supported platforms (default: all)
platforms:
- ubuntu-amd64
- ubuntu-arm64
- rhel-amd64
# Optional: Build hooks
hooks:
timeout: "30m" # Hook timeout (default: 20m)
pre_install: |
echo "Running before package installation"
post_install: |
echo "Running after package installation"
| Field | Required | Description |
|---|---|---|
schema_version |
Yes | Must be “1.0” |
name |
Yes | Runtime identifier (lowercase, hyphens, dots) |
version |
Yes | Semantic version X.Y.Z |
description |
Yes | Human-readable description (max 256 chars) |
base.language |
Yes | Base language: python, java, node, go, rust |
base.version |
Yes | Language version (e.g., “3.11”, “21”) |
pip |
No | List of Python packages |
pip_options |
No | Additional pip install options |
npm |
No | List of Node.js packages |
libraries |
No | Additional library patterns to copy (e.g., libopenblas*) |
environment |
No | Environment variables |
requirements |
No | GPU and memory requirements |
platforms |
No | Supported platforms |
hooks |
No | Pre/post-install scripts |
The runtime builder executes a 14-phase pipeline:
| Phase | Name | Description |
|---|---|---|
| 1 | Parse & Validate | Parse YAML and validate schema |
| 2 | Detect Platform | Identify OS, architecture, package manager |
| 3 | Check Disk Space | Ensure sufficient disk space (1GB minimum) |
| 4 | Validate Packages | Verify packages are available |
| 5 | Prepare Directories | Create runtime directory structure |
| 6 | Pre-install Hook | Run pre-install script (if defined) |
| 7 | Install Base | Install base language packages |
| 8 | Install Packages | Install pip/npm packages |
| 9 | Post-install Hook | Run post-install script (if defined) |
| 10 | Copy Binaries | Copy language binaries to isolated dir |
| 11 | Copy Libraries | Copy required shared libraries |
| 12 | Copy Configuration | Copy SSL certs, resolv.conf, etc. |
| 13 | Generate Config | Generate runtime.yml for joblet |
| 14 | Validate Build | Verify build integrity |
Runtimes are installed to: /opt/joblet/runtimes/{name}/{version}/
Directory structure:
/opt/joblet/runtimes/python-3.11-ml/1.0.0/
├── runtime.yml # Generated runtime configuration
└── isolated/ # Isolated filesystem
├── usr/
│ ├── bin/ # Binaries (python3, pip, etc.)
│ └── lib/ # Libraries
├── lib/ # System libraries
├── etc/ # Configuration files
└── tmp/ # Temporary directory
runtime.ymlThe build generates a runtime.yml with comprehensive metadata:
name: python-3.11-ml
language: python
language_version: "3.11"
version: 1.0.0
description: Python 3.11 with machine learning packages
mounts: [...]
environment:
PYTHONUNBUFFERED: "1"
PATH: /usr/local/bin:/usr/bin:/bin
packages:
- numpy==1.26.2
- pandas==2.1.3
libraries:
- libopenblas*
- libgfortran*
requirements:
architectures: [amd64]
build_info:
built_at: "2025-12-22T17:43:00Z"
platform: ubuntu-amd64
View runtime details:
rnx runtime info python-3.11-ml
base:
language: python
version: "3.11" # 3.9, 3.10, 3.11, 3.12
pip:
- numpy
- pandas
Installed packages: python3.X, python3.X-dev, python3.X-venv, python3-pip, libssl-dev, zlib1g-dev, libffi-dev
base:
language: java
version: "21" # 11, 17, 21
# No additional packages needed - JVM is included
Installed packages: openjdk-X-jdk, ca-certificates
base:
language: node
version: "20" # 18, 20
npm:
- express
- lodash
Installed packages: nodejs, npm
base:
language: go
version: "1.21"
Installed packages: golang, git
base:
language: rust
version: "1.75"
Installed packages: rustc, cargo
schema_version: "1.0"
name: python-3.11-ml
version: 1.0.0
description: Python 3.11 with machine learning packages
base:
language: python
version: "3.11"
pip:
- numpy
- pandas
- scikit-learn
- matplotlib
# Copy system libraries needed by ML packages
libraries:
- libopenblas*
- libgfortran*
- libgomp*
environment:
PYTHONUNBUFFERED: "1"
hooks:
pre_install: |
apt-get install -y libopenblas-dev || yum install -y openblas-devel
schema_version: "1.0"
name: openjdk-21
version: 1.0.0
description: OpenJDK 21 runtime
base:
language: java
version: "21"
environment:
JAVA_OPTS: "-Xmx512m"
schema_version: "1.0"
name: python-analytics
version: 1.0.0
description: Python for data analytics
base:
language: python
version: "3.11"
pip:
- pandas
- matplotlib
- seaborn
pip_options: "--index-url https://pypi.company.com/simple"
environment:
PYTHONUNBUFFERED: "1"
schema_version: "1.0"
name: python-custom
version: 1.0.0
description: Python with custom setup
base:
language: python
version: "3.11"
pip:
- numpy
hooks:
timeout: "30m"
pre_install: |
echo "Configuring system before installation"
# Custom pre-install commands
post_install: |
echo "Running post-installation tasks"
python3.11 -c "import numpy; print('NumPy version:', numpy.__version__)"
Runs after base package installation but before pip/npm packages.
Use cases:
Runs after all packages are installed.
Use cases:
Hooks execute with:
Error: package not found: python3.11-dev
Solution: The package name might differ on your platform. Check available packages:
apt-cache search python3.11
Error: pip install failed: Could not find a version that satisfies the requirement
Solutions:
pip_options for custom indexError: failed to create directory: permission denied
Solution: Ensure joblet service has write access to /opt/joblet/runtimes/
Error: insufficient disk space: 500 MB available, need at least 1024 MB
Solution: Free up disk space on the server or expand the volume.
Error: pre-install hook timed out after 20m
Solution: Increase timeout in hooks configuration:
hooks:
timeout: "60m"
pre_install: |
# Long-running installation
Minimal dependencies - Only include packages you need
rnx runtime validate ./runtime.yaml
rnx runtime validate ./runtime.yaml
Questions? Check Troubleshooting or create an issue on GitHub.