Skip to main content

Universal isolated development environment using kernel overlayfs

Project description

boq

Isolated development environment using Linux kernel overlayfs.

Features

  • All host tools available at original paths (no PATH hacks)
  • Configurable overlay directories (default: $HOME, /usr, /opt, /home/linuxbrew)
  • Passthrough paths that bypass overlay and share with host
  • Full file locking support (unlike fuse-overlayfs)
  • Protected from modifying system files
  • TOML-based configuration with 3-tier override system

Installation

Requires Python 3.11+ and podman.

# Install podman
sudo apt install podman

# Install boq (choose one)
pipx install boq          # Recommended: isolated global install
uv tool install boq       # Alternative: using uv
pip install boq           # Or: install to current environment

# For development
git clone <repo>
cd boq
uv pip install -e .               # Editable install

Note: Requires sudo for mounting kernel overlayfs.

Quick Start

# Create and start a boq
boq create dev

# Attach shell (exit to detach, container keeps running)
boq enter dev

# See what changed
boq diff dev

# Run a command in boq
boq run dev "make test"

# Stop boq
boq stop dev

# Remove boq
boq destroy dev

Commands

Command Description
create <name> Create a new boq and start container
enter [name] Attach shell to boq (starts if not running)
run <name> <cmd> Run a command in boq (must be running)
stop [name] Stop a running boq
destroy <name> Destroy a boq (fails if running, use --force-stop)
diff [name] [path] Show changes made in boq
status [name] Show boq status
list List all boq instances
completion -s <shell> Output shell completion script

Default name is default for commands that accept [name].

diff options

boq diff dev                      # Show all content changes
boq diff dev ~/project            # Filter by path (respects .gitignore)
boq diff dev --no-gitignore       # Include gitignored files
boq diff dev --include-metadata   # Include metadata-only changes

Shell Completion

# Bash: add to ~/.bashrc
eval "$(boq completion -s bash)"

# Zsh: add to ~/.zshrc
eval "$(boq completion -s zsh)"

Configuration

TOML-based configuration with 3-tier override system:

  1. defaults.toml (shipped with package) - base defaults
  2. ~/.boq/config.toml (user global) - override defaults
  3. ~/.boq/<name>/config.toml (per-boq) - override for specific boq

Higher priority overrides lower. Lists append by default (use <key>_replace to fully replace).

Example ~/.boq/config.toml

[container]
# Change default shell
shell = "/bin/zsh"

# Change base image
image = "ubuntu:24.04"

[container.env]
# Add custom environment variables
MY_VAR = "value"

[overlays]
# Add additional overlay directory
"/data" = "data"

[passthrough]
# Add paths that bypass overlay (appends to default list)
paths = [
    "$HOME/.my-tool",
]

# Or replace the entire list
paths_replace = [
    "$HOME/.zsh_history",
    "$HOME/.claude",
]

Default Configuration

[container]
image = "ubuntu:22.04"
shell = "/bin/bash"
capabilities = ["SYS_PTRACE"]

[overlays]
"$HOME" = "home"
"/usr" = "usr"
"/opt" = "opt"
"/home/linuxbrew" = "linuxbrew"

[passthrough]
paths = [
    "$HOME/.zsh_history",
    "$HOME/.bash_history",
    "$HOME/.claude",
    "$HOME/.gemini",
    "$HOME/.codex",
    "$HOME/.factory",
]

[mounts]
readonly = ["/bin", "/lib", "/lib64", "/lib32", "/sbin"]
direct = []

Environment variable expansion ($HOME, $USER, etc.) is supported in all string values.

How It Works

  • create sets up overlays and starts container (keeps running)
  • enter attaches a shell; exiting detaches but container stays running
  • run executes a single command (container must be running)
  • stop explicitly stops container and unmounts overlays
  • Container manages its own /proc, /sys, /dev, /tmp

Overlay Directories

Multiple directories are overlayed (copy-on-write) using kernel overlayfs. Changes are stored in ~/.boq/<name>/<overlay>/upper/.

Read-only Mounts

  • /bin, /lib, /lib64, /lib32, /sbin - essential system directories, read-only from host

Known Limitations

Host file changes visible in running boq

Symptom: If you run git pull on the host while boq is running, new files appear inside the boq.

Cause: Overlayfs lowerdir is live, not a snapshot.

Workaround: Do NOT modify files on the host while boq is running.

  • To update code: run git pull inside the boq, OR
  • Stop the boq first, update on host, then re-enter

Troubleshooting

DNS resolution fails inside container

Error: "Temporary failure in name resolution"

Cause: systemd-resolved uses a stub resolver at 127.0.0.53 which doesn't work inside the container.

Solution: This tool mounts /run/systemd/resolve/resolv.conf (with actual upstream DNS servers) as /etc/resolv.conf. If your system uses a different DNS setup, override dns_resolv in config.

Files under /mnt not visible

Error: "No such file or directory" for files under /mnt/...

Cause: /mnt often contains nested mount points that overlayfs cannot see through.

Solution: Add /mnt to direct mounts in your config:

# ~/.boq/config.toml
[mounts]
direct = ["/mnt"]

Design Notes

Why kernel overlayfs instead of fuse-overlayfs?

  • fuse-overlayfs mounts are only accessible by the user who created them (permission issues with podman)
  • fuse-overlayfs doesn't fully support POSIX file locking
  • Kernel overlayfs requires sudo but provides full compatibility

Project details


Download files

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

Source Distribution

boq-0.0.1.tar.gz (14.0 kB view details)

Uploaded Source

Built Distribution

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

boq-0.0.1-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file boq-0.0.1.tar.gz.

File metadata

  • Download URL: boq-0.0.1.tar.gz
  • Upload date:
  • Size: 14.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for boq-0.0.1.tar.gz
Algorithm Hash digest
SHA256 c5211c7879f4af7bf111aae0c07fd18ad3098b4c140aef3989826f3f5b1ac4c4
MD5 9e5babf5a9c04a6ad2502b54deec1432
BLAKE2b-256 048de5c84ebf2271037cfb8e221952a56aef21c9c3be75fe42643e63f6615cde

See more details on using hashes here.

Provenance

The following attestation bundles were made for boq-0.0.1.tar.gz:

Publisher: publish.yml on zhengbuqian/boq

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

File details

Details for the file boq-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: boq-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 16.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for boq-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8b29634e0978d45b02671fe4431c5664e942dcb2f312ddb749074b55de49a919
MD5 00db501f1449328d604228a2362c7259
BLAKE2b-256 5bc6f8e35ce93ff4e240a1fcb5e2944b466f65b727a2e5b231ddccf953f2cb96

See more details on using hashes here.

Provenance

The following attestation bundles were made for boq-0.0.1-py3-none-any.whl:

Publisher: publish.yml on zhengbuqian/boq

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