Background Link to heading
I’m lucky enough to be able to use linux on my work laptop, and since I actually need to… work, I really don’t want to be tinkering too much. I have been using Pop!_OS as my daily driver since I started this position (2020). It has honsetly been great, it mostly gets out of the way and just works.
One collegue I worked with always amazed me with his i3 tiling window manager setup, he was so efficient with his keyboard navigation. Between that and his clicky mechanical keyboard, I was always in awe when we’d do any pairing sessions over zoom. I was jealous. I tried installing i3 on a personal laptop a few times, but I would always end up struggling doing even basic things. I never gave it a fair chance and gave quickly, reverting back to Gnome or Pop!_OS.
Fast-forward to 2025 and I suppose I caught the DHH Omarchy fever. I threw that on an old laptop and was blown away. Maybe all I needed was that curated experience to make it click. I fell in love with the tiling window manager and even more in love with the arch user repository (AUR). I almost exclusively use debian/ubuntu based distros for my servers and desktops, so I’m accustom to the repos having relatively outdated packages for a lot of things. It’s fine when I dont need the latest and greatest version, but sometimes I really need the latest version. I would resort to random ways to install apps (download AppImages manaually, downloading and compliling the source, installing one-off deb packages, adding random ubuntu PPAs). That part never felt right. After using the AUR for a bit, I realized that was the thing I was missing. For better or worse, I decided to go all-in and installed Omarchy on my work laptop. It worked well enough on the XPS15, but there were just enough quirks (detecting and toggling my external monitors via my thunderbolt dock, usb hi-fi device flaking out, usb3 docs hanging), that I would be constantly troubleshooting these issues, and rebooting A LOT. Likely a me-problem that could be fixed with time, but like I mentioned ealirer, I don’t necessarily have time to be spending half a day tinkering with making my external monitor work reliably. The straw that broke the camel’s back for me was the breaking updates. More than once after an omarchy-update run, I’d have major issues, like my launcher stopped working. And this isn’t any sort of critque on Omarchy, it just wasn’t stable enough for my needs. After roughly ~5 months of using it, I needed a change.
So around the same time, the long awaited COSMIC destop was finally launched on Pop!_OS 24.04. Early reviews were generally positive. I learned it has a tiling window feature built in, so I could keep my keyboard focused navigation going (I think I’ve been permanetley converted to a tiling window manager guy now!). But I wanted the AUR. And that’s when AI entered the chat. After telling it my situation, it suggested I try out distrobox. Keep my base OS lean, install as little as possible, and use Flatpak’s for common GUI tools. Install an arch container, and then get access to the AUR again. It seemed too good to be true.
Distrobox Link to heading
Distrobox, if you haven’t heard of it before, let’s you quoting their site:
Use any Linux distribution inside your terminal. Enable both backward and forward compatibility with software and freedom to use whatever distribution you’re more comfortable with.
This is exactly what I want. And it took only a tiny bit of tinkering to get it working.
The rest of this post documents some of the setup, just in-case I need to do it again. Maybe it can inspire you to try it as well, there’s almost nothing to loose.
Podman Link to heading
Podman is maturing and is a great way to run distrobox as a rootless container. Install this on the host before creating your first distrobox container.
Distrobox container Link to heading
To create a new Arch Linux container:
distrobox create --name arch --image quay.io/toolbx/arch-toolbox:latest
To enter the container, you can use distrobox enter arch. But I create a helper at ~/.local/bin/archbox:
#!/bin/bash
# Check if we are already inside a container
if [[ -n "$CONTAINER_ID" ]]; then
echo "⚠ You are already inside a container ($CONTAINER_ID)!"
echo " Exit to the host first to switch boxes."
exit 1
fi
# Branch logic:
# If no arguments are passed, just enter the shell.
# If arguments ARE passed, use '--' to execute them safely.
if [ $# -eq 0 ]; then
distrobox enter arch
else
distrobox enter arch -- "$@"
fi
And can quickly fire off an archbox to get into the conatiner.
Terminal integration Link to heading
I’m using COSMIC Terminal, and it allows you to setup profiles. I create an arch profile and set it to run distrobox enter arch as the command. I then make that the default profile. I also bind super + enter to lauch COSMIC Terminal, and I get the same behaviour I grew accustom to from Omarchy.
Common shell and shared binaries Link to heading
As part of the setup, one thing to do to make it seamless is to setup the same shell (I’m using bash) on both the host and the container. Since the home directory is mounted in the container, as long as binaries are statically linked, you can share them betwen host and container. I use Starship for my terminal prompt and bash as my shell. Here’s the setup:
# Run this on your host
mkdir -p ~/.local/bin
curl -sS https://starship.rs/install.sh | sh -s -- -b ~/.local/bin
And add the following to .bashrc
# Check if ~/.local/bin is in PATH (fix for some containers)
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
export PATH="$HOME/.local/bin:$PATH"
fi
# Initialize Starship if the binary exists
if command -v starship &> /dev/null; then
eval "$(starship init bash)"
fi
And for fun, here’s my ~/.config/starship.toml`, which includes the container name:
add_newline = false
command_timeout = 200
# CHANGED: Added $container to the very front
format = "$container[$directory$git_branch$git_status]($style)$character"
# NEW: Container settings
[container]
format = '[$symbol $name]($style) '
symbol = "📦"
style = "bold red"
disabled = false
[character]
error_symbol = "[✗](bold cyan)"
success_symbol = "[❯](bold cyan)"
[directory]
truncation_length = 2
truncation_symbol = "…/"
repo_root_style = "bold cyan"
repo_root_format = "[$repo_root]($repo_root_style)[$path]($style)[$read_only]($read_only_style) "
[git_branch]
format = "[$branch]($style) "
style = "italic cyan"
[git_status]
format = '[$all_status]($style)'
style = "cyan"
ahead = "⇡${count} "
diverged = "⇕⇡${ahead_count}⇣${behind_count} "
behind = "⇣${count} "
conflicted = " "
up_to_date = " "
untracked = "? "
modified = " "
stashed = ""
staged = ""
renamed = ""
deleted = ""
The same starship config is then loaded on both host and container. I started putting more common things in ~/.local/bin like uv and mise, but after using this setup for a few months now, I’m not sure those are even needed. They could solely live in the container.
ADB Link to heading
One tricky thing to get working was ADB. I struggled a lot making it detect connected device. I ended up doing this in two parts:
- Install adb on the host, use that as the adb server. Requires manually starting it there.
- Use the ADB_SOCKET_SERVER env var in the container to tell the container to connect to the host adb server (vs spinning one up) when doing adb calls:
export ANDROID_HOME=$HOME/android-sdk
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
# Conditional ADB Configuration:
# Only force TCP mode if running inside Distrobox
if [ -n "$DISTROBOX_ENTER_PATH" ]; then
export ADB_SERVER_SOCKET=tcp:localhost:5037
fi
I use the same adb binary in both host and container to avoid any version issues.