Feb 11, 2017

How to use nix-copy-closure, step by step

Is been a while since I post anything in my blog, but yesterday in the middle of the night I was re-reading the Nix manual and remembered that I never really was able to properly use the nix-copy-closure command, because of some package signature problems, it felt like if some instructions were missing on how to really use nix-copy-closure, needless to say... after some battling with the situation I was victorious!, and as a consideration for the future people of the Internet... I present you with a step-by-step simplified instructions on how to use the nix-copy-closure command.

The remote nix installation

Make sure the target machine has the nix-env tools available. This means make sure you are sourcing the nix.sh bootstrap for single user or the equivalent for a multiuser setup. You can validate that by executing the command:

ssh '<dest>' nix-env --version

The command should end without error, printing the nix version on the remote machine.

Configure your keys

This step was the most problematic for me, because is a blocker in the regular use for nix-copy-closure.

To transfer your packages and verify the authenticity of the origin that is exporting the packages, you have to create a set of public and private keys, the how to create those is documented in a not verify popular document with the steps.

To generate the keys you would need openssl.

  1. Generate the keys:

    Private key

    (umask 277 && openssl genrsa -out /etc/nix/signing-key.sec 2048)
    

    The -out argument can be set to any location and later put the key in that particular directory (actually it depends if you are modifying the default value of sysconfdir), if is not obvious, the parenthesis indicate that the command is executed in a subshell with a default umask of 277 basically it would create the key with a read-only permission to the user that executes the command and nothing else.

    Public key

    With the private key already created from step one, you proceed to create the public key:

    openssl rsa -in /etc/nix/signing-key.sec -pubout > /etc/nix/signing-key.pub
    
  2. Place the keys in the right locations

    In the origin machine (your workstation) place the private key signing-key.sec in /etc/nix (or sysconfdir), the name and location of the file is important.

    # if is not already there...
    sudo mv signin-key.sec /etc/nix
    

    At the deployment/target machine, copy over the public key signing-key.pub into /etc/nix (or sysconfdir), generated in the previous step, again, the name and location of the file is important.

    scp signing-key.pub '<dest>'
    ssh '<dest>'
    sudo mv signing-key.pub /etc/nix
    

And finally, copy the closure

With the the proper nix configuration on the target machine and the keys in place we are in the condition to finally use the nix-copy-closure as it should:

# install hello on your work station to demonstrate the point
nix-env -iA nixpkgs.hello

# convenient command to get the store path of the package
store_path=$(nix-env -q --no-name --out-path hello)

# copy the closure required for the package based on that store path
nix-copy-closure --sign --include-outputs  <target> $store_path

# install the package on the remote side, the previous step
# only copy over the path into the remote nix store, but now we
# need to include those paths in the user environment,
# nix-env is used for that purpose
ssh '<dest>' "nix-env -i $store_path"

And that's it! You can verify the current packages in the remote side with:

ssh '<dest>' nix-env -q

You would see that the hello package is installed and available for the user on the remote host.

Final notes

It might be redundant to state this, but the idea of copying a closure of a certain package from your machine into an external to do a deployment is probably not the absolute best, but I think that is a simple alternative if you don't want to setup a proper hydra and channels.

And for those who read this post without having a clue about nix, go over their site and take a look, as an implicit prerequisite to really get something out of nix-copy-closure is the fact that you know the nix language and are sort-of familiar with the nixpkgs collection.

For more information, make sure you read the man page for the nix-copy-closure command and the section on the manual.

Tags: nix deployments nixos packaging