/posts/computing/server/nix/password-store

Secrets storage on NixOS with password store

Deprecation warning. See the section on nix-sops for better secrets handling. The reason for deprecation:

  • nix-plugins uses C and not Nix, this can cause nixos-rebuild to break from incompatibility between versions (see this issue).
  • This way of doing things is hard to bootstrap. You cannot launch a new system with the following config from a blank slate, since builtins.extraBuiltins is not available until nix-plugins is installed, so you can only use after at least one rebuild.
  • The secrets handled this will still be available in the nix store as plaintext. This is not a fault of nix-plugins but is due to my implementation laziness.

In this section we will implement a simple function that would retrieve secrets from password-store. It might be useful to go over the section on web services (especially the one on git) after this so that you can sync your password-store to your server.

This section is actually a copy of this blog post. I will cut out the explanations as usual and make it cookbook style. It is actually fairly easy to implement.

First you need to enable the nix-plugins plugin. Note that you should ensure everything here is absolutely correct before rebuilding. An error in your nix.conf can make rebuilds or rollbacks impossible and may require rebooting into an older configuration if goes sideways. For example: do not rebuild after this stage, because we have not defined extra-builtins.nix yet.

/etc/nixos/configuration.nix
nix.extraOptions = '' plugin-files = ${pkgs.nix-plugins}/lib/nix/plugins extra-builtins-file = ${toString ./misc/extra-builtins.nix} '';

Now we define extra-builtins.nix. It will contain all of our extra functions that have exec capability.

/etc/nixos/misc/extra-builtins.nix
{ exec, ... }:
{
getSecret = name: exec [ ./nix-pass.sh name ];
}

Simple enough. So this gives us access to a function builtins.extraBuiltins.getSecret that will return whatever nix-pass.sh evaluates to. Now we define that script.

/etc/nixos/misc/nix-pass.sh
#! /bin/sh
f=$(mktemp)
trap "rm $f" EXIT
su -c "pass show $1" <USER> > $f
nix-instantiate --eval --expr "builtins.readFile $f"

This script will log in to <USER>, which should be the user that has access to the correct password-store. Then it retrieves the password that was supplied as argument and returns it. Obviously before all this works, you should have set up password-store and GPG.