DISTROBOX-ASSEMBLE(1)

๐Ÿ“ฆ
version 1.8.2.5 ยท 5 versions
, in alpine 3.24, arch rolling, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu stonking

๐Ÿ’… DISTROBOX-ASSEMBLE(1) โ€” User Manual ๐Ÿฆ‹

okay bestie, welcome to the distrobox-assemble manual page. it's giving โœจbulk container managementโœจ and honestly? iconic. let's get into it ๐Ÿ’–


โœจ NAME โœจ

distrobox assemble distrobox-assemble


๐ŸŒธ DESCRIPTION ๐ŸŒธ

okay so distrobox-assemble is the one that handles creating or destroying containers in batches, and it does all of that based on a manifest file. no cap, it's a whole vibe.

the manifest file, by default, is ./distrobox.ini โ€” but bestie you can totally point it somewhere else with the --file flag. ๐Ÿซถ


๐ŸŽ€ SYNOPSIS ๐ŸŽ€

distrobox assemble

and here are the flags that ride along with it, one by one:

  • --file โ€” path or URL to the distrobox manifest/ini file ๐Ÿ—‚๏ธ
  • --name/-n โ€” run against a single entry in the manifest/ini file ๐Ÿ‘‘
  • --replace/-R โ€” replace already existing distroboxes with matching names ๐Ÿ”
  • --dry-run/-d โ€” only print the container manager command generated ๐Ÿ‘€
  • --verbose/-v โ€” show more verbosity ๐Ÿ“ข
  • --version/-V โ€” show version โญ

๐Ÿฆ‹ EXAMPLES ๐Ÿฆ‹

here's an example manifest file that creates two containers, because why make one when you can make two ๐Ÿ’…

[ubuntu]
additional_packages="git vim tmux nodejs"
image=ubuntu:latest
init=false
nvidia=false
pull=true
root=false
replace=true
start_now=false

# You can add comments using this #
[arch] # also inline comments are supported
additional_packages="git vim tmux nodejs"
home=/tmp/home
image=archlinux:latest
init=false
start_now=true
init_hooks="touch /init-normal"
nvidia=true
pre_init_hooks="touch /pre-init"
pull=true
root=false
replace=false
volume="/tmp/test:/run/a /tmp/test:/run/b"

๐ŸŒˆ Create ๐ŸŒˆ

we can bring them up simply using

distrobox assemble create

if the file is called distrobox.ini and it's in the same directory you're launching the command from, no further arguments are needed. that's the dream fr fr ๐Ÿ˜Œ

you can specify a custom path for the file using

distrobox assemble create --file /my/custom/path.ini

or even specify a remote file, by using an URL:

distrobox-assemble create --file https://raw.githubusercontent.com/89luca89/dotfiles/master/distrobox.ini

๐Ÿ’œ Replace ๐Ÿ’œ

by default, distrobox assemble will replace a container only if replace=true is specified in the manifest file. so it's opt-in, bestie, no surprise deletions ๐Ÿ’€

in the example of the manifest above, the ubuntu container will always be replaced when running distrobox assemble create, while the arch container will not.

to force a replace for all containers in a manifest, use the --replace flag

distrobox assemble create --replace [--file my/custom/path.ini]

๐Ÿ“ Remove ๐Ÿ“

we can bring down all the containers in a manifest file by simply doing

distrobox assemble rm

or using a custom path for the ini file

distrobox assemble rm --file my/custom/path.ini

๐Ÿงš Test ๐Ÿงš

you can always test what distrobox would do by using the --dry-run flag. this command will only print what commands distrobox would do without actually running them. it's the rehearsal, not the performance โœจ


๐Ÿ’€ Clone ๐Ÿ’€

Disclaimer: You need to start the container once to ensure it is fully initialized and created before cloning it. The container being copied must also be stopped before the cloning process can proceed.

so yeah โ€” start it, stop it, then clone it. that's the whole ritual ๐Ÿ™ˆ


๐Ÿ‘‘ Available options ๐Ÿ‘‘

this is a list of available options with the corresponding type:

๐ŸŒŸ Types legend: ๐ŸŒŸ

  • bool: true or false
  • string: a single string, for example home="/home/luca-linux/dbox"
  • string_list: multiple strings, for example additional_packages="htop vim git". Note that string_list can be declared multiple times to be compounded:
[ubuntu]
image=ubuntu:latest
additional_packages="git vim tmux nodejs"
additional_packages="htop iftop iotop"
additional_packages="zsh fish"

now the actual option roster, no cap, every single one:

  • additional_flags (string_list) โ€” Additional flags to pass to the container manager ๐Ÿ”ง
  • additional_packages (string_list) โ€” Additional packages to install inside the container ๐Ÿ“ฆ
  • home (string) โ€” Which home directory should the container use ๐Ÿ 
  • hostname (string) โ€” Set hostname of the container ๐Ÿท๏ธ
  • image (string) โ€” Which image should the container use, look here for a list ๐Ÿ–ผ๏ธ
  • clone (string) โ€” Name of the Distrobox container to use as the base for a new container (the container must be stopped). ๐Ÿงฌ
  • include (string) โ€” Name of the entry in the manifest to include in the current definition. ๐Ÿช„
  • init_hooks (string_list) โ€” Commands to run inside the container, after the packages setup ๐Ÿช
  • pre_init_hooks (string_list) โ€” Commands to run inside the container, before the packages setup ๐Ÿช
  • volume (string_list) โ€” Additional volumes to mount inside the containers ๐Ÿ’พ
  • exported_apps (string_list) โ€” App names or desktopfile paths to export ๐Ÿš€
  • exported_bins (string_list) โ€” Binaries to export ๐Ÿš€
  • exported_bins_path (string) โ€” Optional path where to export binaries (default: $HOME/.local/bin) ๐Ÿ“
  • entry (bool) โ€” Generate an entry for the container in the app list (default: false) ๐Ÿ“
  • start_now (bool) โ€” Start the container immediately (default: false) โฑ๏ธ
  • init (bool) โ€” Specify if this is an initful container (default: false) ๐ŸŒฑ
  • nvidia (bool) โ€” Specify if you want to enable NVidia drivers integration (default: false) ๐ŸŽฎ
  • pull (bool) โ€” Specify if you want to pull the image every time (default: false) โฌ‡๏ธ
  • root (bool) โ€” Specify if the container is rootful (default: false) ๐Ÿ‘‘
  • unshare_groups (bool) โ€” Specify if the container should unshare users additional groups (default: false) ๐Ÿซฅ
  • unshare_ipc (bool) โ€” Specify if the container should unshare the ipc namespace (default: false) ๐Ÿซฅ
  • unshare_netns (bool) โ€” Specify if the container should unshare the network namespace (default: false) ๐Ÿซฅ
  • unshare_process (bool) โ€” Specify if the container should unshare the process (pid) namespace (default: false) ๐Ÿซฅ
  • unshare_devsys (bool) โ€” Specify if the container should unshare /dev (default: false) ๐Ÿซฅ
  • unshare_all (bool) โ€” Specify if the container should unshare all the previous options (default: false) ๐Ÿซฅ

the include option copies the attributes of a definition into another one. Recursive inclusions are allowed. it operates on the manifest file and the consequent distrobox containers have no relation of any kind. please be aware that attributes in the including definition will not override nor shadow the ones in the included definition, they will simply duplicate. ๐Ÿชž

for further explanation of each of the other options in the list, take a look at the distrobox create usage, each option corresponds to one of the create flags. iykyk ๐Ÿ”ฅ


โญ Advanced example โญ

okay bestie</p> picking right back up where we left off, no re-intro, we're just in it now ๐Ÿ’…

this next block is the big one โ€” a whole tumbleweed_distrobox setup that stacks a bunch of additional_packages fields, fires off a pile of init_hooks (all those go install lines and the ln -sf /usr/bin/distrobox-host-exec ... symlinks), and exports htop plus some exported_bins. copy it exactly, do not be cute with it:

[tumbleweed_distrobox]
image=registry.opensuse.org/opensuse/distrobox
pull=true
additional_packages="acpi bash-completion findutils iproute iputils sensors inotify-tools unzip"
additional_packages="net-tools nmap openssl procps psmisc rsync man tig tmux tree vim htop xclip yt-dlp"
additional_packages="git git-credential-libsecret"
additional_packages="patterns-devel-base-devel_basis"
additional_packages="ShellCheck ansible-lint clang clang-tools codespell ctags desktop-file-utils gcc golang jq python3"
additional_packages="python3-bashate python3-flake8 python3-mypy python3-pipx python3-pycodestyle python3-pyflakes python3-pylint python3-python-lsp-server python3-rstcheck python3-yapf python3-yamllint rustup shfmt"
additional_packages="kubernetes-client helm"
init_hooks=GOPATH="${HOME}/.local/share/system-go" GOBIN=/usr/local/bin go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest;
init_hooks=GOPATH="${HOME}/.local/share/system-go" GOBIN=/usr/local/bin go install github.com/onsi/ginkgo/v2/ginkgo@latest;
init_hooks=GOPATH="${HOME}/.local/share/system-go" GOBIN=/usr/local/bin go install golang.org/x/tools/cmd/goimports@latest;
init_hooks=GOPATH="${HOME}/.local/share/system-go" GOBIN=/usr/local/bin go install golang.org/x/tools/gopls@latest;
init_hooks=GOPATH="${HOME}/.local/share/system-go" GOBIN=/usr/local/bin go install sigs.k8s.io/kind@latest;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/conmon;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/crun;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/docker;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/docker-compose;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/flatpak;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/podman;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/local/bin/xdg-open;
exported_apps="htop"
exported_bins="/usr/bin/htop /usr/bin/git"
exported_bins_path="~/.local/bin"

like, the range on this one?? go tooling and container tooling and a symlink farm, all in one lil config. iconic. ๐Ÿ‘‘


โœจ Clone example โœจ

here's where you define one box and then just clone it into siblings โ€” deno_ubuntu and bun_ubuntu both ride on [ubuntu] via clone=ubuntu, and each one brings its own pre_init_hooks (one curls the deno installer, one curls the bun installer). no cap:

[ubuntu]
additional_packages="git vim tmux"
image=ubuntu:latest
init=false
nvidia=false
pull=true
root=false
replace=true
start_now=true

[deno_ubuntu]
clone=ubuntu
init=false
nvidia=false
pull=true
root=false
replace=true
start_now=true
pre_init_hooks=curl -fsSL https://deno.land/install.sh | sh;

[bun_ubuntu]
clone=ubuntu
init=false
nvidia=false
pull=true
root=false
replace=true
start_now=true
pre_init_hooks=curl -fsSL https://bun.sh/install | bash;

โœจ Custom login shell example โœจ

want a specific login shell? you set it up in pre_init_hooks, and here it's exporting SHELL=/bin/bash; โ€” that's the whole vibe:

[ubuntu]
image=ubuntu:latest
pre_init_hooks="export SHELL=/bin/bash;"

โœจ Include example (inherit fields from another distrobox) โœจ

and this is the include one โ€” [ubuntu-nvidia] doesn't redefine everything, it just says include=ubuntu and flips nvidia=true. chef's kiss inheritance ๐Ÿซถ:

[ubuntu]
image=ubuntu:latest
additional_packages="git vim tmux nodejs"
additional_packages="htop iftop iotop"
additional_packages="zsh fish"

[ubuntu-nvidia]
include=ubuntu
nvidia=true

and that's the whole page, bestie!! ๐ŸŽ€ this manual came to you from the Distrobox project, dated Mar 2026 โ€” go build yourself a lil container zoo and slay ๐Ÿ’–โœจ๐Ÿฆ‹