<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: oxcl</title>
    <description>The latest articles on DEV Community by oxcl (@oxcl).</description>
    <link>https://dev.to/oxcl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1279026%2F409ac660-a119-4b5d-be58-422375a01418.jpg</url>
      <title>DEV Community: oxcl</title>
      <link>https://dev.to/oxcl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oxcl"/>
    <language>en</language>
    <item>
      <title>How I Packaged a .deb File for NixOS with Flakes</title>
      <dc:creator>oxcl</dc:creator>
      <pubDate>Thu, 07 May 2026 12:19:34 +0000</pubDate>
      <link>https://dev.to/oxcl/how-i-packaged-a-deb-file-for-nixos-with-flakes-5dn</link>
      <guid>https://dev.to/oxcl/how-i-packaged-a-deb-file-for-nixos-with-flakes-5dn</guid>
      <description>&lt;p&gt;I wanted to run Helium browser on NixOS. Helium only publishes &lt;code&gt;.deb&lt;/code&gt; packages on GitHub releases. no AUR, no Nix package, nothing. So I packaged it myself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/oxcl/nix-flake-helium-browser" rel="noopener noreferrer"&gt;https://github.com/oxcl/nix-flake-helium-browser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same technique works for any app that ships a &lt;code&gt;.deb&lt;/code&gt; but has no Nix package. This covers the full process: grabbing the &lt;code&gt;.deb&lt;/code&gt; from a GitHub release, unpacking it, patching the binaries so they run on NixOS, putting it all in a flake, and then writing a NixOS module and a Home Manager module on top. Helium is just the example. the pattern applies to any pre-built binary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why NixOS can't just run a .deb
&lt;/h2&gt;

&lt;p&gt;On a normal Linux distro, &lt;code&gt;apt install ./thing.deb&lt;/code&gt; copies files into &lt;code&gt;/usr/lib&lt;/code&gt;, &lt;code&gt;/usr/bin&lt;/code&gt;, etc. The binaries look for shared libraries at those hardcoded paths.&lt;/p&gt;

&lt;p&gt;NixOS doesn't have &lt;code&gt;/usr/lib&lt;/code&gt;. Libraries live under &lt;code&gt;/nix/store/some-hash-name/lib&lt;/code&gt;. A binary compiled on Ubuntu will try to load &lt;code&gt;libc.so.6&lt;/code&gt; from a path that simply doesn't exist on NixOS — it crashes before it does anything.&lt;/p&gt;

&lt;p&gt;The fix is &lt;code&gt;patchelf&lt;/code&gt;. It rewrites the ELF headers of a binary to point to the actual library paths in the Nix store. That's the whole trick. The &lt;a href="https://nixos.wiki/wiki/Packaging/Binaries" rel="noopener noreferrer"&gt;nixpkgs wiki on packaging binaries&lt;/a&gt; is worth reading before you start.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Declare the source with fetchurl
&lt;/h2&gt;

&lt;p&gt;Find the &lt;code&gt;.deb&lt;/code&gt; download URL from the project's GitHub releases page. In Nix, you don't download things with &lt;code&gt;curl&lt;/code&gt; at build time — you declare the source with &lt;code&gt;fetchurl&lt;/code&gt;, which also verifies a hash so the build is reproducible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;pname&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.2.3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;

&lt;span class="nv"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fetchurl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;url&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/someorg/myapp/releases/download/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/myapp_&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_amd64.deb"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get the hash, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nix-prefetch-url &lt;span class="nt"&gt;--type&lt;/span&gt; sha256 &lt;span class="s1"&gt;'https://github.com/someorg/myapp/releases/download/1.2.3/myapp_1.2.3_amd64.deb'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then convert it to SRI format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nix &lt;span class="nb"&gt;hash &lt;/span&gt;to-sri &lt;span class="nt"&gt;--type&lt;/span&gt; sha256 &amp;lt;&lt;span class="nb"&gt;hash &lt;/span&gt;from above&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the project publishes both &lt;code&gt;amd64&lt;/code&gt; and &lt;code&gt;arm64&lt;/code&gt; builds, you can select the right one based on the target platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;suffix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;aarch64-linux&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arm64"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;x86_64-linux&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"amd64"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hostPlatform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;throw&lt;/span&gt; &lt;span class="s2"&gt;"Unsupported system: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hostPlatform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Unpack the .deb
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;.deb&lt;/code&gt; file is an &lt;code&gt;ar&lt;/code&gt; archive. Inside it you'll find &lt;code&gt;data.tar.xz&lt;/code&gt; (the actual files) and &lt;code&gt;control.tar.xz&lt;/code&gt; (package metadata). You only need the data. In &lt;code&gt;stdenv.mkDerivation&lt;/code&gt;, override &lt;code&gt;unpackPhase&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;unpackPhase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  runHook preUnpack&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  ar vx $src&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  tar -xvf data.tar.xz&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  runHook postUnpack&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, you'll have the directory structure from the &lt;code&gt;.deb&lt;/code&gt; in your build directory — things like &lt;code&gt;usr/bin/myapp&lt;/code&gt;, &lt;code&gt;usr/share/applications/myapp.desktop&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;You need &lt;code&gt;binutils&lt;/code&gt; (which provides &lt;code&gt;ar&lt;/code&gt;) in &lt;code&gt;nativeBuildInputs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;nativeBuildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;patchelf&lt;/span&gt; &lt;span class="nv"&gt;makeWrapper&lt;/span&gt; &lt;span class="nv"&gt;binutils&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nativeBuildInputs&lt;/code&gt; is for tools that run during the build. &lt;code&gt;buildInputs&lt;/code&gt; is for libraries the package links against at runtime. Mixing them up breaks cross-compilation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Copy files and patch the binaries
&lt;/h2&gt;

&lt;p&gt;The install phase copies files out of the unpacked &lt;code&gt;.deb&lt;/code&gt; into &lt;code&gt;$out&lt;/code&gt; (your package's Nix store path), then patches the binaries so they can actually run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;installPhase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  runHook preInstall&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  mkdir -p $out/bin $out/share&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  # Copy the binary and shared assets&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  cp usr/bin/myapp $out/bin/myapp&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  cp -r usr/share  $out/share&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  # Patch the binary to use the Nix linker and library paths&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  patchelf \&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    --set-rpath "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;libPath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" \&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    $out/bin/myapp&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  # Fix absolute paths in the .desktop file&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  substituteInPlace $out/share/applications/myapp.desktop \&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    --replace-fail 'Exec=myapp' "Exec=$out/bin/myapp"&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="s2"&gt;  runHook postInstall&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;--set-interpreter&lt;/code&gt;&lt;/strong&gt; rewrites which dynamic linker the binary uses. On Ubuntu this is something like &lt;code&gt;/lib64/ld-linux-x86-64.so.2&lt;/code&gt;, which doesn't exist on NixOS. &lt;code&gt;$(cat $NIX_CC/nix-support/dynamic-linker)&lt;/code&gt; gives you the correct one from the Nix store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--set-rpath&lt;/code&gt;&lt;/strong&gt; rewrites where the binary looks for shared libraries at runtime. The &lt;code&gt;libPath&lt;/code&gt; variable is built from your dependency list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;deps&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;zlib&lt;/span&gt; &lt;span class="nv"&gt;glib&lt;/span&gt; &lt;span class="nv"&gt;dbus&lt;/span&gt; &lt;span class="c"&gt;/* whatever your app actually needs */&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;libPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;makeLibraryPath&lt;/span&gt; &lt;span class="nv"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're not sure what your app needs, run it on a normal Linux distro with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LD_DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;libs ./myapp 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"not found"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That lists exactly what's missing. Add those to &lt;code&gt;deps&lt;/code&gt; and repeat until the app starts.&lt;/p&gt;

&lt;p&gt;For a real-world example with a complex dependency list (Chromium-based apps need a lot), see &lt;a href="https://github.com/oxcl/nix-flake-helium-browser/blob/main/helium.nix" rel="noopener noreferrer"&gt;helium.nix&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A note on wrapGAppsHook
&lt;/h3&gt;

&lt;p&gt;If you're packaging a GTK app, replace &lt;code&gt;makeWrapper&lt;/code&gt; in &lt;code&gt;nativeBuildInputs&lt;/code&gt; with &lt;code&gt;wrapGAppsHook3&lt;/code&gt;. It handles GSettings schemas, icon themes, and other GTK machinery automatically. You then inject extra flags in &lt;code&gt;preFixup&lt;/code&gt; rather than calling &lt;code&gt;wrapProgram&lt;/code&gt; manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;preFixup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  gappsWrapperArgs+=(&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    --prefix LD_LIBRARY_PATH : "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;libPath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  )&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For non-GTK apps, &lt;code&gt;makeWrapper&lt;/code&gt; with a plain &lt;code&gt;wrapProgram&lt;/code&gt; call is enough. See the &lt;a href="https://nixos.org/manual/nixpkgs/stable/#ssec-gnome-common-issues-wrap-gapps-hook" rel="noopener noreferrer"&gt;wrapGAppsHook documentation&lt;/a&gt; for the full picture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: The package file and the flake
&lt;/h2&gt;

&lt;p&gt;Put the derivation in its own file — &lt;code&gt;myapp.nix&lt;/code&gt;. The &lt;code&gt;flake.nix&lt;/code&gt; wires everything together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My app flake"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:NixOS/nixpkgs/nixos-unstable"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt;
      &lt;span class="nv"&gt;supportedSystems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"x86_64-linux"&lt;/span&gt; &lt;span class="s2"&gt;"aarch64-linux"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="nv"&gt;forAllSystems&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;genAttrs&lt;/span&gt; &lt;span class="nv"&gt;supportedSystems&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;in&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;forAllSystems&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;legacyPackages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="kn"&gt;in&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nv"&gt;myapp&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;callPackage&lt;/span&gt; &lt;span class="sx"&gt;./myapp.nix&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
          &lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nv"&gt;apps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;forAllSystems&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nv"&gt;type&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nv"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/myapp"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nv"&gt;overlays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;final&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;myapp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;final&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;callPackage&lt;/span&gt; &lt;span class="sx"&gt;./myapp.nix&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nv"&gt;nixosModules&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./modules/nixos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;homeModules&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./modules/home-manager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;forAllSystems&lt;/code&gt; runs the function for each supported system and collects the results. &lt;code&gt;pkgs.callPackage&lt;/code&gt; injects arguments into &lt;code&gt;myapp.nix&lt;/code&gt; automatically by matching parameter names against packages in &lt;code&gt;pkgs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once this is in place, anyone can run your app with &lt;code&gt;nix run github:you/myapp-flake&lt;/code&gt; without installing anything. For flake basics, the &lt;a href="https://nixos.wiki/wiki/Flakes" rel="noopener noreferrer"&gt;NixOS wiki on flakes&lt;/a&gt; is the best starting point.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: The NixOS Module
&lt;/h2&gt;

&lt;p&gt;A NixOS module lets users configure your package declaratively in their &lt;code&gt;configuration.nix&lt;/code&gt;. Every module has the same basic shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* declare options */&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nv"&gt;config&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* apply them when enabled */&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A minimal one for any app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;in&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkEnableOption&lt;/span&gt; &lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkOption&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;type&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;package&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkOption&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;type&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;listOf&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;default&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
      &lt;span class="nv"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Extra command-line flags to pass at launch."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkIf&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;systemPackages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;package&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lib.mkIf&lt;/code&gt; means nothing fires unless &lt;code&gt;enable = true&lt;/code&gt;. The &lt;code&gt;flags&lt;/code&gt; option passes down to the package derivation via &lt;code&gt;.override&lt;/code&gt;, and the wrapper script bakes them in — so the binary in &lt;code&gt;$PATH&lt;/code&gt; always runs with those flags appended.&lt;/p&gt;

&lt;p&gt;To use the module, users add your flake as an input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:NixOS/nixpkgs/nixos-unstable"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:you/myapp-flake"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;follows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nixpkgs"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nv"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;nixosConfigurations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;my-system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixosSystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;system&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"x86_64-linux"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixosModules&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;
        &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;overlays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;overlays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="sx"&gt;./configuration.nix&lt;/span&gt;
      &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;configuration.nix&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;flags&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"--some-flag"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://nixos.org/manual/nixos/stable/#sec-writing-modules" rel="noopener noreferrer"&gt;NixOS module system documentation&lt;/a&gt; covers the full &lt;code&gt;options&lt;/code&gt;/&lt;code&gt;config&lt;/code&gt; API — the official docs are actually good here.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: The Home Manager Module
&lt;/h2&gt;

&lt;p&gt;Structurally identical to the NixOS module, but scoped to a single user. The &lt;code&gt;config&lt;/code&gt; block writes to user-level paths instead of system ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkIf&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;package&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:NixOS/nixpkgs/nixos-unstable"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:nix-community/home-manager"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:you/myapp-flake"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nv"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;homeConfigurations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"youruser"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;homeManagerConfiguration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;legacyPackages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;x86_64-linux&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nv"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;homeModules&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;
        &lt;span class="sx"&gt;./home.nix&lt;/span&gt;
      &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;home.nix&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;myapp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;flags&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"--start-maximized"&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://nix-community.github.io/home-manager/" rel="noopener noreferrer"&gt;Home Manager manual&lt;/a&gt; covers everything. If you already understand the NixOS module system, this one is the same pattern.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build&lt;/span&gt;
nix build .#myapp

&lt;span class="c"&gt;# Run it&lt;/span&gt;
./result/bin/myapp

&lt;span class="c"&gt;# See what the wrapper script actually does&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;result/bin/myapp

&lt;span class="c"&gt;# Check what the binary links against&lt;/span&gt;
ldd result/bin/myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;ldd&lt;/code&gt; shows &lt;code&gt;=&amp;gt; not found&lt;/code&gt;, add those libraries to &lt;code&gt;deps&lt;/code&gt; and rebuild. That loop — build, ldd, add dep, repeat — is most of the real work when packaging pre-built binaries. It's not glamorous, but it's finite.&lt;/p&gt;

&lt;p&gt;For real-world reference, the nixpkgs packages for &lt;a href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/browsers/vivaldi/default.nix" rel="noopener noreferrer"&gt;Vivaldi&lt;/a&gt; and &lt;a href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/browsers/brave/default.nix" rel="noopener noreferrer"&gt;Brave&lt;/a&gt; use this same &lt;code&gt;.deb&lt;/code&gt;-extraction pattern. Comparing against those when something isn't working is usually faster than reading docs.&lt;/p&gt;




&lt;h2&gt;
  
  
  One thing worth adding from day one
&lt;/h2&gt;

&lt;p&gt;The version and SHA256 are hardcoded in the package file. When the app releases a new version, those values need manual updates. A GitHub Actions workflow that checks for new releases on a schedule and opens a PR when something changes is worth setting up early — otherwise the package goes stale and you forget about it for months.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full example: Helium Browser
&lt;/h2&gt;

&lt;p&gt;This entire post came from wanting to use &lt;a href="https://helium.computer" rel="noopener noreferrer"&gt;Helium&lt;/a&gt; on NixOS — a private, Chromium-based browser that ships with uBlock Origin built in and no Google account integration. It's a solid daily driver if you want a clean browser without an afternoon of extension configuration.&lt;/p&gt;

&lt;p&gt;The flake that packages it has everything covered in this post, plus multi-arch support, Wayland detection, a Chromium policy system in the NixOS module, and a GitHub Actions auto-update workflow. If you use NixOS and want a browser that's already packaged up with declarative config support, give it a try.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/oxcl/nix-flake-helium-browser" rel="noopener noreferrer"&gt;github.com/oxcl/nix-flake-helium-browser&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If it's useful to you, a ⭐ on the repo is appreciated. And if you end up packaging something with this pattern and run into issues, pull requests are open.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nixos.wiki/wiki/Packaging/Binaries" rel="noopener noreferrer"&gt;NixOS wiki: Packaging Binaries&lt;/a&gt; — start here&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nixos.wiki/wiki/Flakes" rel="noopener noreferrer"&gt;NixOS wiki: Flakes&lt;/a&gt; — flake basics and setup&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nix.dev/concepts/flakes.html" rel="noopener noreferrer"&gt;nix.dev: Flake concepts&lt;/a&gt; — the output schema reference&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nixos.org/manual/nixos/stable/#sec-writing-modules" rel="noopener noreferrer"&gt;NixOS module system&lt;/a&gt; — writing your own modules&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nixos.org/manual/nixpkgs/stable/#chap-overlays" rel="noopener noreferrer"&gt;nixpkgs overlays&lt;/a&gt; — how overlays work&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nix-community.github.io/home-manager/" rel="noopener noreferrer"&gt;Home Manager manual&lt;/a&gt; — everything home-manager&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nixos.org/manual/nixpkgs/stable/#ssec-gnome-common-issues-wrap-gapps-hook" rel="noopener noreferrer"&gt;wrapGAppsHook documentation&lt;/a&gt; — for GTK apps specifically&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/oxcl/nix-flake-helium-browser/blob/main/helium.nix" rel="noopener noreferrer"&gt;helium.nix&lt;/a&gt; — full real-world derivation for a complex app&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/browsers/vivaldi/default.nix" rel="noopener noreferrer"&gt;Vivaldi nixpkgs package&lt;/a&gt; — .deb repackaging reference&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/browsers/brave/default.nix" rel="noopener noreferrer"&gt;Brave nixpkgs package&lt;/a&gt; — same pattern, different app&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What If Money Is Time? A Wild Take on Economical Relativity</title>
      <dc:creator>oxcl</dc:creator>
      <pubDate>Sat, 29 Mar 2025 10:05:21 +0000</pubDate>
      <link>https://dev.to/oxcl/what-if-money-is-time-a-wild-take-on-economical-relativity-111b</link>
      <guid>https://dev.to/oxcl/what-if-money-is-time-a-wild-take-on-economical-relativity-111b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9j7nvrlkobfrpu96eh8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9j7nvrlkobfrpu96eh8.jpg" alt="how GDP and technological advancements are tied to our perception of time" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
You’ve heard “time is money” a million times. But what if we flip it? What if money — GDP, cash flow, economic juice — is actually time? Not the ticking-clock kind, but the way societies move through history. The faster your economy grows, the quicker you blast into the future. The slower it crawls — or collapses — the more you’re stuck in the past. I call it economical relativity, and it’s been rattling around my brain lately. Let me break it down.&lt;/p&gt;

&lt;p&gt;Think about North Korea and South Korea. Same people, same language, split by a border. North Korea’s GDP per person is barely $1,700 — most folks don’t have internet, electricity’s a gamble, and food’s a daily hustle. It’s like living in the 1800s, scraping by with no window to the world. Then there’s South Korea — $34,000 per head, high-speed everything, skyscrapers, K-pop. They’re not just richer; they’re in a different era. Money didn’t just buy stuff — it sped up their societal clock while North Korea’s stayed frozen.&lt;/p&gt;

&lt;p&gt;History’s full of this. Way back, fire was the first big win. It cooked food, kept us warm, let us craft better tools — boom, prehistoric GDP spiked, and human life leaped forward. Bows and arrows? Same deal — hunting got easier, food piled up, tribes grew. Fast-forward to steam engines: factories popped up, cities exploded, and the industrial age rewrote time in decades, not centuries. Each technological advancement pumped the economy, and with it, society raced ahead.&lt;/p&gt;

&lt;p&gt;Now look at Poland. A hundred years ago, they were dirt poor, barely scraping by — like North Korea today. But since the ’90s, their GDP’s soared over tenfold. They didn’t just catch up; they hit fast-forward, building a modern world while the US, already comfy, just coasted. For Poland, those decades felt like centuries of progress crammed into a sprint. Meanwhile, Venezuela’s a grim flip-side. Their GDP’s crashed 75% since 2013 — now it’s bartering, blackouts, and breadlines. It’s not just a crisis; it’s like 1920 rolled back in.&lt;/p&gt;

&lt;p&gt;Here’s the kicker: tech’s the engine, and AI’s the next beast. Countries jumping on artificial intelligence could turbocharge their economies — think healthcare breakthroughs, automated factories, smarter cities. Decades of progress might hit in a handful of years. South Korea’s already leaning in, while others sleep on it. The gap’s growing — not just in wealth, but in time. One nation’s living in 2040, another’s stuck in 2020. Adoption’s the catch, though — no investment, no skills, no infrastructure? You’re left behind, clock ticking slow.&lt;/p&gt;

&lt;p&gt;So, economical relativity isn’t some abstract theory. It’s how money bends our sense of history. GDP growth doesn’t just pile up cash — it compresses time, shoving societies into the future. Stagnation or collapse? Time stretches, dragging you back to a world your ancestors might recognize. From fire to AI, technological advancement’s been the spark, lighting up economies and rewinding or fast-forwarding the human story.&lt;/p&gt;

&lt;p&gt;Next time you hear about GDP stats, don’t yawn. It’s not just numbers — it’s a time machine. Poland’s sprinting, Venezuela’s rewinding, and AI’s about to hit the gas. Money isn’t just power; it’s how fast we live.&lt;/p&gt;

</description>
      <category>economy</category>
      <category>ai</category>
      <category>programming</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
