Sometimes you need to run an app on NixOS that’s only available for Ubuntu/Debian or ships as .deb/.iso. Distrobox lets you run it in a container with host integration - like a native app.

πŸ’‘ Works on any distro with Nix installed.


πŸ“¦ Create container

# Create container with necessary volume mounts
nix shell nixpkgs#distrobox --command distrobox create \
  --image ubuntu:20.04 \
  --name <container-name> \
  --volume "<volume_pts>:/dev/pts" \
  --volume "<volume_journal>:/var/log/journal" \
  --home "$HOME/<container-name>-home"

Parameters:

  • --image - base image (ubuntu:20.04, debian:11, etc.)
  • --volume - mount directories (audio, logs)
  • --home - separate home directory inside container
  • --name - container name (used in other commands)

Enter container:

nix shell nixpkgs#distrobox --command distrobox enter <container-name>

πŸ”§ Install app inside container

# Inside container (after distrobox enter)
sudo sh -c '
  # Clean old configs
  rm -rf /etc/apt/sources.list.d/<vendor>.list*
  umount /mnt/<vendor> 2>/dev/null || true

  # Download and mount image
  wget -O /tmp/<vendor>.iso "https://<url>/<vendor>.iso"
  mkdir -p /mnt/<vendor>
  mount -o loop,ro -t iso9660 /tmp/<vendor>.iso /mnt/<vendor>

  # Install from local repo
  echo "deb [trusted=yes] file:/mnt/<vendor>/repo ./" > /etc/apt/sources.list.d/<vendor>.list
  apt update
  apt install -y <package-name>-full

  # Cleanup
  umount /mnt/<vendor>
  rm -f /etc/apt/sources.list.d/<vendor>.list /tmp/<vendor>.iso
'

Replace placeholders:

PlaceholderDescription
<vendor>Vendor name (e.g., nausoftphone)
<package-name>Package name in repo
<url>URL to installer image

Verify:

<package-name> --version

πŸ–₯ Desktop launcher (.desktop)

# ~/.local/share/applications/<app>-distrobox.desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=<App Name> (Distrobox)
Comment=Run <App Name> inside Distrobox container
Exec=konsole --hold -e bash -c 'nix shell nixpkgs#distrobox --command distrobox enter --name <container-name> -- <app-command>'
Icon=<icon-name>
Terminal=false
Categories=Network;AudioVideo;
Keywords=<app>;distrobox;container;

Apply:

update-desktop-database ~/.local/share/applications/

App now appears in menu, launchers, and system search.


πŸ”„ Update app

# Enter container
nix shell nixpkgs#distrobox --command distrobox enter <container-name>

# Upgrade package
sudo apt update && sudo apt install --only-upgrade <package-name>-full

πŸ—‘ Full cleanup (container + volumes)

# 1. Remove container
distrobox rm <container-name>

# 2. Remove associated volumes (if created separately)
# For Podman:
podman volume rm <volume_pts> <volume_journal>

# For Docker:
docker volume rm <volume_pts> <volume_journal>

# 3. Remove container home directory (if used)
rm -rf "$HOME/<container-name>-home"

# 4. Remove launcher
rm -f ~/.local/share/applications/<app>-distrobox.desktop
update-desktop-database ~/.local/share/applications/

⚠️ Volume deletion is irreversible - ensure no needed data inside.

Verify cleanup:

# Containers
distrobox list | grep <container-name>

# Volumes (Podman)
podman volume ls | grep <volume_pts>

# Volumes (Docker)
docker volume ls | grep <volume_pts>

βš™οΈ Launch optimization

Hide terminal (for production)

# Replace Exec with:
Exec=sh -c 'nix shell nixpkgs#distrobox --command distrobox enter --name <container-name> -- <app-command>' >> ~/.cache/<app>.log 2>&1 &

Fix audio (if not working)

# Add when creating container:
--volume "$XDG_RUNTIME_DIR/pulse:/run/user/1000/pulse"
# Or for PipeWire:
--volume "$XDG_RUNTIME_DIR/pipewire-0:/run/user/1000/pipewire-0"

⚠️ Common issues

# Launcher not appearing
β†’ Validate syntax: desktop-file-validate ~/.local/share/applications/<app>-distrobox.desktop
β†’ Refresh cache: update-desktop-database ~/.local/share/applications/

# Container won't start after Nix update
β†’ Recreate: distrobox rm <name> && create anew
β†’ Data in --home persists if directory not manually deleted

# No audio/device access
β†’ Check volume mounts during container creation
β†’ Ensure user is in required groups (audio, input)

# Volume won't delete ("in use")
β†’ Ensure container is stopped: distrobox list
β†’ Force stop: podman stop <container-name> || docker stop <container-name>