Installation¶
Boxen has two parts: a CLI on the packaging host and an agent image containing QEMU and the container-side runtime. Download a released CLI or build it from source.
Download the CLI¶
GitHub releases include CLI binaries for Linux and macOS (darwin), on both AMD64 and ARM64. The installer detects your OS and architecture, downloads the matching archive from the latest stable release, verifies its SHA-256 checksum, and installs boxen into /usr/local/bin. It requires curl, tar, and either sha256sum or shasum, and uses sudo when you are not root.
Download and run the installer in one command:
Review the full script below, then copy and paste it into your shell. This is the same script used by the quick installer; the subshell keeps its settings and cleanup trap separate from your current shell.
#!/bin/sh
(
set -eu
case "$(uname -s)" in
Linux) os=linux ;;
Darwin) os=darwin ;;
*) echo "Unsupported operating system: $(uname -s)" >&2; exit 1 ;;
esac
case "$(uname -m)" in
x86_64|amd64) arch=amd64 ;;
aarch64|arm64) arch=arm64 ;;
*) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;;
esac
repo=https://github.com/carlmontanari/boxen
tag=${BOXEN_TAG:-$(curl --fail --silent --show-error --location --head \
--output /dev/null --write-out '%{url_effective}' "$repo/releases/latest")}
tag=${tag##*/}
version=${tag#v}
archive="boxen_${version}_${os}_${arch}.tar.gz"
tmp_dir=$(mktemp -d)
trap 'rm -rf "$tmp_dir"' 0
trap 'exit 1' HUP INT TERM
curl --fail --silent --show-error --location \
"$repo/releases/download/$tag/$archive" --output "$tmp_dir/$archive"
curl --fail --silent --show-error --location \
"$repo/releases/download/$tag/boxen_${version}_checksums.txt" \
--output "$tmp_dir/checksums.txt"
expected=$(awk -v archive="$archive" '$2 == archive {print $1; exit}' "$tmp_dir/checksums.txt")
if command -v sha256sum >/dev/null 2>&1; then
actual=$(sha256sum "$tmp_dir/$archive")
else
actual=$(shasum -a 256 "$tmp_dir/$archive")
fi
if [ -z "$expected" ] || [ "${actual%% *}" != "$expected" ]; then
echo "Checksum verification failed for $archive" >&2
exit 1
fi
tar -xzf "$tmp_dir/$archive" -C "$tmp_dir" boxen
if [ "$(id -u)" -eq 0 ]; then
install -d /usr/local/bin
install -m 0755 "$tmp_dir/boxen" /usr/local/bin/boxen
else
sudo install -d /usr/local/bin
sudo install -m 0755 "$tmp_dir/boxen" /usr/local/bin/boxen
fi
printf 'Installed boxen %s to /usr/local/bin/boxen\n' "$version"
)
Check the installed CLI:
To install a specific release or a prerelease, set BOXEN_TAG to its exact tag before running either option, for example export BOXEN_TAG=v0.0.4. Each release includes boxen_<version>_checksums.txt; both options check the downloaded archive against it before installation.
| Host | Archive |
|---|---|
| Linux x86-64 | boxen_<version>_linux_amd64.tar.gz |
| Linux ARM64 | boxen_<version>_linux_arm64.tar.gz |
| macOS Intel | boxen_<version>_darwin_amd64.tar.gz |
| macOS Apple Silicon | boxen_<version>_darwin_arm64.tar.gz |
The downloaded CLI does not require Go. Packaging and running network OS guests still require a suitable Linux Docker host as described below.
Host requirements¶
Use a Linux x86-64 host for the documented packaging and lab workflows.
| Requirement | Why it matters |
|---|---|
Docker Engine and the docker CLI |
Boxen currently supports Docker only. The CLI must reach the daemon. |
Hardware virtualization and /dev/kvm |
QEMU uses KVM when the device exists. Nested platforms such as vJunos-router need nested virtualization. |
| Enough memory, CPU, and disk | Each guest reserves the resources in its profile. Packaging also needs room for a converted disk and image layers. |
Go at the version in .github/vars.env |
Needed only for source builds. make tools checks the exact toolchain version. |
| A vendor VM disk and required companion files | Boxen packages your files; it does not download the network OS. |
For Docker and Containerlab setup, follow their Docker Engine installation and Containerlab installation guides.
Check the host before building:
The builder runs privileged and mounts /boot and /lib/modules read-only for disk sparsification. Docker Desktop, a remote Docker daemon, and non-Linux hosts can behave differently: the builder must reach the host CLI's RPC server, and those mount paths belong to the Docker daemon's host. A local Linux daemon is the simplest setup.
Build from source¶
Install the Go toolchain specified by GO_VERSION in the repository, plus git, make, and Docker. Then:
git clone https://github.com/carlmontanari/boxen.git
cd boxen
cat .github/vars.env
go version
make build
make build-image
make build produces dist/boxen for linux/amd64. make build-image builds the agent image with QEMU, the Boxen binary, libscrapli, and the console definition. Its default tag is ghcr.io/carlmontanari/boxen:0.0.0, matching the version of a source-built CLI.
Install the CLI into your executable path:
You can also invoke dist/boxen directly from the repository.
Select a different builder image¶
The host CLI normally uses ghcr.io/carlmontanari/boxen:<CLI-version> as its builder. Set BOXEN_BUILDER_IMAGE if you built or obtained another tag:
make build-image BOXEN_IMAGE=boxen-agent:dev
BOXEN_BUILDER_IMAGE=boxen-agent:dev boxen build \
--disk /path/to/disk.qcow2 --profile /path/to/profile.yaml
The agent image is a packaging tool. It becomes a runnable NOS image only after boxen build adds a prepared disk and profile and changes its entrypoint.
Prepare your OS files¶
Choose an included profile. Keep firmware, boot media, or initial configuration files beside the disk when the profile lists them under extraFiles.
Use files you are entitled to use and keep their redistribution terms in mind when sharing a packaged image. Boxen does not change the OS license.
Documentation tools¶
Python and uv are needed only for the documentation site. make docs-serve installs pinned uv into .tools/bin if it is missing, then uses the locked docs environment. See documentation and publishing.