nix-packaging-best-practices
from lihaoze123/my-skills
My claude-code
0 stars0 forksUpdated Jan 24, 2026
npx skills add https://github.com/lihaoze123/my-skills --skill nix-packaging-best-practicesSKILL.md
Packaging Binary Distributions for Nix
Extract and patch binary packages within Nix builds for reproducibility.
Core Principle
Source from original archive directly, never from pre-extracted directories.
When to Use
- Converting binary packages (.deb, .rpm, .tar.gz, .zip) to Nix derivations
- Packaging proprietary/closed-source software distributed as binaries
- Electron/GUI apps show "library not found" errors
- User provides pre-extracted binary contents
- Binary distributions need library path fixes
Don't use for:
- Software available in nixpkgs
- Source-based packages (use standard derivation)
- AppImages (use appimage-run or extract and patch)
Quick Reference
| 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 |
Essential Pattern (.deb)
{ 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/
'';
}
Common Tasks
| 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 |
Dependency Categories
nativeBuildInputs: Build-time tools (dpkg, autoPatchelfHook, makeWrapper) buildInputs: Runtime libraries (gtk3, glib, libpulseaudio) propagatedBuildInputs: Rarely needed for binary packaging
Common Library Mappings
| 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 |
Red Flags - STOP
- "User already extracted it, use that directory" → NO, source from original archive
- "Absolute path works for me locally" → Breaks for others, use relative
- "Just add more libraries until it works" → Find actual dependencies with
ldd
How to Use
Read individual rule files for detailed explanations and code examples:
rules/essential-pattern.md
rules/archive-formats.md
rules/_sections.md
Each rule file contains:
- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Additional context and references
Full Compiled Document
For the complete guide with all rules expanded: AGENTS.md
Repository
lihaoze123/my-skillsParent repository
Repository Stats
Stars0
Forks0