Skip to content

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:

curl --fail --silent --show-error --location \
  https://raw.githubusercontent.com/carlmontanari/boxen/main/install.sh | sh -

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:

boxen --version

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:

docker version
docker info
ls -l /dev/kvm
ls -ld /boot /lib/modules

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:

sudo install -m 0755 dist/boxen /usr/local/bin/boxen
boxen --help
boxen build --help

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.

images/
├── nxosv.9.2.4.qcow2
└── OVMF.fd

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.

Next: package and deploy your first lab.