Installation
Bailey is Linux only. It builds with a stable Rust toolchain and has no system dependencies for the enforcement path.
From a release
Each release carries a statically linked binary for x86_64 and aarch64, so it runs whatever your distribution's glibc is. The archive also holds shell completions, the man page, and the licences.
tar -xzf bailey-<version>-x86_64-unknown-linux-musl.tar.gz
cd bailey-<version>-x86_64-unknown-linux-musl
install -Dm755 bailey ~/.local/bin/bailey
install -Dm644 completions/bailey.fish ~/.config/fish/completions/bailey.fish
install -Dm644 bailey.1 ~/.local/share/man/man1/bailey.1Then ask what your kernel gives you:
bailey doctorThe audit recorder is not in the archive: it needs capabilities granted on your own machine and a nightly toolchain to build, so it comes from source. The sandbox itself does not need it.
From source
git clone https://github.com/QaidVoid/bailey
cd bailey
cargo build --releaseThe binary is at target/release/bailey. Put it somewhere on your PATH.
This build gives you everything except audit recording: the policy model, the cascading config, all enforcement layers, namespace isolation, reconciliation, profile generation, and the CLI.
The audit recorder
Audit mode records access with eBPF. The eBPF programs are loaded by a separate, minimal binary, bailey-bpf-helper, which is the only component that needs privilege. Keeping it separate means the main tool carries no eBPF code and needs no capabilities.
Building it needs a nightly toolchain and bpf-linker:
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
cargo install bpf-linker
cargo build --release -p bailey-bpf-helperThen grant the helper its capabilities, once:
sudo setcap cap_bpf,cap_perfmon+ep ./target/release/bailey-bpf-helperWith that in place, bailey audit runs unprivileged and drives the helper. If you would rather not use file capabilities, run the audit under sudo instead.
The target never runs privileged
The helper does not spawn the program being audited. The unprivileged main tool runs it and tells the helper which process to observe, so the program itself never inherits elevated privilege.
How the helper is found
In order:
- The path in the
BAILEY_BPF_HELPERenvironment variable. - A
bailey-bpf-helpernext to thebaileyexecutable. bailey-bpf-helperonPATH.
Checking your kernel
Bailey adapts to what the kernel offers, and reports what it cannot enforce. Ask it before running anything:
bailey doctorThat covers the Landlock ABI and what it does not reach, user namespaces, cgroup delegation, kernel BTF, and whether the audit helper can load its programs, each with what its absence costs. See knowing what was enforced.
By hand, if you want the raw answers:
# Landlock present?
grep -q landlock /sys/kernel/security/lsm && echo "landlock: yes"
# Unprivileged user namespaces, for the isolation layer?
cat /proc/sys/user/max_user_namespaces
# BTF, for the audit backend?
test -e /sys/kernel/btf/vmlinux && echo "btf: yes"See kernel requirements for what each feature affects and which kernel version introduced it.
Building and testing the workspace
cargo build # the main tool and the shared crate
cargo test # and their testsBoth act on the default members, so a stable toolchain and no system dependencies are enough.
cargo build --workspace
cargo test --workspaceThese add the privileged helper, which needs nightly and bpf-linker. Without them the build stops with a message naming what to install; nothing else in the workspace depends on that toolchain.
The eBPF programs themselves sit behind a bpf feature that only the helper's build script enables. They compile for the BPF target and nothing else, so without the gate every --workspace command would try to link them for your machine and fail.
Some tests need more than a toolchain: a delegated cgroup, unprivileged user namespaces, or the audit helper with its capabilities. Each of those self-skips with a note rather than failing, so a passing run on a restricted host is not proof that everything was exercised.