Using podman, distrobox, chezmoi, and forgejo to create a portable and reproducible terminal environment
I am definitely back on my bullshit. There is no reason why, me as a landscape contractor, should be doing this kind of project.
This is an idea to have all my terminal tooling inside of a single distrobox container that is then portable to any machine. I won’t have to configure anything and can do all my terminal work inside of the distrobox container, with full access to the host if needed. A huge benefit of this setup isn’t just having a reproducible environment to easily install on new systems, it also means I can clone it as many times as I want for various testing. I can run as many of these containers on a single system as I want.
These notes are how to setup the distrobox container, install and configure all my terminal apps, push the image to my Forgejo container registry, and push the config files into a Forgejo dotfiles repo. Now, I realize that real devs or sysadmins might have already known and have been using distrobox in this way. But, its all new to me and I’m pumped I got through this project.
Honestly, I don’t know if this is how I will work on my systems in the future. I am using it now since I’ve spent so much time working on it. However, this was a major learning opportunity. I like to accompany these kinds of posts with some takeaways.
- I am vastly under-utilizing distrobox. It is so powerful and, since it is all containers, super portable to other systems. Not only was I able to move this container to a new system and easily get going, I can run on multiple architectures if needed.
- I’m getting better with Podman. I found out that Docker and Podman are much more compatible than I thought. I was able to create all of this with distrobox+podman on my desktop and then run on a laptop with distrobox+docker.
- Git is ridiculous. Unless you use it every day there is no reason to learn it. If it wasn’t for my notes I’d never be able to do this again since I use git like 4 times a year.
- I need to get better at using chezmoi. I will edit configs outside of chezmoi and then run into conflicts. Then, with my limited git knowledge, I struggle to fix it. I just need to get better at using
chezmoi edit. - This setup has more value than I was originally thinking. Yes, it makes it easy to get a new system up and running. I can also use it for virtual machines and testing since it makes getting my environment up and running easily. But, I can also use it on a local machine and have as many of these distrobox containers running as I want, even all at the same time. Doing this project got me to think about distrobox for more than just installing something from the AUR onto a Debian machine. I can setup an entire environment and duplicate it as many times as I want. Big mind blown moment.
Distrobox container install
Let’s start with the one line install:
distrobox create --image debian:12 --name debs_toolkit --home $HOME/distrobox/debs_toolkit --volume ~/Nextcloud2:$HOME/distrobox/debs_toolkit/Nextcloud2 --volume ~/Downloads:$HOME/distrobox/debs_toolkit/Downloads --volume ~/remote_systems:$HOME/distrobox/debs_toolkit/remote_systems
What this command is doing:
- Create a new distrobox using Debian 12
- Name it “debs_toolkit”
- Set a custom home dir in the path. This is crucial for a portable setup.
- Bind mount paths on the host into the container. More below.
Custom home dir
This is critical for having a portable toolkit like this. All of the configuration, run-in-place binaries, bash history, etc. are in $HOME. These folders need to be moved along with the container to the new machine. Theoretically I could tar up .config and .local and then unpack it on the new machine, then use this distrobox container without a custom home.
However, there could be a mismatch of versions to the configs. For example, I could have a yazi config for an older version that will then throw errors when run. I want a “frozen in time” portable toolkit. Both the apps and the configs are frozen. Updates can happen on the new machine as necessary. However, I want to do periodic updates and push to backups, not have a bunch of one-off machines.
Another example is different architectures and distros. This is why I want a Debian container. Then I can use it on any machine, regardless of the OS, and carry on as normal. Right now I’m using PostmarketOS on my chromebook, which is built on Alpine. Porting this container to it gives me Debian, which I am used to using, along with all the tools that work on a Debian host. I don’t have crossover between Alpine and Debian. This way I don’t run one-off apps in distrobox and export to Alpine, the entire toolkit is inside the Debian distrobox.
In order to be portable, the data for each of the apps needs to be in its own home dir.
Now, when moving this install to another machine, this means I will have to move the custom home dir to the new machine. The distrobox home dir is not part of the container image. To move I have created an archive of the dir and then placed on the NAS. I can then download on any machine on my network. I have also created a dotflies repo on the Forgejo instance and can be managed with chezmoi.
Bind mounts
I’m actually unsure about doing this. In the distrobox setup I am passing bind mounts from the host home to the custom home for the container. But, these directories are available to the container without the bind mounts. Is it worth symlinking them into the custom home dir? I guess for ease of use it comes in handy. Instead of doing cd /home/$USER/Nextcloud2 I can do cd ~/Nextcloud2 and then I don’t have to remember these folders aren’t in the custom home dir. This will probably come up trying to get to Downloads all the time.
I am also passing a mount for my system samba mounts for the same purpose, to keep it easy to remember where the dirs are. I could also mount these directly inside the container instead of mounting to the host and then passing. Will have to play with that.
Configure the container
Enter the distrobox container with distrobox enter debs_toolkit and get busy configuring all my tools. Since this is a x86 Debian 12 container I can use all the tools I prefer, whether from apt, static binaries, or favorite apps built from source or downloaded .deb files.
Managing configs and files with chezmoi
To keep the debs_toolkit container configured exactly the same on every system and without having to update the configs manually, I am pushing .config and some other directories to a Forgejo repo and managing it all with chezmoi. Doing it this way means I can easily pull my dotfiles to any machine, have versioning for the files, and push updates and keep those updates in sync across all my instances.
Not going to go into detail on how to use chezmoi here or what dirs I’m sending (other than the obvious .config)
Alternative: Compress and transfer the custom home dir
Instead of using a dotfile manager, I could simply tar the custom home dir on the host and then send that to the new machine in some way. It would be as simple as doing a tar -cvf debs_toolkit_home.tar.gz $HOME/distrobox/debs_toolkit and then using rsync or another tool to send that anywhere. Currently I have an archive of this on my NAS if/when I need it or if I don’t want to deal with chezmoi.
Container registry
The whole reason I’m doing this project is to create a portable image I can easily put onto any machine (with distrobox and docker/podman). I could use docker save or podman save and then manually move the .tar file around. However, I want to be able to easily pull this image onto any machine, so I’m pushing the container image to the container registry on my Forgejo instance.
These are the steps to do so.
First, login with podman login example.com.
Now, commit the image with podman commit debs_toolkit debs_toolkit-v1.x. I need to be sure I commit changes to the system when they happen. Then, on any machine, I can pull down the latest image, rm the old distrobox, create a new, and all my changes will be present.
Next, tag the image with podman tag debs_toolkit-v1.0:latest example.com/$USER/debs_toolkit:latest.
Now, push to the registry with podman push example.com/$USER/debs_toolkit:latest.
On any machine I can pull with podman pull example.com/$USER/debs_toolkit:latest or with Docker (same way).
New system setup
When using a new machine these are the steps to get to a working container on the new system.
- Install and configure Docker/Podman
- Install distrobox
- Create
$HOME/distrobox/debs_toolkit - Setup Nextcloud sync client (optional depending on system)
- Configure samba mounts in
~/remote_systems(optional depending on system) - Set up the distrobox
- Install chezmoi in distrobox container and pull down dotfiles
- Restart container
Install utils and Podman
Straight from the repos, since I will likely be using this on a Debain system.
sudo apt install curl wget git podman
Install distrobox
Using the script to install.
wget -qO- https://raw.githubusercontent.com/89luca89/distrobox/main/install | sudo sh
Install chezmoi
Using the install script and the binary instead of installing on the host.
Configure dirs
Need to have these dirs in the host $HOME.
mkdir -p ~/remote_systems/{nas_home,nas_storage}
mkdir ~/Nextcloud2
mkdir ~/Downloads
Mount remote systems
Add this to /etc/fstab.
# nas storage access
//SERVER/storage $HOME/remote_systems/nas_storage cifs rw,uid=$USER,auto,credentials=$HOME/.creds 0 0
//SERVER/nas_home $HOME/remote_systems/nas_home cifs rw,uid=$USER,auto,credentials=$HOME/.creds 0 0
Create a credentials file on the host system at $HOME/.creds with this layout:
username=USER
password=PASS
Start distrobox container
Now create the container. I am pulling from my own registry so the image will come with all the apps I’ve installed with apt, any fstab mounts, and configs that live in other places like /etc.
Pull and setup container:
distrobox create -i example.com/$USER/debs_toolkit:latest --name debs_toolkit --home $HOME/distrobox/debs_toolkit --volume ~/Nextcloud2:$HOME/distrobox/debs_toolkit/Nextcloud2 --volume ~/Downloads:$HOME/distrobox/debs_toolkit/Downloads --volume ~/remote_systems:$HOME/distrobox/debs_toolkit/remote_systems
Install chezmoi
Using the install script and the binary instead of installing on the host.
sh -c "$(curl -fsLS get.chezmoi.io)" -- -b $HOME/.local/bin
Now apply the dotfiles.
chezmoi init --apply https://example.com/$USER/debs_toolkit.git
Random problem with ping
Ping fails due to an error with ping: => missing cap_net_raw+p capability or setuid?.
Finding this answer we need to change the ping_group_range on certain hosts.
Check how your host is configured:
$ sysctl net.ipv4.ping_group_range
net.ipv4.ping_group_range = 1 0
1 0 means the host won’t allow rootless containers to use ping. Ubuntu 24.04.2, for example, is 1 0, Fedora 42 is 0 2147483647.
To enable, you have to change the net.ipv4.ping_group_range value:
$ sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"
net.ipv4.ping_group_range = 0 2147483647
You may have to create a distrobox with --cap-add=NET_RAW:
distrobox create ... --additional-flags "--cap-add=NET_RAW"
- - - - -
Did you like this post? Give it an upvote by clicking on the arrows below! Sending me an upvote is like you and I giving each other a high five.
🙏 😎
Thank you for reading! If you would like to comment on this post you can start a conversation on the Fediverse. Message me on Mastodon at @cinimodev@masto.ctms.me. Or, you may email me at blog.discourse904@8alias.com. This is an intentionally masked email address that will be forwarded to the correct inbox.If you enjoy the random stuff I write here, post to Mastodon, or watch on YouTube, and are feeling generous, I am open to tips of Ko-fi.