Skip to main content

box

Manage VirtualBox virtual machines from the command line.

box imports an Ubuntu cloud image as a VirtualBox machine, seeds it with cloud-init (a passwordless-sudo box user, your SSH key, a static host-only address) and gets you a shell in it — one command per lifecycle step, no VBoxManage incantations.

It is a Python port of the box vbox provider from gitlab.com/xtec/box, packaged on its own so it installs with uv/pip instead of a Rust toolchain. Sibling of wslx, which ports the WSL provider the same way. Machines created by either tool are interchangeable: same config directory, same cloud-init, same box user, same SSH key.

Install

uv tool install boxctl

or run it without installing:

uvx --from boxctl box list

pip install boxctl works too. Python 3.11+.

The distribution is named boxctl because box is taken on PyPI; the command it installs is box. A boxctl alias is installed alongside it in case something else on your PATH already answers to box.

Use

box create alfa           # import a new Ubuntu machine named alfa
box ssh alfa              # start it if needed, wait for sshd, open a shell
box list                  # every machine box made, with state and address
box stop alfa             # ACPI power button, wait for poweroff
box start alfa -c 4 -m 4096   # boot headless with 4 CPUs and 4 GB RAM
box resize alfa 40        # grow the disk to 40 GB, and the partition inside it
box delete alfa           # power off, unregister, delete the disks

create, start, stop and delete take any number of names:

box create alfa beta gamma

Images

box create alfa --image ubuntu   # default
box create alfa --image coreos
box create alfa --image fedora
Image Source Provisioning
ubuntu Ubuntu 22.04 cloud OVA, downloaded and cached cloud-init seed ISO
coreos Fedora CoreOS 37 OVA, downloaded and cached Ignition guest property
fedora <config>/ova/fedora-37.ova, supplied by you none

Fedora Cloud publishes no VirtualBox appliance, so there is nothing for box to download and no network layout it can rely on; drop your own OVA at that path and box will import it as-is.

What a machine looks like

  • user box, password password, passwordless sudo, your ~/.ssh/id_ed25519.pub in authorized_keys
  • a NAT adapter for outbound traffic (enp0s3) and a host-only adapter (enp0s8) with a static address, so box ssh works without DHCP leases
  • hostname set to the machine name
  • snapd disabled, floppy controller blacklisted, cloud-init disabled after the first boot

Addresses

Host-only addresses are allocated by box from 192.168.56.15 upward and stored in the machine's own VirtualBox extra data, so they survive reboots. The range stops at .100: VirtualBox's host-only interface is .1 and its DHCP server hands out .101.254.

Where things live

What Where
Machines (.vbox, disks, seed.iso) ~/.config/box/virtualbox/<name>/
Downloaded OVA appliances ~/.config/box/cache/
Locally supplied appliances ~/.config/box/ova/
SSH key pair ~/.ssh/id_ed25519

On Windows the config directory is %APPDATA%\box instead. box delete removes a machine's folder; the SSH key and the OVA cache are left alone.

box list only shows machines box created — it owns a directory per machine, and that listing is what it walks. A directory whose machine VirtualBox no longer knows about (deleted from the GUI, say) is pruned as a side effect.

Requirements

VBoxManage on PATH — on Windows box also honours the installer's VBOX_MSI_INSTALL_PATH. box ssh and box resize additionally need an ssh client. The package installs and imports anywhere so it can be developed and tested on a machine with no VirtualBox at all.

Development

uv sync --all-groups
uv run pytest
uv run ruff check

The test suite needs neither VirtualBox nor a network: everything that shells out is covered through its pure parts — VBoxManage output parsing, host address allocation, cloud-init and Ignition rendering, seed ISO structure, key generation — with subprocess stubbed at the boundary.

Differences from the Rust box vbox

Behaviour is otherwise a faithful port.

  • box stop gives up with an error instead of pressing the ACPI button forever when a guest ignores it.
  • VBoxManage output parsing keeps values containing = (rec_screen_opts), which the Rust port's regexes silently dropped.
  • The generated private key always uses LF line endings, on Windows too. The Rust port wrote CRLF and then had to sed the CRs out again after copying the key into a machine.
  • The netplan file box writes declares version: 2, which netplan requires.
  • The seed ISO is built with pycdlib rather than a hand-rolled ISO 9660 writer, and carries Joliet and Rock Ridge so the guest sees user-data rather than its 8.3 alias.
  • box ip <name> is new; box update is gone, since uv tool upgrade boxctl does that job.

License

AGPL-3.0-only. © David de Mingo.

Download files

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

Source Distribution

boxctl-0.1.0.tar.gz (30.9 kB view details)

Uploaded Source

Built Distribution

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

boxctl-0.1.0-py3-none-any.whl (33.4 kB view details)

Uploaded Python 3

File details

Details for the file boxctl-0.1.0.tar.gz.

File metadata

  • Download URL: boxctl-0.1.0.tar.gz
  • Upload date:
  • Size: 30.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for boxctl-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b3665f3e171ab61a0881366f5898f891faaf640a53a11712192296a88624182d
MD5 fafe0b2d9a02a6f8595e74e707afbfa9
BLAKE2b-256 da526bb6fcebd54f154dd8a05821f2ee1a8e1bd8c2731eb595c36a7931d6bc56

See more details on using hashes here.

File details

Details for the file boxctl-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: boxctl-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for boxctl-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b5eb25e32020f854266764d267cf179dbcba31e326bd9e9dbeb2b071a9796bf0
MD5 f6c15c8bda37b1eb912d7043ca7b1034
BLAKE2b-256 dd9833c904f83d3979dddae7ed8b356334b8843ba63c9d446ef409f7824a44f1

See more details on using hashes here.

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