A Go CLI and library that runs commands in a sandboxed environment using bubblewrap, and resource limits using cgroups.
I wanted to have docker-like isolation when running some binaries that I don't trust, or when I wanted to make sure that they don't have network access, bwrap directly seemed too low-level, and also I couldn't set resource limits on the app, this package use bwrap for sandboxing, and cgroups(via systemd-run) for resource limits.
curl -Lo isolate.tar.gz https://github.com/Shadi/isolate/releases/download/v1.1.0/isolate-linux-amd64.tar.gz
tar xzf isolate.tar.gz
# either use directly
./isolate --help
# or install system-wide
sudo mv isolate /usr/local/bin/go install github.com/shadi/isolate/cmd/isolate@latestbwrap and systemd-run must be available on the host.
go install github.com/shadi/isolate/cmd/isolate@latest
isolate -v "$HOME/.local:$HOME/.local:ro" -v "$HOME/.claude:$HOME/.claude" -v "$HOME/.claude.json:$HOME/.claude.json" claudeadd an alias to .bashrc:
alias iclaude='isolate -v "$HOME/.local:$HOME/.local:ro" -v "$HOME/.claude:$HOME/.claude" -v "$HOME/.claude.json:$HOME/.claude.json" claude'
isolate [flags] command [args...]
| Flag | Description |
|---|---|
--max-memory |
Memory limit using k8s format (256Mi, 1Gi, 512M) — enforced via cgroups |
--max-cpu |
CPU limit in cores or millicores (1, 0.5, 500m) — enforced via cgroups |
-v, --volume |
Bind mount as target:source[:ro] (repeatable) |
--mount-cwd |
Auto-mount current directory into sandbox (default: true, disable with --mount-cwd=false) |
--no-network |
Disable network access |
--full-etc |
Mount all of /etc (default only mounts safe paths like resolv.conf, ssl/, hosts) |
--bare |
Skip all default mounts — you control everything via --volume |
--workdir |
Working directory inside the sandbox |
Run a command in the current directory (auto-mounted by default):
isolate /usr/bin/python3 train.pyRun with memory and CPU limits:
isolate --max-memory 256Mi --max-cpu 2 /usr/bin/python3 train.pyMount an additional directory and restrict network:
isolate --no-network -v /data:/mnt/datasets /bin/lsFull /etc access (exposes secrets — use only when needed):
isolate --full-etc /usr/bin/curl https://example.comBare mode with manual mounts:
isolate --bare -v /usr:/usr:ro -v /app:/home/user/code /usr/bin/myappUnless --bare is set, the sandbox includes:
- Current working directory (read-write, same path inside sandbox)
/usr(read-only),/lib,/bin,/sbin(symlinks into/usr)/proc,/dev,/tmp- Safe
/etcsubset:resolv.conf,ssl/,ca-certificates/,ld.so.*,nsswitch.conf,localtime,hosts - systemd-resolved socket (for DNS)
import "github.com/shadi/isolate/sandbox"
s, _ := sandbox.New(&sandbox.Config{
Command: "/usr/bin/python3",
Args: []string{"train.py"},
MaxMemory: "256Mi",
MaxCPU: "500m",
NoNetwork: true,
Volumes: []sandbox.Volume{{Source: "/home/user/ml", Target: "/workspace"}},
})
s.Run(context.Background())| Resource | Mechanism |
|---|---|
| Filesystem isolation | bubblewrap namespaces |
| Memory limit | systemd-run -p MemoryMax=... (cgroups v2) |
| CPU limit | systemd-run -p CPUQuota=... (cgroups v2) |
| Network isolation | bwrap --unshare-net |