I made a post a while ago asking what you do when NixOS isn't cutting it. You need a package that isn't available as a flatpak/appimage or already in nixpkgs. You don't want to build from source, because it's either too difficult or too time consuming. One suggestion was containerization or virtual machines, but those seemed too cumbersome. Well, distrobox is the tool that fixes it.
Distrobox is a shell script that wraps over docker/podman to run a container of a distribution of your choice. But it does it behind a very high level API, and integrates the container environment seemlessly with your host environment. It is seriously as easy as this, if you need to install something with apt inside debian.
$ distrobox create -n my_debian --image debian:latest
$ distrobox enter my_debian
And bang, your in a debian container and it won't even feel like it. It automatically integrates your shell environment and maps your root directory inside the container (or something like that.) You seriously wouldn't know unless you neofetch
. Best part is that since everything is in the nix store, every program in your environment should work, for the most part, inside this container. I've not noticed problems yet.
Tada! apt
is available in this environment and you can install what you need. Then you can run it while inside the container. From the host machine, outside the container, you can run it directly too. Say you installed program X
in debian:
$ distrobox enter my_debian -- X
And it will just run the command and send you back to the host machine.
In the case of docker, you can type docker ps
and it will show you your debian image my_debian
listed.
There's two more things I want to do to really polish this workflow. The first is to change my shell prompt so I know that I'm actually in debian without typing neofetch! Inside the box the variable CONTAINER_ID
is set and the hostname is modified. I've adjusted my starship prompt to look like this when inside the box:
distrobox:my_debian ~ $
And lastly, I really want to blur the lines. If I install X in debian, I want to just call it directly from the host as X
, not invoke my debian instance with distrobox enter
.
When you type X
and the program is missing, bash (and fish and zsh I'm sure) runs a hook that you can look at by typing
$ declare -p -f command_not_found_handle
By overriding this, you could first have it try the inside container if it can't find the application in the host container, like so.
command_not_found_handle () {
distrobox enter my_debian -- $@
}
This is not a perfect solution, but I'm still experimenting with how to integrate this both seamlessly and also not accidentally run things inside debian and not realize it. If you have suggestions for how to improve handling calling commands from the outside environment, please share. Best case might just be adding aliases for programs explicitly. For example, `alias X=distrobox enter my_debian -- X.
Anyway, distrobox is the solution! This is one more barrier removed that was preventing me from moving my main computer over to NixOS. I'm so happy to have found this and wanted to share.
It looks like a useful tool - thanks for sharing all of that info! Personally I would prefer to set up a shell alias or wrapper script for each command I want to run in distrobox instead of using a missing-program hook.
I think thats the best way too, and it doing that ends up cateloguing all my immutable packages in one place.