Passing secrets to NixOps logical network specification

650 Views Asked by At

I am deploying a web application to AWS with NixOps. The application requires some environment variables to be set. I can achieve this with something similar to the following:

{
  network.description = "Web server";

  webserver = { config, pkgs, ... }: {
    environment.systemPackages = [ webserver ];
    networking.firewall.allowedTCPPorts = [ 80 ];

    systemd.services.webserver = {
      description = "Example webapp";

      environment = {
        SECRET_KEY = "SECRET_VALUE";
      }
    };
  };
}

I want this file to be checked into my source control system, but I do not want the SECRET_VALUE to be stored in the clear if I can help it.

Is there a way to read these values in from a GPG encrypted file when they're needed for a deploy? Or is there some other method? Or do I need to encrypt the whole file?

1

There are 1 best solutions below

0
On BEST ANSWER

Ideally you'd use NixOps keys, since their purpose is to provide sensitive data to your app while storing such content outside of the Nix store.

Files in /nix/store/ are readable by every user on that host, so storing secret keys embedded in nix derivations is insecure. To address this, nixops provides the configuration option deployment.keys, which nixops manages separately from the main configuration derivation for each machine. - https://nixos.org/nixops/manual/#idm140737318276736

To be more specific, in your case Nix will create a systemd unit file for your webserver service and that file, which is stored in /nix/store, will have your SECRET_KEY in it.

But if using environment variables is a must, you can use builtins.readFile to read the environment variable's value from an external file. The file will need to be present when you build/deploy, so you'd secure the data either by NOT storing it in the Git repo, or using transparent encryption (ex. git-crypt) as Robert suggested.

{
  network.description = "Web server";

  webserver = { config, pkgs, ... }: {
    environment.systemPackages = [ webserver ];
    networking.firewall.allowedTCPPorts = [ 80 ];

    systemd.services.webserver = {
      description = "Example webapp";

      environment = {
        SECRET_KEY = builtins.readFile ./secret.data;
      }
    };
  };
}