Binary Cache: Difference between revisions

From NixOS Wiki
imported>Tfc
Incorporate musicmatze
Fsbof (talk | contribs)
m Removed extra-substituters as not available since 22.05, Added Signing Existing Packages, Added Command Line Options
 
(29 intermediate revisions by 18 users not shown)
Line 1: Line 1:
Every machine with nix installed can be a configured to be a binary cache for another nix machine - no matter if it is a NixOS, other Linux distro, or MacOS machine.
{{Expansion|What is the format of a binary cache? How does it differ from a local/remote Nix store? See [https://github.com/NixOS/nix/pull/6870 `NixOS/nix` PR #6870]. (Maybe even splitting it into a guide and a reference?)}}


== Setting up a NixOS Machine as Binary Cache for Others ==
A binary cache builds Nix packages and caches the result for other machines. Any machine with Nix installed can be a binary cache for another one, no matter the operating system.


This tutorial assumes:
If you are facing problems with derivations not being in a cache, try switching to a release version. Most caches will have many derivations for a specific release.


* NixOS on the serving machine
== Setting up a binary cache ==
* You want to serve the nix store via port 80 and already have an nginx service running (See here how to configure nginx [https://nixos.wiki/wiki/Nginx])
* The store is served with signing activated
* Firewall rules (port 80) are already set up (See firewall settings in NixOS manual[https://nixos.org/nixos/manual/index.html#sec-firewall])
* The hostname "binarycache.mydomain.com" points to the server (see <code>networking.hostName</code>[https://nixos.org/nixos/manual/options.html#opt-networking.hostName])


This tutorial explains the following steps one by one in the following:
This tutorial explains how to setup a machine as a binary cache for other machines, serving the nix store on TCP port 80 with signing turned on. It assumes that an {{ic|[[nginx]]}} service is already running, that port 80 is open,<ref group="cf."> {{manual:nixos|sec=#sec-firewall|chapter=11.5. Firewall}}</ref> and that the hostname {{ic|binarycache.example.com}} resolves to the server.<ref group="cf.">{{nixos:option|networking.hostName}}</ref>


# Generate a private/public keypair for signing packages
=== 1. Generating a private/public keypair ===
#* This step is not mandatory, but we are going to serve signed nix packages
# Activate <code>nix-serve</code>
#* This is the service that speaks the binary cache protocol via HTTP.
#* It will use the private key to sign the packages
# Create a virtual hostname in <code>nginx</code>
#* It will redirect the HTTP(s) traffic from port 80 to <code>nix-serve</code>
# Rebuild the NixOS config and test


=== 1. Generate a private/public keypair ===
A keypair is necessary to sign Nix packages. Replace <code>binarycache.example.com</code> with your domain.


<syntaxhighlight lang="bash">
{{bc|
$ nix-store --generate-binary-cache-key binarycache.mydomain.com1 cache-priv-key.pem cache-pub-key.pem
cd /var
$ sudo mv cache-priv-key.pem /var/cache-priv-key.pem
nix-store --generate-binary-cache-key binarycache.example.com cache-priv-key.pem cache-pub-key.pem
$ sudo chown nix-store /var/cache-priv-key.pem
chown nix-serve cache-priv-key.pem
$ sudo chmod 600 /var/cache-priv-key.pem
chmod 600 cache-priv-key.pem
</syntaxhighlight>
cat cache-pub-key.pem
}}
 
The packages can be signed before adding them to the binary cache, or on the fly as they are served.
In this tutorial we'll set up {{ic|nix-serve}} to sign packages on the fly when it serves them.
In this case it is important that only {{ic|nix-serve}} can access the private key.
The location {{ic|/var/cache-priv-key.pem}} is just an example.


It is important that only <code>nix-serve</code> can access the private key.
=== 2. Activating {{ic|nix-serve}} ===
The location <code>/var/cache-priv-key.pem</code> is just an example.


=== 2. Activate <code>nix-serve</code> ===
{{ic|nix-serve}} is the service that speaks the binary cache protocol via HTTP.


To start it on NixOS:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.nix-serve = {
services.nix-serve = {
Line 43: Line 38:
</syntaxhighlight>
</syntaxhighlight>


<code>nix-serve</code> will by default serve on port 5000. We are not going to open a firewall port for it, because we will let <code>nginx</code> redirect to it.
To start it on a non-NixOS machine at boot, add to {{ic|/etc/crontab}}:
<syntaxhighlight lang="crontab">
NIX_SECRET_KEY_FILE=/var/cache-priv-key.pem
@reboot /home/USER/.nix-profile/bin/nix-serve --listen :5000 --error-log /var/log/nix-serve.log --pid /var/run/nix-serve.pid --user USER --daemonize
</syntaxhighlight>
 
{{ic|nix-serve}} will by default serve on port 5000. We are not going to open a firewall port for it, because we will let {{ic|nginx}} redirect to it.
 
=== 3. Creating a virtual hostname in {{ic|nginx}} ===


=== 3. Create a virtual hostname in <code>nginx</code> ===
We redirect the HTTP(s) traffic from port 80 to {{ic|nix-serve}}. As {{ic|nix-serve}} is capable of serving only on IPv4, redirecting is also useful to make the binary cache available on IPv6.


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.nginx = {
services.nginx = {
   enable = true;
   enable = true;
  recommendedProxySettings = true;
   virtualHosts = {
   virtualHosts = {
     # ... existing hosts config etc. ...
     # ... existing hosts config etc. ...
     "binarycache.mydomain.com" = {
     "binarycache.example.com" = {
      serverAliases = [ "binarycache" ];
       locations."/".proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
       locations."/".extraConfig = ''
        proxy_pass http://localhost:${toString config.services.nix-serve.port};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      '';
     };
     };
   };
   };
Line 65: Line 63:
</syntaxhighlight>
</syntaxhighlight>


Add HTTPS settings to this config if possible. The tutorial will simply continue with unsecure HTTP. (See NixOS manual on how to set up HTTPS with letsencrypt[https://nixos.org/nixos/manual/index.html#module-security-acme-nginx])
Add HTTPS settings to this config if possible.<ref group="cf.">{{manual:nixos|sec=#module-security-acme-nginx|chapter=26.3. Using ACME certificates in Nginx}}</ref> This tutorial will simply continue with insecure HTTP.


=== 4. Rebuild the NixOS config and test ===
To set up Nginx on a non-NixOS machine, create for example {{ic|/etc/nginx/sites-enabled/nix-serve.conf}}:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="nginx">
sudo nixos-rebuild switch
server {
    listen      80 default_server;
    listen      [::]:80 default_server;
    location / {
        proxy_pass  http://127.0.0.1:5000;
    }
}
</syntaxhighlight>
</syntaxhighlight>
=== 4. Testing ===
To apply the previous settings to your NixOS machine, run:
{{bc|# nixos-rebuild switch}}


Check the general availability:
Check the general availability:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
$ curl http://binarycache.mydomain.com/nix-cache-info
$ curl http://binarycache.example.com/nix-cache-info
StoreDir: /nix/store
StoreDir: /nix/store
WantMassQuery: 1
WantMassQuery: 1
Line 87: Line 97:
</syntaxhighlight>
</syntaxhighlight>


On some other machine, test if nix can realize the same package via the binary cache (the content of the <code>trusted-public-keys</code> is the content of the file <code>cache-pub-key.pem</code> which you should share with users of the binary cache!):
To verify the signing on the fly, make sure the following request contains a {{ic|Sig:}} line:
<syntaxhighlight lang="bash">
$ curl http://binarycache.example.com/gdh8165b7rg4y53v64chjys7mbbw89f9.narinfo
StorePath: /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
URL: nar/gdh8165b7rg4y53v64chjys7mbbw89f9.nar
Compression: none
NarHash: sha256:0mkfk4iad66xkld3b7x34n9kxri9lrpkgk8m17p97alacx54h5c7
NarSize: 205920
References: 6yaj6n8l925xxfbcd65gzqx3dz7idrnn-glibc-2.27 gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
Deriver: r6h5b3wy0kwx38rn6s6qmmfq0svcnf86-hello-2.10.drv
Sig: binarycache.example.com:EmAANryZ1FFHGmz5P+HXLSDbc0KckkBEAkHsht7gEIOUXZk9yhhZSBV+eSX9Kj+db/b36qmYmffgiOZbAe21Ag==
</syntaxhighlight>
 
Next, with the public key that was generated to {{ic|cache-pub-key.pem}}, setup a client machine to use the binary cache, and see if Nix successfully fetches the cached package.
 
== Using a binary cache ==
 
To configure Nix to use a certain binary cache, refer to the Nix manual.<ref group="cf.">[https://nixos.org/nix/manual/#ch-files Nix Manual, 21. Files]</ref> Add the binary cache as substituter (see the option {{ic|substituters}}) and the public key to the trusted keys (see {{ic|trusted-public-keys}}).
 
Permanent use of binary cache:
 
<syntaxhighlight lang="nix">
# /etc/nixos/configuration.nix
 
  nix = {
    settings = {
      substituters = [
        "http://binarycache.example.com"
        "https://nix-community.cachix.org"
        "https://cache.nixos.org/"
      ];
      trusted-public-keys = [
        "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD"
        "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
      ];
    };
  };
</syntaxhighlight>As described on [https://search.nixos.org/options?show=nix.settings.substituters&type=packages&query=substituters search.nixos.org] by default <nowiki>https://cache.nixos.org/</nowiki> is added to the substituters. You may need to use lib.mkForce to override this and ensure your substituter is the primary choice.<syntaxhighlight>
# /etc/nixos/configuration.nix
 
 
{ config, lib, pkgs, ... }:
 
{
  nix = {
    settings = {
      substituters = lib.mkForce [
        "http://binarycache.example.com"
      ];
      trusted-public-keys = [
        "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD"
      ];
    };
  };
}
</syntaxhighlight>{{Warning|Keys that are entered incorrectly or are otherwise invalid, aside from preventing you from benefiting from the cached derivations, may also prevent you from rebuilding your system. This is most likely to occur after garbage collection (e.g., via <code>nix-collect-garbage -d</code>). Consult [https://github.com/NixOS/nix/issues/8271 NixOS/nix#8271] for additional details and a workaround.}}
 
Temporary use of binary cache:
 
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
$ nix-store -r /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10 --option substituters http://binarycache.mydomain.com --option trusted-public-keys binarycache.mydomain.com1:dsafdafDFW123fdasfa123124FADSAD
$ nix-store -r /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10 --option substituters http://binarycache.example.com --option trusted-public-keys binarycache.example.com:dsafdafDFW123fdasfa123124FADSAD
these paths will be fetched (0.00 MiB download, 24.04 MiB unpacked):
these paths will be fetched (0.00 MiB download, 24.04 MiB unpacked):
   /nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27
   /nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27
   /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
   /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
copying path '/nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27' from 'http://binarycache.mydomain.com'...
copying path '/nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27' from 'http://binarycache.example.com'...
copying path '/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10' from 'http://binarycache.mydomain.com'...
copying path '/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10' from 'http://binarycache.example.com'...
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
</syntaxhighlight>
</syntaxhighlight>


It works, great! Now you can configure your nix machines to look up packages always/also on this server.
=== Using a binary cache on non-NixOS installations ===
For that, have a look into the Nix manual [https://nixos.org/nix/manual/#name-11] and the following settings:
 
To use a binary cache with a Nix that has been installed on an operating system other than NixOS (e.g. Ubuntu or macOS)  {{ic|/etc/nix/nix.conf}} will need to be edited manually. This can be done by adding something similar to the following lines to {{ic|/etc/nix/nix.conf}}:
 
<pre>
trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
trusted-substituters = https://nix-community.cachix.org https://cache.nixos.org
trusted-users = root @wheel
</pre>
 
Note that not all of that information is needed, see the manual for the respective options ([https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-trusted-public-keys trusted-public-keys], [https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-trusted-substituters trusted-substituters], [https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-trusted-users trusted-users]).
 
With the {{ic|trusted-*}} options set correctly, a user can benefit permanently from a substituter by add the following to their {{ic|~/.config/nix/nix.conf}}
 
<pre>
substituters = https://nix-community.cachix.org https://cache.nixos.org
</pre>
 
or temporarily as explained above.
 
 
=== Binary cache hint in Flakes ===
 
You can place a hint to your binary cache in your Flake so when someone builds an output of your Flake, the nix command will ask interactively to trust the specified binary cache.
 
<syntaxHighlight lang=nix>
{
  nixConfig = {
    extra-substituters = [
      "https://colmena.cachix.org"
    ];
    extra-trusted-public-keys = [
      "colmena.cachix.org-1:7BzpDnjjH8ki2CT3f6GdOk7QAzPOl+1t3LvTLXqYcSg="
    ];
  };
  outputs = { ... }: {
    ...
  };
}
</syntaxHighlight>
 
== Populating a binary cache ==
 
As the cache is served from the nix store of the machine serving the binary cache, one option is to build the packages directly on that machine.
 
Another option is to build the packages on a separate machine and push them only when all the checks pass using {{ic|nix copy}}:
<syntaxhighlight lang="bash">
$ nix copy --to ssh://binarycache.example.com PACKAGE
</syntaxhighlight>
For details see the [https://nixos.org/manual/nix/stable/package-management/sharing-packages.html Sharing Packages Between Machines] in the Nix manual.
 
== Signing Existing Packages ==
It is also possible to sign all the packages that already exist in the nix store of the machine serving the binary cache to make them immediately available.
<code>$ nix store sign --extra-experimental-features nix-command --all --key-file /var/cache-priv-key.pem</code>
Note : As of NixOS 24.05 {{ic|--extra-experimental-features nix-command}} is required for {{ic|store sign}} if this is not in your configuration.nix.
 
== Hosted binary cache ==
 
https://cachix.org provides hosted binary caches starting with a free plan for public caches.
 
== How to check if content is on a binary cache ==
 
We can use '''curl''' to check if a binary cache contains a given derivation.
''curl https://cache/store_hash.narinfo''
 
<syntaxhighlight lang="bash">
$ curl https://fzakaria.cachix.org/949dxjmz632id67hjic04x6f3ljldzxh.narinfo
 
StorePath: /nix/store/949dxjmz632id67hjic04x6f3ljldzxh-mvn2nix-0.1
URL: nar/4026897ef85219b5b697c1c4ef30d50275423857cb7a81e138c4b1025f550935.nar.xz
Compression: xz
FileHash: sha256:4026897ef85219b5b697c1c4ef30d50275423857cb7a81e138c4b1025f550935
FileSize: 24392
NarHash: sha256:0kk3d8rk82ynqwg8isk83hvq8vszh4354fqg4hhaz40kd49rmm9n
NarSize: 29208
References: 2hhmmj0vbb5d181nfx2mx3p7k54q44ij-apache-maven-3.6.3 6737cq9nvp4k5r70qcgf61004r0l2g3v-bash-4.4-p23 949dxjmz632id67hjic04x6f3ljldzxh-mvn2nix-0.1 hrlxlk768vy5rgl6hc4xiba6gxg6s0yz-mvn2nix-0.1-dependencies qybd7j6v7kb7yhizc7gklgg3lyrxf38y-openjdk-headless-11.0.8+10
Deriver: 585w6p8rclbvz97fwgixvfgnh5493ia2-mvn2nix-0.1.drv
Sig: fzakaria.cachix.org-1:MkOrZCa9qdxHFdE2mtFRsbEzmLUgWGgSrqD3advKfdHLW+SKxj/V2n6+4a/qy6dhCoR+gWQfGzda/jNkER10CQ==
</syntaxhighlight>
 
Or use ''nix path-info'':
<syntaxhighlight lang="bash">
$ nix path-info -r /nix/store/sb7nbfcc1ca6j0d0v18f7qzwlsyvi8fz-ocaml-4.10.0 --store https://cache.nixos.org/
[0.0 MiB DL] querying libunistring-0.9.10 on https://cache.nixos.org/nix/store/0gc9dr71ldp79cla2qbl3kwdd4ig46pi-linux-headers-5.5
/nix/store/2jysm3dfsgby5sw5jgj43qjrb5v79ms9-bash-4.4-p23
/nix/store/4wy9j24psf9ny4di3anjs7yk2fvfb0gq-glibc-2.31-dev
/nix/store/4z79ipgxqn80ns7mpax25zmb77i3ndfw-gawk-5.1.0
/nix/store/9df65igwjmf2wbw0gbrrgair6piqjgmi-glibc-2.31
/nix/store/czc3c1apx55s37qx4vadqhn3fhikchxi-libunistring-0.9.10
/nix/store/fgn3sih5vi7543jcw389a7qqax8nwkhz-glibc-2.31-bin
/nix/store/sb7nbfcc1ca6j0d0v18f7qzwlsyvi8fz-ocaml-4.10.0
/nix/store/xim9l8hym4iga6d4azam4m0k0p1nw2rm-libidn2-2.3.0
</syntaxhighlight>
 
Example: Fetch metadata of <code>bash</code>
 
<pre>
curl https://cache.nixos.org/$(readlink -f $(which bash) | cut -c12-43).narinfo
</pre>
 
== Command Line Options ==
It is also possible to pass {{ic|substituters}} and {{ic|trusted-public-keys}} on the command line if they are not in {{ic|configuration.nix}} or you want to use a particular binary cache server.
$ nix-build --option substituters "<nowiki>http://binarycache.example.com</nowiki>" --option trusted-public-keys "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD" '<nixpkgs>' -A pkgs.PACKAGE
 
$ nixos-rebuild --option substituters "<nowiki>http://binarycache.example.com</nowiki>" --option trusted-public-keys "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD" switch
To do an offline install (providing your binary cache contains all the packages required);
$ nixos-install --option substituters "<nowiki>http://binarycache.example.com</nowiki>" --option trusted-public-keys "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD"
 
== See also ==
<references group="cf."/>
 
* [https://discourse.nixos.org/t/how-to-use-binary-cache-in-nixos/5202/4 How to use binary cache in NixOS]
 
* [https://github.com/zhaofengli/attic attic: Multi-tenant Nix Binary Cache]


* substituters
* [https://discourse.nixos.org/t/nix-binary-cache-for-macos-nix-darwin-with-attic/40118 Nix Binary Cache for MacOS/Nix-Darwin with Attic]
* extra-substituters
* trusted-public-keys

Latest revision as of 10:10, 1 July 2024

A binary cache builds Nix packages and caches the result for other machines. Any machine with Nix installed can be a binary cache for another one, no matter the operating system.

If you are facing problems with derivations not being in a cache, try switching to a release version. Most caches will have many derivations for a specific release.

Setting up a binary cache

This tutorial explains how to setup a machine as a binary cache for other machines, serving the nix store on TCP port 80 with signing turned on. It assumes that an nginx service is already running, that port 80 is open,[cf. 1] and that the hostname binarycache.example.com resolves to the server.[cf. 2]

1. Generating a private/public keypair

A keypair is necessary to sign Nix packages. Replace binarycache.example.com with your domain.

cd /var
nix-store --generate-binary-cache-key binarycache.example.com cache-priv-key.pem cache-pub-key.pem
chown nix-serve cache-priv-key.pem
chmod 600 cache-priv-key.pem
cat cache-pub-key.pem

The packages can be signed before adding them to the binary cache, or on the fly as they are served. In this tutorial we'll set up nix-serve to sign packages on the fly when it serves them. In this case it is important that only nix-serve can access the private key. The location /var/cache-priv-key.pem is just an example.

2. Activating nix-serve

nix-serve is the service that speaks the binary cache protocol via HTTP.

To start it on NixOS:

services.nix-serve = {
  enable = true;
  secretKeyFile = "/var/cache-priv-key.pem";
};

To start it on a non-NixOS machine at boot, add to /etc/crontab:

NIX_SECRET_KEY_FILE=/var/cache-priv-key.pem
@reboot /home/USER/.nix-profile/bin/nix-serve --listen :5000 --error-log /var/log/nix-serve.log --pid /var/run/nix-serve.pid --user USER --daemonize

nix-serve will by default serve on port 5000. We are not going to open a firewall port for it, because we will let nginx redirect to it.

3. Creating a virtual hostname in nginx

We redirect the HTTP(s) traffic from port 80 to nix-serve. As nix-serve is capable of serving only on IPv4, redirecting is also useful to make the binary cache available on IPv6.

services.nginx = {
  enable = true;
  recommendedProxySettings = true;
  virtualHosts = {
    # ... existing hosts config etc. ...
    "binarycache.example.com" = {
      locations."/".proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
    };
  };
};

Add HTTPS settings to this config if possible.[cf. 3] This tutorial will simply continue with insecure HTTP.

To set up Nginx on a non-NixOS machine, create for example /etc/nginx/sites-enabled/nix-serve.conf:

server {
    listen      80 default_server;
    listen      [::]:80 default_server;
			
    location / {
        proxy_pass  http://127.0.0.1:5000;
    }
}

4. Testing

To apply the previous settings to your NixOS machine, run:

# nixos-rebuild switch

Check the general availability:

$ curl http://binarycache.example.com/nix-cache-info
StoreDir: /nix/store
WantMassQuery: 1
Priority: 30

On the binary cache server, build some package:

$ nix-build '<nixpkgs>' -A pkgs.hello
/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10

To verify the signing on the fly, make sure the following request contains a Sig: line:

$ curl http://binarycache.example.com/gdh8165b7rg4y53v64chjys7mbbw89f9.narinfo
StorePath: /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
URL: nar/gdh8165b7rg4y53v64chjys7mbbw89f9.nar
Compression: none
NarHash: sha256:0mkfk4iad66xkld3b7x34n9kxri9lrpkgk8m17p97alacx54h5c7
NarSize: 205920
References: 6yaj6n8l925xxfbcd65gzqx3dz7idrnn-glibc-2.27 gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
Deriver: r6h5b3wy0kwx38rn6s6qmmfq0svcnf86-hello-2.10.drv
Sig: binarycache.example.com:EmAANryZ1FFHGmz5P+HXLSDbc0KckkBEAkHsht7gEIOUXZk9yhhZSBV+eSX9Kj+db/b36qmYmffgiOZbAe21Ag==

Next, with the public key that was generated to cache-pub-key.pem, setup a client machine to use the binary cache, and see if Nix successfully fetches the cached package.

Using a binary cache

To configure Nix to use a certain binary cache, refer to the Nix manual.[cf. 4] Add the binary cache as substituter (see the option substituters) and the public key to the trusted keys (see trusted-public-keys).

Permanent use of binary cache:

# /etc/nixos/configuration.nix

  nix = {
    settings = {
      substituters = [
        "http://binarycache.example.com"
        "https://nix-community.cachix.org"
        "https://cache.nixos.org/"
      ];
      trusted-public-keys = [
        "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD"
        "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
      ];
    };
  };

As described on search.nixos.org by default https://cache.nixos.org/ is added to the substituters. You may need to use lib.mkForce to override this and ensure your substituter is the primary choice.

# /etc/nixos/configuration.nix


{ config, lib, pkgs, ... }:

{
  nix = {
    settings = {
      substituters = lib.mkForce [
        "http://binarycache.example.com"
      ];
      trusted-public-keys = [
        "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD"
      ];
    };
  };
}
Warning: Keys that are entered incorrectly or are otherwise invalid, aside from preventing you from benefiting from the cached derivations, may also prevent you from rebuilding your system. This is most likely to occur after garbage collection (e.g., via nix-collect-garbage -d). Consult NixOS/nix#8271 for additional details and a workaround.

Temporary use of binary cache:

$ nix-store -r /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10 --option substituters http://binarycache.example.com --option trusted-public-keys binarycache.example.com:dsafdafDFW123fdasfa123124FADSAD
these paths will be fetched (0.00 MiB download, 24.04 MiB unpacked):
  /nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27
  /nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10
copying path '/nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27' from 'http://binarycache.example.com'...
copying path '/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10' from 'http://binarycache.example.com'...
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
/nix/store/gdh8165b7rg4y53v64chjys7mbbw89f9-hello-2.10

Using a binary cache on non-NixOS installations

To use a binary cache with a Nix that has been installed on an operating system other than NixOS (e.g. Ubuntu or macOS) /etc/nix/nix.conf will need to be edited manually. This can be done by adding something similar to the following lines to /etc/nix/nix.conf:

trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
trusted-substituters = https://nix-community.cachix.org https://cache.nixos.org
trusted-users = root @wheel

Note that not all of that information is needed, see the manual for the respective options (trusted-public-keys, trusted-substituters, trusted-users).

With the trusted-* options set correctly, a user can benefit permanently from a substituter by add the following to their ~/.config/nix/nix.conf

substituters = https://nix-community.cachix.org https://cache.nixos.org

or temporarily as explained above.


Binary cache hint in Flakes

You can place a hint to your binary cache in your Flake so when someone builds an output of your Flake, the nix command will ask interactively to trust the specified binary cache.

{
  nixConfig = {
    extra-substituters = [
      "https://colmena.cachix.org"
    ];
    extra-trusted-public-keys = [
      "colmena.cachix.org-1:7BzpDnjjH8ki2CT3f6GdOk7QAzPOl+1t3LvTLXqYcSg="
    ];
  };
  outputs = { ... }: {
    ...
  };
}

Populating a binary cache

As the cache is served from the nix store of the machine serving the binary cache, one option is to build the packages directly on that machine.

Another option is to build the packages on a separate machine and push them only when all the checks pass using nix copy:

$ nix copy --to ssh://binarycache.example.com PACKAGE

For details see the Sharing Packages Between Machines in the Nix manual.

Signing Existing Packages

It is also possible to sign all the packages that already exist in the nix store of the machine serving the binary cache to make them immediately available.

$ nix store sign --extra-experimental-features nix-command --all --key-file /var/cache-priv-key.pem

Note : As of NixOS 24.05 --extra-experimental-features nix-command is required for store sign if this is not in your configuration.nix.

Hosted binary cache

https://cachix.org provides hosted binary caches starting with a free plan for public caches.

How to check if content is on a binary cache

We can use curl to check if a binary cache contains a given derivation. curl https://cache/store_hash.narinfo

$ curl https://fzakaria.cachix.org/949dxjmz632id67hjic04x6f3ljldzxh.narinfo

StorePath: /nix/store/949dxjmz632id67hjic04x6f3ljldzxh-mvn2nix-0.1
URL: nar/4026897ef85219b5b697c1c4ef30d50275423857cb7a81e138c4b1025f550935.nar.xz
Compression: xz
FileHash: sha256:4026897ef85219b5b697c1c4ef30d50275423857cb7a81e138c4b1025f550935
FileSize: 24392
NarHash: sha256:0kk3d8rk82ynqwg8isk83hvq8vszh4354fqg4hhaz40kd49rmm9n
NarSize: 29208
References: 2hhmmj0vbb5d181nfx2mx3p7k54q44ij-apache-maven-3.6.3 6737cq9nvp4k5r70qcgf61004r0l2g3v-bash-4.4-p23 949dxjmz632id67hjic04x6f3ljldzxh-mvn2nix-0.1 hrlxlk768vy5rgl6hc4xiba6gxg6s0yz-mvn2nix-0.1-dependencies qybd7j6v7kb7yhizc7gklgg3lyrxf38y-openjdk-headless-11.0.8+10
Deriver: 585w6p8rclbvz97fwgixvfgnh5493ia2-mvn2nix-0.1.drv
Sig: fzakaria.cachix.org-1:MkOrZCa9qdxHFdE2mtFRsbEzmLUgWGgSrqD3advKfdHLW+SKxj/V2n6+4a/qy6dhCoR+gWQfGzda/jNkER10CQ==

Or use nix path-info:

$ nix path-info -r /nix/store/sb7nbfcc1ca6j0d0v18f7qzwlsyvi8fz-ocaml-4.10.0 --store https://cache.nixos.org/
[0.0 MiB DL] querying libunistring-0.9.10 on https://cache.nixos.org/nix/store/0gc9dr71ldp79cla2qbl3kwdd4ig46pi-linux-headers-5.5
/nix/store/2jysm3dfsgby5sw5jgj43qjrb5v79ms9-bash-4.4-p23
/nix/store/4wy9j24psf9ny4di3anjs7yk2fvfb0gq-glibc-2.31-dev
/nix/store/4z79ipgxqn80ns7mpax25zmb77i3ndfw-gawk-5.1.0
/nix/store/9df65igwjmf2wbw0gbrrgair6piqjgmi-glibc-2.31
/nix/store/czc3c1apx55s37qx4vadqhn3fhikchxi-libunistring-0.9.10
/nix/store/fgn3sih5vi7543jcw389a7qqax8nwkhz-glibc-2.31-bin
/nix/store/sb7nbfcc1ca6j0d0v18f7qzwlsyvi8fz-ocaml-4.10.0
/nix/store/xim9l8hym4iga6d4azam4m0k0p1nw2rm-libidn2-2.3.0

Example: Fetch metadata of bash

curl https://cache.nixos.org/$(readlink -f $(which bash) | cut -c12-43).narinfo

Command Line Options

It is also possible to pass substituters and trusted-public-keys on the command line if they are not in configuration.nix or you want to use a particular binary cache server.

$ nix-build --option substituters "http://binarycache.example.com" --option trusted-public-keys "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD" '<nixpkgs>' -A pkgs.PACKAGE
$ nixos-rebuild --option substituters "http://binarycache.example.com" --option trusted-public-keys "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD" switch

To do an offline install (providing your binary cache contains all the packages required);

$ nixos-install --option substituters "http://binarycache.example.com" --option trusted-public-keys "binarycache.example.com-1:dsafdafDFW123fdasfa123124FADSAD"

See also