docs(dev-env): aiolabs stack overview and lnbits workflow notes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
dbd9e76027
commit
346042f1c5
8 changed files with 1276 additions and 0 deletions
110
modules/dev-env/docs/secrets-management.md
Normal file
110
modules/dev-env/docs/secrets-management.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# 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`
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```nix
|
||||
{ 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):
|
||||
|
||||
```bash
|
||||
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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue