Best practices for packaging pre-compiled binaries (.deb, .rpm, .tar.gz, AppImage) for NixOS, handling library dependencies, or facing "library not found" errors with binary distributions
Extract and patch binary packages within Nix builds for reproducibility.
Source from original archive directly, never from pre-extracted directories.
Don't use for:
| Topic | Rule File |
|---|---|
| Core pattern for .deb packages | essential-pattern |
| .rpm, .tar.gz, .zip extraction | archive-formats |
| nativeBuildInputs vs buildInputs | dependencies |
| Local vs remote source files | source-files |
| Common pitfalls and fixes | common-mistakes |
| Finding missing libraries with ldd | finding-libraries |
| Quick testing with steam-run | quick-testing |
| Troubleshooting autoPatchelf errors | troubleshooting-autoPatchelf |
| Version variable in filename | version-management |
| Electron app dependencies | electron-apps |
| FHS env for resistant binaries | advanced-fhs-env |
| Build phases and hooks | build-phases |
| Wrapper scripts with makeWrapper | wrapper-programs |
{ pkgs }:
pkgs.stdenv.mkDerivation rec {
pname = "appname";
version = "1.0.0";
src = ./AppName-${version}-linux-amd64.deb;
nativeBuildInputs = with pkgs; [
autoPatchelfHook # Fixes library paths
dpkg # Extracts .deb
];
buildInputs = with pkgs; [
stdenv.cc.cc.lib
glib
gtk3
];
unpackPhase = ''
ar x $src
tar xf data.tar.xz
'';
installPhase = ''
mkdir -p $out
cp -r opt/AppName/* $out/
'';
}
| Task | Solution |
|---|---|
| Local archive | src = ./package-${version}.tar.gz |
| Remote archive | src = fetchurl { url = "..."; hash = "sha256-..."; } |
| Extract .deb | ar x $src && tar xf data.tar.xz + dpkg |
| Extract .rpm | rpm2cpio $src | cpio -idmv + rpm, cpio |
| Extract .tar.gz | Auto-detected by stdenv |
| Extract .zip | Add unzip to nativeBuildInputs |
| Fix libraries | Add autoPatchelfHook to nativeBuildInputs |
| Find missing libs | Run ldd result/bin/app for "not found" |
| Quick test binary | nix-shell -p steam-run; steam-run ./binary |
| Debug autoPatchelf | nix log /nix/store/...-drv |
| Search libraries | nix-locate libX11.so.6 |
| Wrapper scripts | Add makeWrapper to nativeBuildInputs |
| Version sync | Use src = ./app-${version}.tar.gz |
nativeBuildInputs: Build-time tools (dpkg, autoPatchelfHook, makeWrapper) buildInputs: Runtime libraries (gtk3, glib, libpulseaudio) propagatedBuildInputs: Rarely needed for binary packaging
| Missing Library | Nix Package |
|---|---|
libgtk-3.so.0 |
gtk3 |
libglib-2.0.so.0 |
glib |
libpulse.so.0 |
libpulseaudio |
libGL.so.1 |
mesa or libglvnd |
libxkbcommon.so.0 |
libxkbcommon (NOT xorg.libxkbcommon) |
libstdc++.so.6 |
stdenv.cc.cc.lib |
lddRead individual rule files for detailed explanations and code examples:
rules/essential-pattern.md
rules/archive-formats.md
rules/_sections.md
Each rule file contains:
For the complete guide with all rules expanded: AGENTS.md