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-practices

SKILL.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

TopicRule File
Core pattern for .deb packagesessential-pattern
.rpm, .tar.gz, .zip extractionarchive-formats
nativeBuildInputs vs buildInputsdependencies
Local vs remote source filessource-files
Common pitfalls and fixescommon-mistakes
Finding missing libraries with lddfinding-libraries
Quick testing with steam-runquick-testing
Troubleshooting autoPatchelf errorstroubleshooting-autoPatchelf
Version variable in filenameversion-management
Electron app dependencieselectron-apps
FHS env for resistant binariesadvanced-fhs-env
Build phases and hooksbuild-phases
Wrapper scripts with makeWrapperwrapper-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

TaskSolution
Local archivesrc = ./package-${version}.tar.gz
Remote archivesrc = fetchurl { url = "..."; hash = "sha256-..."; }
Extract .debar x $src && tar xf data.tar.xz + dpkg
Extract .rpmrpm2cpio $src | cpio -idmv + rpm, cpio
Extract .tar.gzAuto-detected by stdenv
Extract .zipAdd unzip to nativeBuildInputs
Fix librariesAdd autoPatchelfHook to nativeBuildInputs
Find missing libsRun ldd result/bin/app for "not found"
Quick test binarynix-shell -p steam-run; steam-run ./binary
Debug autoPatchelfnix log /nix/store/...-drv
Search librariesnix-locate libX11.so.6
Wrapper scriptsAdd makeWrapper to nativeBuildInputs
Version syncUse 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 LibraryNix Package
libgtk-3.so.0gtk3
libglib-2.0.so.0glib
libpulse.so.0libpulseaudio
libGL.so.1mesa or libglvnd
libxkbcommon.so.0libxkbcommon (NOT xorg.libxkbcommon)
libstdc++.so.6stdenv.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 Stats

Stars0
Forks0