Binary Cache: Difference between revisions

From NixOS Wiki
imported>Tfc
Incorporate musicmatze
imported>Mth
No edit summary
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.
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.


== Setting up a NixOS Machine as Binary Cache for Others ==
== Setting up a binary cache ==


This tutorial assumes:
This tutorial explains how to setup a server running NixOS as a binary cache for other machines, serving the 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>


* NixOS on the serving machine
=== 1. Generating a private/public keypair ===
* 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:
A keypair is necessary to sign Nix packages.


# Generate a private/public keypair for signing packages
{{bc|
#* This step is not mandatory, but we are going to serve signed nix packages
$ nix-store --generate-binary-cache-key binarycache.example.com cache-priv-key.pem cache-pub-key.pem
# Activate <code>nix-serve</code>
# mv cache-priv-key.pem /var/cache-priv-key.pem
#* This is the service that speaks the binary cache protocol via HTTP.  
# chown nix-store /var/cache-priv-key.pem
#* It will use the private key to sign the packages
# chmod 600 /var/cache-priv-key.pem
# 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 ===
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.


<syntaxhighlight lang="bash">
=== 2. Activating {{ic|nix-serve}} ===
$ nix-store --generate-binary-cache-key binarycache.mydomain.com1 cache-priv-key.pem cache-pub-key.pem
$ sudo mv cache-priv-key.pem /var/cache-priv-key.pem
$ sudo chown nix-store /var/cache-priv-key.pem
$ sudo chmod 600 /var/cache-priv-key.pem
</syntaxhighlight>


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


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
Line 43: Line 30:
</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.
{{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. Create a virtual hostname in <code>nginx</code> ===
=== 3. Creating a virtual hostname in {{ic|nginx}} ===
 
We redirect the HTTP(s) traffic from port 80 to {{ic|nix-serve}}.


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
Line 52: Line 41:
   virtualHosts = {
   virtualHosts = {
     # ... existing hosts config etc. ...
     # ... existing hosts config etc. ...
     "binarycache.mydomain.com" = {
     "binarycache.example.com" = {
       serverAliases = [ "binarycache" ];
       serverAliases = [ "binarycache" ];
       locations."/".extraConfig = ''
       locations."/".extraConfig = ''
Line 65: Line 54:
</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 ===
=== 4. Rebuilding and testing ===


<syntaxhighlight lang="bash">
{{bc|# nixos-rebuild switch}}
sudo nixos-rebuild switch
</syntaxhighlight>


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 74:
</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!):
Next, with the public key that was generated to {{ic|cache-pub-key.pem}}, setup another 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 options {{ic|substituters}} and {{ic|extra-substituters}}) and the public key to the trusted keys (see {{ic|trusted-public-keys}}).
 
<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.
== See also ==
For that, have a look into the Nix manual [https://nixos.org/nix/manual/#name-11] and the following settings:


* substituters
<references group="cf."/>
* extra-substituters
* trusted-public-keys

Revision as of 17:43, 14 April 2019

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.

Setting up a binary cache

This tutorial explains how to setup a server running NixOS as a binary cache for other machines, serving the 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.

$ nix-store --generate-binary-cache-key binarycache.example.com cache-priv-key.pem cache-pub-key.pem
# mv cache-priv-key.pem /var/cache-priv-key.pem
# chown nix-store /var/cache-priv-key.pem
# chmod 600 /var/cache-priv-key.pem

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.

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

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.

services.nginx = {
  enable = true;
  virtualHosts = {
    # ... existing hosts config etc. ...
    "binarycache.example.com" = {
      serverAliases = [ "binarycache" ];
      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;
      '';
    };
  };
};

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

4. Rebuilding and testing

# 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

Next, with the public key that was generated to cache-pub-key.pem, setup another 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 options substituters and extra-substituters) and the public key to the trusted keys (see trusted-public-keys).

$ 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

See also