Use any Linux distribution inside your terminal, with tight host integration, backed by Incus system containers instead of Docker or Podman.
Inspired by distrobox. Replaces the OCI application container backend with Incus system containers, gaining full init system support, ZFS/Btrfs-native storage, and VM capability — while keeping the same user-facing workflow.
| Dependency | Purpose | Required |
|---|---|---|
incus ≥ 6.0 |
Container runtime | Always |
skopeo |
OCI image pull from Docker Hub / GHCR / Quay | OCI images only |
cloud-init |
In-container first-boot setup | In OCI images |
zfs / zpool |
ZFS dataset management for home dirs | ZFS storage only |
btrfs-progs |
Btrfs subvolume management for home dirs | Btrfs storage only |
incus-user |
Rootless container daemon | Rootless mode only |
git clone https://github.com/Interested-Deving-1896/incusbox
cd incusbox/incusbox
sudo ./installgit clone https://github.com/Interested-Deving-1896/incusbox
cd incusbox/incusbox
./install --user
# Add ~/.local/bin to PATH if not already present
export PATH="${PATH}:${HOME}/.local/bin"The install script:
- Copies all scripts to
{prefix}/bin/ - Copies Incus profiles to
{prefix}/share/incusbox/profiles/ - Registers profiles with the running Incus daemon (if available)
- Registers OCI remotes:
docker(docker.io),ghcr(ghcr.io),quay(quay.io)
# Create a container from a Docker Hub image
incusbox create --image docker:ubuntu:22.04 --name mybox
# Enter it
incusbox enter mybox
# Create from an Incus native image
incusbox create --image images:fedora/40 --name fedbox
# Create with NVIDIA GPU passthrough
incusbox create --image docker:ubuntu:22.04 --name gpubox --nvidia
# List all incusbox containers
incusbox list
# Stop a container
incusbox stop mybox
# Remove a container
incusbox rm myboxincusbox auto-detects the Incus storage pool driver and applies storage-specific behaviour for the container's home directory.
# Use a specific pool
incusbox create --image docker:ubuntu:22.04 --name mybox \
--storage-pool tank
# Create a dedicated ZFS dataset for the home directory
# (separate from the Incus-managed rootfs dataset)
incusbox create --image docker:ubuntu:22.04 --name mybox \
--storage-pool tank \
--storage-dataset tank/incusboxWhen --storage-dataset is set, incusbox creates
<dataset>/<name>/home with compression=zstd,atime=off and mounts it
as the container's home directory. The container rootfs dataset is always
managed by Incus itself.
# Default compression (zstd)
incusbox create --image docker:ubuntu:22.04 --name mybox \
--home-prefix /data/incusbox
# Custom compression
incusbox create --image docker:ubuntu:22.04 --name mybox \
--home-prefix /data/incusbox \
--btrfs-compress lzoWhen the home directory path lives on a Btrfs filesystem, incusbox creates a subvolume at that path and sets the compression property.
No special handling — plain directories are used.
Rootless containers run via the incus-user per-user daemon. Run the
setup helper first:
incusbox-setup-rootlessThis checks for and configures:
incus-usersystemd user service- AppArmor profiles (required on Ubuntu 24.04+)
/dev/fuseaccess (required for fuse-overlayfs)- UID/GID mapping
Once set up, all incusbox commands work without sudo or --root.
By default, incusbox shares the host's PID, IPC, and network namespaces so the container feels like a native part of the host system. Each can be disabled individually:
incusbox create --image docker:ubuntu:22.04 --name isolated \
--unshare-netns \ # own network namespace (bridged NIC)
--unshare-ipc \ # own IPC namespace
--unshare-process # own PID namespace (no host process visibility)
# Or disable all at once
incusbox create --image docker:ubuntu:22.04 --name isolated \
--unshare-allFor containers that need a full init system (systemd, OpenRC):
incusbox create --image docker:ubuntu:22.04 --name svcbox --initThis applies the incusbox-init Incus profile which mounts the tmpfs
paths systemd requires (/run, /run/lock, /var/lib/journal) and
enables user lingering.
From inside a container, export apps, binaries, or services to the host:
# Export a .desktop application (appears in host app launcher)
incusbox-export --app firefox
# Export a binary to ~/.local/bin on the host
incusbox-export --bin /usr/bin/htop
# Export a systemd user service
incusbox-export --service syncthing
# Remove an export
incusbox-export --delete --app firefox# From inside an incusbox container:
incusbox-host-exec flatpak run org.mozilla.firefox
incusbox-host-exec systemctl --user status
incusbox-host-exec bashUses nsenter to escape into the host's namespaces. Falls back to
chroot /run/host when the PID namespace is unshared.
Define containers in YAML and create them all at once:
# myboxes.yaml
containers:
- name: ubuntu-dev
image: docker:ubuntu:22.04
additional_packages: git curl build-essential
init_hooks: "curl -fsSL https://get.docker.com | sh"
- name: fedora-tools
image: images:fedora/40
nvidia: true
home_prefix: /data/incusbox
- name: arch-gaming
image: docker:archlinux
init: true
storage_pool: tank
storage_dataset: tank/incusboxincusbox-assemble --file myboxes.yamlAny image accessible via an OCI registry or Incus image server:
# Docker Hub
incusbox create --image docker:ubuntu:22.04
incusbox create --image docker:fedora:40
incusbox create --image docker:archlinux
incusbox create --image docker:alpine:3.19
incusbox create --image docker:debian:bookworm
# GitHub Container Registry
incusbox create --image ghcr:someorg/someimage:latest
# Quay.io
incusbox create --image quay:fedora/fedora:40
# Incus image servers (no skopeo required)
incusbox create --image images:ubuntu/24.04
incusbox create --image images:fedora/40
incusbox create --image images:archlinux
incusbox create --image images:alpine/3.19Incus profiles are stored in profiles/ and registered at install time.
They can be inspected or modified directly:
incus profile show incusbox-base
incus profile edit incusbox-base| Profile | Applied when |
|---|---|
incusbox-base |
All containers |
incusbox-init |
--init flag |
incusbox-nvidia |
--nvidia flag |
incusbox-unshare-net |
--unshare-netns flag |
incusbox-gui |
GUI app containers |
incusbox-rootless |
Rootless (incus-user) mode |
- OCI images without cloud-init: Images that don't include cloud-init
(Alpine, Arch, minimal Ubuntu) use a direct
incus execinjection fallback instead of cloud-init. This is less reliable on first boot timing — seeincusbox-initfor details. lxc.namespace.share.pid: Host PID namespace sharing requires a non-hardened kernel. Some distributions (e.g. certain Fedora/RHEL configurations) reject this even for privileged containers.- Rootless OCI images: Pulling OCI images in rootless mode goes through
the
incus-userdaemon (which runs as root internally), so it works transparently. If you encounter permission errors, runincusbox-setup-rootlessto verify your setup.
GPL-3.0-only — same as distrobox, from which this project draws inspiration.