Secrets Management
Managing secrets with SOPS-Nix.
NixOSInstall
GenerateNixOS
Subset Keysof flake.nix
# flake.nix
{
inputs = {
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = inputs@{
sops-nix,
...
}: {
nixosConfigurations = {
};
};
}
Create module for target machines
AGE (Using SSH Host Keys)
SOPS
nix-shell# -pmodules/nixos/secrets.nix
{ config, lib, pkgs, sops-nix, ... }:
let
isEd25519 = k: k.type == "ed25519";
getKeyPath = k: k.path;
keys = builtins.filter isEd25519 config.services.openssh.hostKeys;
in
{
imports = [
sops-nix.nixosModules.sops
];
environment.systemPackages = with pkgs; [
age
gnupg
pinentry.out
ssh-to-age
--run 'ssh-keyscan servername | ssh-to-age'pgp
#sops
OR];
locallysops nix-shell= -p{
ssh-to-ageage.sshKeyPaths --run= 'catmap /etc/ssh/ssh_host_ed25519_key.pubgetKeyPath |keys;
ssh-to-age'};
}
GPG (Using SSH Host Keys)
ssh user@server "sudo cat /etc/ssh/ssh_host_rsa_key" | nix-shell -p ssh-to-pgp --run "ssh-to-pgp -o server.asc"
# OR locally
nix-shell -p ssh-to-pgp --run "ssh-to-pgp -i /etc/ssh/ssh_host_rsa_key -o $(hostname).asc"
Home-Manager
Install
# flake.nix
{
inputs = {
...
sops-nix = {
url = "github:mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
...
outputs = { ..., sops-nix, ...} :
imports = [
sops-nix.homeManagerModules.sops
];
...
};
Create SOPS module.
# modules/cli/sops.nix
{ pkgs, config, specialArgs, ...}:
let
inherit(specialArgs) username;
in
{
home = {
packages = with pkgs;
[
age
gnupg
pinentry.out
ssh-to-age
ssh-to-pgp
sops
];
};
systemd.user.services.sops-nix.Unit.After = [ "sops-nix.service" ];
sops.defaultSopsFile = ../../secrets/example.yaml;
sops.age.keyFile = "/home/${username}/.config/sops/age/keys.txt";
sops.secrets.example_key = {};
Generate Public Keys for target machines
AGE (Using SSH Host Keys)
ssh-keyscan servername | ssh-to-age
# OR locally
cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
GPG (Using SSH Host Keys)
ssh user@server "sudo cat /etc/ssh/ssh_host_rsa_key" | ssh-to-pgp -o server.asc
# OR locally
ssh-to-pgp -i /etc/ssh/ssh_host_rsa_key -o $(hostname).asc
Generate Private+Public Keypair
If creating this for NixOS, use sudo
Choose one..one, recommend using an existing SSH ed25519 key.
AGE
- Need
pkgs.age
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt
Get Public Key:
age-keygen -y ~/.config/sops/age/keys.txt
AGE (Convert exsiting SSH ed25519 key)
- Need
pkgs.age
mkdir -p ~/.config/sops/age
nix-shell -p ssh-to-age --run "ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt"
age-keygen -y ~/.config/sops/age/keys.txt
GPG Key
- Need some variant of
pkgs.pinentry
gpg --full-generate-key
Get Public Key:
gpg --list-secret-keys
Create SOPS configuration
NixOS
Filling in the user public key, and the groups for a standard set of secrets to be found within the secrets
folder.
# ./src/nixos/.sops.yaml
keys:
- &user_dave age1upzm9um3qljxlmxcg8vl35d7eyeqtnsfcnqlh3wtnj46dhfzwyrqa80avw
- &host_machine age1wq5xj5mwv9xk4tp26cxc4xqjq9xd9hwqv0zeemawl2cc8sarmqesw366dh
creation_rules:
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
key_groups:
- age:
- *user_dave
- *host_machine
Home Manager
Filling in the user public key, and the groups for a standard set of secrets to be found within the secrets
folder.
# ./config/home-manager/.sops.yaml
keys:
- &user_dave age1upzm9um3qljxlmxcg8vl35d7eyeqtnsfcnqlh3wtnj46dhfzwyrqa80avw
- &host_beefhost_machine age1wq5xj5mwv9xk4tp26cxc4xqjq9xd9hwqv0zeemawl2cc8sarmqesw366dh
creation_rules:
- path_regex: secrets/[^/]+\.yaml$(yaml|json|env|ini)$
key_groups:
- age:
- *user_dave
- *host_beefhost_machine
Create new secrets file
nix-shell -p sops --run "sops secrets/github.yaml"yaml
# Inside the file put the key and value:
gh_token: 12345678910
Upon saving this will encrypt the secret. If you execute it again it will decrypt the file to revise.
Configure Home Manager
# sops.example.nix
{ pkgs,
...}:
{
home = {
packages = with pkgs;
[
age
gnupg
pinentry.out
ssh-to-age
ssh-to-pgp
sops
];
};
sops.defaultSopsFile = ../../secrets/example.yaml;
sops.age.keyFile = "/home/$USER/.config/sops/age/keys.txt";
sops.secrets.example_key = {};
sops.secrets.gh_token = {
sopsFile = ../../secrets/github.yaml ;
path = "%r/gh-token" ;
owner = dave.name ;
group = dave.group ;
};
}
Activate
ActivateNixOS
Upon generating new NixOS configuration the secrets will appear in /run/secrets/
[root@hostname:/]# ls -l /run/secrets/*
-r-------- 1 root root 46 Jul 19 09:21 /run/secrets/hostname
-r-------- 1 root root 25 Jul 19 09:21 /run/secrets/common
cat /run/secrets/common
supersecretpassword
Home Manager
Upon performing home-manager switch
the secrets will appear in $XDG_RUNTIME_DIR/
[~/] $ ls -l $XDG_RUNTIME_DIR/secrets/
.r-------- dave users 13 B Fri Jun 23 16:29:52 2023 example_key
.r-------- dave users 40 B Fri Jun 23 16:29:52 2023 gh_token
[~/] $ cat $XDG_RUNTIME_DIR/secrets/gh_token
12345678910
Usage and Tips
Use in configuration
Environment example
programs.bash.initExtra = ''
export GITHUB_TOKEN=$(cat /$XDG_RUNTIME_DIR/secrets/gh_token)
'';
Nix Configuration
{ config, pkgs, lib, ...} :{
services.example = {
...
username = "dave";
password = config.sops.secrets.example_key;
};
};
'';
Reencrypting secrets
If ever adding or removing keys from .sops.yaml
then you will need to reencrypt your secrets.
Use sops updatekeys path/to/secrets.yaml
to re-encrypt the secrets contained in that .yaml file with all the keys that the file should use.