Clicks SOPS

To create a secret you can do the following:

clicks.secrets."${lib.clicks.secrets.name ./headscale.sops.json}" = {
  file = ./headscale.sops.json;
  group = "headscale";
  keys = [
    "oidc_client_secret"
    "database_password"
    "noise_private_key"
    "private_key"
  ];
  neededForUsers = false;
};

The secret name is based on the secret file's hash. file is a path to the secrets file. It is required. group is the group the key should be owned by. We chose to use groups instead of users so that you can allow multiple different users to read the file. If you don't set it, we'll use "root. keys is a list of the keys of the secret file, assuming it's not a binary file. If it isn't a binary file, you are required to set this. If it is a binary file, you shouldn't specify this. neededForUsers requires the secret to be present before users are created on boot, it's identical to the sops option of the same name. Use it for user passwords. If you don't specify it, we'll use false.


You can then refer to the different keys directly from the secret, no need to manually create individual files:

client_secret_path = config.clicks.secrets."${lib.clicks.secrets.name ./headscale.sops.json}".paths.oidc_client_secret;

If the secret file is a binary file, the path can be accessed via

private_key = config.clicks.secrets."${lib.clicks.secrets.name ./privatekey.bin}".path;

We recommend using lib.clicks.secrets.name with your path to name your secrets. This avoids you creating naming conflicts or having messy names. This is not a hard requirement for using the module outside of Clicks, but if you're contributing to Clicks infrastructure we will enforce this at review.

This takes a path, and is guarenteed to be stable when passed the same file at the same path.

lib.clicks.secrets.name ./file.sops.json

In Clicks, secrets are only ever encrypted to a single host. You'll need to make the secrets within the systems/<arch>/<hostname> directory to let sops know what host to encrypt to.