Hi! Here are some notes about how to use secrets in NixOS configuration securely. As of now I use sops-nix with simple age keys (not generated from ssh keys).
Concept
We will generate a file with all our secrets (e.g. secrets.yaml
). For example:
my_secret_auth: <plain-text secret>
secrets.yaml
is stored encrypted. We can edit it with sops secrets.yaml
which decrypts it and opens your editor from the $EDITOR
environment variable.
For this encryption / decryption sops uses an age
public and private keys - we generate those too.
For those secrets to be picked up by nixos we register them in nixos config (we can set secret's owner to allow access for needed service):
sops.secrets = {
my_secret_auth = {
owner = "nginx";
};
};
In the nixos configuration we now can use those secrets like so (an example for nginx basic auth):
basicAuthFile = config.sops.secrets.my_secret_auth.path;
That's basically it. Below are some details on how to setup all of this.
Local secrets with nixos-rebuild
For use on a local machine. We will use niv to install sops-nix
.
1) Go to your configuration directory, init a niv
project with sops-nix
:
# where `configuration.nix` is located, adjust if needed
cd /etc/nixos
# init `niv` with `sops-nix` before installing anything
nix-shell -p niv --run "niv init && niv add Mic92/sops-nix"
2) Create the directory for age keys:
mkdir -p ~/.config/sops/age
3) Configure sops
and other stuff in secrets.nix
(you can choose another name, don't forget to import this file from your configuration), replace YOUR_USER
:
{ pkgs, config, ... }:
{
imports = [ "${(import ./nix/sources.nix).sops-nix}/modules/sops" ];
environment.systemPackages = with pkgs; [
age sops
];
sops = {
defaultSopsFile = ./secrets/secrets.yaml;
defaultSopsFormat = "yaml";
age.keyFile = "/home/${config.users.users.YOUR_USER.name}/.config/sops/age/keys.txt";
};
}
4) Apply configuration above:
sudo nixos-rebuild switch
5) Generate an age key:
age-keygen -o ~/.config/sops/age/keys.txt
6) Create .sops.yaml
and paste public key printed on the previous step (replace capslocked text), use arbitrarily username:
keys:
- &USERNAME PUBLIC_KEY
creation_rules:
- path_regex: secrets/secrets.yaml$
key_groups:
- age:
- *USERNAME
7) Register secrets to secrets.nix
from step 3:
...
sops = {
# ...
secrets = {
my_secret_auth = {
owner = "nginx";
};
};
}
8) Use your secrets in nixos configuration (where the option expects a file path to the secret):
# ...
basicAuthFile = config.sops.secrets.my_secret_auth.path;
# ...
Remote secrets with flake
For use on a remote machine.
DISCLAIMER: I keep remote's configs locally and send them via scp
when updating it.
1) Add this to your flake:
{
inputs = {
# ...
sops-nix.url = "github:Mic92/sops-nix"; # <--
};
outputs = {
# ...
sops-nix, # <--
...
}@inputs: # <--
{
nixosConfigurations.your_flake_name = nixpkgs.lib.nixosSystem {
# ...
specialArgs = { inherit inputs; }; # <--
modules = [
# ...
sops-nix.nixosModules.sops # <--
];
};
};
}
2) Create the directory for age keys:
mkdir -p ~/.config/sops/age
3) Configure sops
and other stuff in secrets.nix
(you can choose another name, don't forget to import this file from your configuration), replace YOUR_USER
:
{ pkgs, config, inputs, ... }:
{
imports = [ inputs.sops-nix.nixosModules.sops ]; # <-- differs from the local setup
environment.systemPackages = with pkgs; [
age sops
];
sops = {
defaultSopsFile = ./secrets/secrets.yaml;
defaultSopsFormat = "yaml";
age.keyFile = "/home/${config.users.users.YOUR_USER.name}/.config/sops/age/keys.txt";
};
}
4) Apply configuration above:
# I'm copying the configuration via ssh and running update on a remote - you do you
nixos-rebuild switch --flake .#update
5) Generate an age key:
age-keygen -o ~/.config/sops/age/keys.txt
6) Create .sops.yaml
and paste public key printed on the previous step (replace capslocked text), use arbitrarily username:
keys:
- &USERNAME PUBLIC_KEY
creation_rules:
- path_regex: secrets/secrets.yaml$
key_groups:
- age:
- *USERNAME
7) Register secrets to secrets.nix
from step 3:
...
sops = {
...
secrets = {
my_secret_auth = {
owner = "nginx";
};
};
...
8) Use your secrets in nixos configuration (where the option expects a file path to the secret):
...
basicAuthFile = config.sops.secrets.my_secret_auth.path;
...
9) If you use sops on both local and remote, it's useful to copy age private key from the remote machine to your home keys.txt
(so you'll have two keys there) - this way you can edit remote's secrets.yaml
locally.
Resources
- sops-nix repo
- short tutorial from vimjoyer
- commands from tutorial above
- nice article from dade about this topic and some more
Top comments (0)