Generate Nix binary caches without nix copy<br>- Justus Perlwitz
Generate Nix binary caches without nix copy
Published: July 29, 2026
Here's how to create a Nix binary cache from a derivation's closure within a Nix derivation. Since you can't run nix commands within derivations, this can be useful for including a build closure within an installation medium, such as when performing a NixOS offline installation.
This method uses the binary-cache function in the nixpkgs repository.
Create the following flake.nix Nix flake file in a new directory and follow along:
# Save as flake.nix<br>description = "Nix binary cache demo";<br>inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-26.05";<br>inputs.flake-utils.url = "github:numtide/flake-utils";<br>outputs =<br>self,<br>nixpkgs,<br>flake-utils,<br>}:<br>flake-utils.lib.eachDefaultSystem (<br>system:<br>let<br>pkgs = nixpkgs.legacyPackages.${system};<br>modulePath =<br>"${pkgs.path}/pkgs/build-support/binary-cache/default.nix";<br>mkBinaryModule = import modulePath;<br>mkBinaryCache = pkgs.callPackage mkBinaryModule { };<br>rootPaths = [ pkgs.hello ];<br>in<br>packages.default = mkBinaryCache { inherit rootPaths; };<br>);
How the Nix flake works
Before running the script, observe how the Nix flake works.
pkgs.path gives you the path to nixpkgs for your current system within your Nix store. Here's what pkgs.path evalutes to:
$ nix eval nixpkgs#path<br>/nix/store//9fig…-source/
The modulePath variable "${pkgs.path}/pkgs/build-support/binary-cache/default.nix" evaluates to the following:
/nix/store/9fig…-source/pkgs/build-support/binary-cache/default.nix
This is a real path that you can inspect
$ head (nix eval nixpkgs#path)/pkgs/build-support/\<br>binary-cache/default.nix<br>lib,<br>stdenv,<br>coreutils,<br>jq,<br>[…]
import modulePath imports the contents of this binary-cache/default.nix file. To make this a callable function returning a derivation for your very own binary cache, call the imported contents of modulePath with pkgs.callPackage modulePath { }:
# flake.nix<br>modulePath =<br>"${pkgs.path}/pkgs/build-support/binary-cache/default.nix";<br>mkBinaryModule = import modulePath;<br>mkBinaryCache = pkgs.callPackage mkBinaryModule { };
Assign this pkgs.callPackage result to mkBinaryCache and pass to this result the derivations that you want to include in the binary cache with the rootPaths variable. rootPaths here contains pkgs.hello:
# flake.nix<br>rootPaths = [ pkgs.hello ];<br>packages.default = mkBinaryCache { inherit rootPaths; };
pkgs.hello is the nixpkgs version of saying "Hello, world!":
$ nix run nixpkgs#hello<br>Hello, world!
Build the binary cache
Build the binary cache in flake.nix with nix build:
$ nix build
Review the result:
$ ls -la result<br>[…] result -> /nix/store/f5wf…-binary-cache/<br>$tree result -sh<br>[ 56] result<br>├── [ 64] debuginfo<br>├── [ 389] gdz[…]h1d.narinfo<br>├── [ 385] k28[…]d74.narinfo<br>├── [ 64] log<br>├── [ 128] nar<br>│ ├── [1.2M] 0fx[…]5mj.nar.zst<br>│ └── [ 30K] 0xr[…]2c1.nar.zst<br>├── [ 21] nix-cache-info<br>└── [ 64] realisations
5 directories, 5 files
The .nar.zst files contain compressed Nix archive files. The result directory itself contains a Nix store. Inspect the Nix store:
$ nix store info \<br>--store file:///$PWD/result --json<br>"trusted": true,<br>"url": "file:////p/[…]mp.lM00OzLy141/result"
List the Nix archive file contents using zstdcat1 and nix nar ls:
nix nar ls --recursive \<br>(zstdcat result/nar/0fx[…]5mj.nar.zst | psub) /
Output:
./bin<br>./bin/iconv<br>./lib<br>./lib/i18n<br>./lib/i18n/libBIG5.dylib<br>[…]<br>./share/man/man3/iconvlist.3.gz
Here are the contents of the second Nix archive:
nix nar ls --recursive \<br>(zstdcat result/nar/0xr[…]2c1.nar.zst | psub) /
Output:
./bin<br>./bin/hello<br>./share<br>./share/info<br>./share/info/hello.info<br>./share/man<br>./share/man/man1<br>./share/man/man1/hello.1.gz
"zstdcat - Compress or decompress .zst files" on man.uex.se. Make available with nix shell nixpkgs#zstd ↩
I would be thrilled to hear from you! Please share your thoughts and ideas<br>with me via<br>email.
Back to Index