omnixient/modules/dev-env/docs/secrets-management.md
Padreug 346042f1c5 docs(dev-env): aiolabs stack overview and lnbits workflow notes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 09:59:05 +02:00

3.1 KiB

Secrets Management

Layered approach to secrets in dev-env. None of this is enforced by the module — these are conventions that pair well with the dev-env layout.

Context Tool Storage
Local dev pass ~/.password-store (GPG encrypted)
NixOS servers sops-nix + age Encrypted in git
Repo secrets git-crypt or .sops.yaml Encrypted files in repo

The shared pre-commit hook (installed by dev-env.gitHooks.enable) refuses to commit common secret patterns and unencrypted sops files. See dev-env/scripts/git-hooks/pre-commit for the patterns.

Local dev with pass

# pass is in dev-env's package set; gpg is in omni's defaults
gpg --gen-key                   # if you don't have one
pass init "your-email@example.com"

pass insert dev/lnbits/admin-key
pass insert dev/postgres/password
pass insert dev/bitcoin/rpc-password

pass dev/lnbits/admin-key                # print
pass -c dev/lnbits/admin-key             # to clipboard (clears after 45s)
export LNBITS_ADMIN_KEY=$(pass dev/lnbits/admin-key)  # in scripts

Server secrets with sops-nix

Initial setup

age-keygen -o ~/.config/sops/age/keys.txt    # generate your key
age-keygen -y ~/.config/sops/age/keys.txt    # show your public key
# age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Per-project

In each deploy host directory:

cd ~/dev/deploy/unified/hosts/host5

cat > .sops.yaml << EOF
keys:
  - &admin age1xxx...                                  # you
  - &host5  age1yyy...                                  # the server's key

creation_rules:
  - path_regex: secrets/host5\.yaml$
    key_groups:
      - age:
        - *admin
        - *host5
EOF

mkdir -p secrets
nvim secrets/host5.yaml          # write the unencrypted file
sops -e -i secrets/host5.yaml    # encrypt in place

The pre-commit hook will refuse to commit secrets/host5.yaml if it's not encrypted. (False positive? git commit --no-verify.)

Using in NixOS

{ config, pkgs, ... }:

{
  imports = [ inputs.sops-nix.nixosModules.sops ];

  sops.defaultSopsFile = ./secrets/host5.yaml;
  sops.age.keyFile = "/var/lib/sops-nix/key.txt";

  sops.secrets."lnbits/admin_key" = {};
  sops.secrets."postgres/password" = {};

  services.lnbits = {
    adminKeyFile = config.sops.secrets."lnbits/admin_key".path;
  };
}

Bootstrapping a server's age key

On each NixOS host (one-time):

sudo mkdir -p /var/lib/sops-nix
sudo age-keygen -o /var/lib/sops-nix/key.txt
sudo chmod 600 /var/lib/sops-nix/key.txt
sudo age-keygen -y /var/lib/sops-nix/key.txt    # add to .sops.yaml

Best practices

  1. Never commit unencrypted secrets. The pre-commit hook helps but isn't a substitute for paying attention.
  2. Rotate after team changes — especially when removing keys.
  3. Different secrets per environment. staging ≠ production.
  4. Backup your master keys. GPG and age private keys are the only thing standing between you and a total loss.
  5. No secrets in .devenv.conf / /etc/dev-env/config.sh. Those files are world-readable.