Installation
There are two ways to install vee:
- Download a prebuilt binary from the GitHub Releases page (fastest — no Go toolchain needed).
- Build from source (requires Go 1.21 or later).
Either way, vee drives QEMU, so the host QEMU packages listed under Prerequisites must be installed first.
Prebuilt vee binaries are published for every supported host on the
Releases page. Each release ships a
.tar.gz per platform plus a matching .sha256 checksum file:
| Platform | Asset |
|---|---|
| Linux (x86-64) | vee-linux-amd64.tar.gz |
| Linux (ARM64) | vee-linux-arm64.tar.gz |
| macOS (Apple Silicon) | vee-darwin-arm64.tar.gz |
| macOS (Intel) | vee-darwin-amd64.tar.gz |
| Windows (x86-64) | vee-windows-amd64.tar.gz |
Each snippet below grabs the latest release. For a specific version, swap
latest/download for download/<tag> (e.g. download/v0.2.0), and pick the
matching asset from the table above.
curl -LO https://github.com/Benehiko/vee/releases/latest/download/vee-linux-amd64.tar.gz
curl -LO https://github.com/Benehiko/vee/releases/latest/download/vee-linux-amd64.tar.gz.sha256
sha256sum -c vee-linux-amd64.tar.gz.sha256
tar xzf vee-linux-amd64.tar.gz
install -Dm755 vee "$HOME/.vee/bin/vee"
curl -LO https://github.com/Benehiko/vee/releases/latest/download/vee-darwin-arm64.tar.gz
curl -LO https://github.com/Benehiko/vee/releases/latest/download/vee-darwin-arm64.tar.gz.sha256
shasum -a 256 -c vee-darwin-arm64.tar.gz.sha256
tar xzf vee-darwin-arm64.tar.gz
mkdir -p "$HOME/.vee/bin" # stock BSD install(1) has no GNU -D
install -m755 vee "$HOME/.vee/bin/vee"
xattr -d com.apple.quarantine "$HOME/.vee/bin/vee" 2>/dev/null || true # unsigned binary
# Apple Silicon only: the same tarball carries the macOS-guest helper.
if [ -f vee-vz-helper ]; then
install -m755 vee-vz-helper "$HOME/.vee/bin/vee-vz-helper"
xattr -d com.apple.quarantine "$HOME/.vee/bin/vee-vz-helper" 2>/dev/null || true
fi
The darwin-arm64 tarball contains a second binary, vee-vz-helper, which
hosts macOS guests on Apple’s Virtualization.framework — one helper process per
running guest, the way qemu-system backs a QEMU VM. You only need it for
vee create --template macos; every other guest runs on QEMU and ignores it.
Install it in the same directory as vee, as the snippet above does. vee looks
for it under $VEE_VZ_HELPER first, then beside the running vee binary, then
in ~/.vee/bin, then on your PATH. It is ad-hoc codesigned with the
com.apple.security.virtualization entitlement, which macOS honours without a
paid Apple Developer account; a browser download arrives quarantined, and vee
clears that flag itself whenever it resolves the helper. From a source checkout
on an Apple Silicon Mac, make install builds, signs and installs it alongside
vee (make vz-helper does the helper alone).
See macOS guests for what that backend supports.
$Base = "https://github.com/Benehiko/vee/releases/latest/download"
iwr "$Base/vee-windows-amd64.tar.gz" -OutFile vee.tar.gz
iwr "$Base/vee-windows-amd64.tar.gz.sha256" -OutFile vee.tar.gz.sha256
# Verify the checksum:
if ((Get-Content vee.tar.gz.sha256).Split()[0].ToLower() -ne (Get-FileHash vee.tar.gz -Algorithm SHA256).Hash.ToLower()) { throw "checksum mismatch" }
tar xzf vee.tar.gz # tar ships with Windows 10+
New-Item -ItemType Directory -Force "$HOME\.vee\bin" | Out-Null
Move-Item -Force vee.exe "$HOME\.vee\bin\vee.exe"
Then add ~/.vee/bin to your PATH (next section) and jump to
Verify. If you plan to run VMs on boot, see
Run vee as a daemon.
Install the required system packages before building.
NoteManaged QEMU. For platforms where vee publishes avee-qemubundle, vee downloads a pinned, checksum-verified QEMU into~/.vee/bin/on first use and prefers it over any system QEMU. That bundle also carries the edk2/OVMF firmware under~/.vee/share/qemu/, so neither QEMU nor OVMF needs a system install. When no bundle is published for your platform, vee falls back to the system QEMU on yourPATH— install the packages below.
sudo pacman -S qemu-desktop edk2-ovmf openssh virtiofsd swtpm
sudo apt install qemu-system-x86 ovmf openssh-client virtiofsd swtpm
sudo dnf install qemu-kvm edk2-ovmf openssh-clients virtiofsd swtpm
| Package | Purpose |
|---|---|
qemu-system-x86_64 | VM execution engine |
qemu-img | Disk image creation |
ovmf | UEFI firmware |
openssh | vee ssh and vee tunnel |
virtiofsd | Host directory sharing into VMs — optional, see below |
swtpm | TPM 2.0 emulation (Windows template, x86_64 hosts — arm64 Windows guests attach no TPM) |
NoteOVMF firmware location. Distros ship OVMF under different names and directories — Arch puts it in
/usr/share/OVMF/x64/OVMF_*.4m.fd, Debian/Ubuntu/Mint in/usr/share/OVMF/OVMF_*_4M.fd, Fedora/RHEL in/usr/share/edk2/ovmf/. vee probes all of these automatically, so installing your distro’s OVMF package (ovmfon Debian-family,edk2-ovmfon Arch/Fedora) is all that’s needed. If your firmware lives somewhere unusual, overrideovmf_code_path/ovmf_vars_pathin~/.vee/config.yaml.When vee uses a managed QEMU bundle (see the note above), that bundle ships edk2/OVMF firmware under
~/.vee/share/qemu/, which vee prefers over any system OVMF — so no distro OVMF package is required in that case.
Notevirtiofsdis optional. When a VM first requests a virtiofs share and no systemvirtiofsdis found, vee builds a pinned, checksum-verified copy on demand into~/.vee/bin/virtiofsd— inside a host container (nerdctl/docker) if one is available, otherwise inside a temporary Ubuntu VM. Installing the distro package skips this on-demand build.
Your user must be in the kvm group to run hardware-accelerated VMs:
sudo usermod -aG kvm $USER
Log out and back in (or newgrp kvm) for the change to take effect.
git clone https://github.com/Benehiko/vee.git
cd vee
make install
This builds the binary and installs it to ~/.vee/bin/vee. Add that directory to your PATH:
echo 'export PATH="$HOME/.vee/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# bash — add to ~/.bashrc
source <(vee completion bash)
# zsh — add to ~/.zshrc
source <(vee completion zsh)
# fish — add to ~/.config/fish/config.fish
vee completion fish | source
vee --help
The daemon starts every VM marked autostart=true on boot, restarts any
that exit, and stops running VMs cleanly when the host shuts down. It is
supported on Linux and macOS; install it with (prompts for sudo):
vee daemon install
The daemon runs as a systemd system service
(/etc/systemd/system/vee.service) so it can react to logind’s shutdown
signal in time to stop VMs cleanly.
Check status, logs, and control the service with the usual systemctl verbs:
systemctl status vee # is it running?
journalctl -u vee -f # follow logs
sudo systemctl restart vee # restart (e.g. after upgrading the vee binary)
sudo systemctl stop vee # stop
The daemon runs as a system-level launchd LaunchDaemon
(/Library/LaunchDaemons/io.vee.daemon.plist) under your user account. At
host shutdown, launchd’s SIGTERM gives it up to 300 seconds to power off
every running VM.
sudo launchctl print system/io.vee.daemon # is it running?
tail -F ~/.vee/logs/daemon.log # daemon stdout/stderr
sudo launchctl kickstart -k system/io.vee.daemon # restart (e.g. after upgrading vee)
Note that unloading the job (launchctl bootout, or vee daemon uninstall)
also stops running VMs gracefully — macOS gives launchd jobs no way to tell
a plain unload apart from a host shutdown.
NoteAfter upgrading vee, restart the daemon so it runs the new binary:sudo systemctl restart vee(Linux) orsudo launchctl kickstart -k system/io.vee.daemon(macOS). The service’s executable path is pinned to the absolute path of theveebinary that ranvee daemon install. If your upgrade replaces that same file in place (a new release extracted over~/.vee/bin/vee, ormake install), a restart is all you need. If the new binary lands at a different path, re-runvee daemon installso the service points at it.
Remove the service with:
vee daemon uninstall