Add agenix secrets management

Phase 3: Encrypted secrets

- Add secrets module with agenix integration
- Create secrets/secrets.nix template for key definitions
- Installer generates SSH key if missing
- Installer creates personalized secrets.nix with user's key
- Full documentation in docs/SECRETS.md

Features:
- Secrets encrypted with age using SSH keys
- Decrypted automatically at system activation
- Safe to commit .age files to git
- Support for WiFi passwords, API keys, service credentials

Usage:
  agenix -e secrets/my-secret.age
  age.secrets.my-secret.file = ./secrets/my-secret.age;

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 02:56:25 -05:00
parent 6686a9f6b6
commit 5a52b3c159
6 changed files with 297 additions and 0 deletions

149
docs/SECRETS.md Normal file
View File

@@ -0,0 +1,149 @@
# Secrets Management with agenix
Nomarchy uses [agenix](https://github.com/ryantm/agenix) for managing encrypted secrets. Secrets are encrypted with age using SSH public keys and decrypted at system activation.
## How It Works
1. **Secrets are encrypted** with your SSH public key(s)
2. **Stored in git** as `.age` files (safe to commit)
3. **Decrypted at boot** using the host's SSH private key
4. **Available at runtime** in `/run/agenix/`
## Quick Start
### 1. Get Your SSH Public Key
```bash
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host
```
### 2. Get the Host's SSH Public Key
After first boot:
```bash
ssh-keyscan localhost 2>/dev/null | grep ed25519
```
Or from your hardware-configuration.nix's host:
```bash
ssh-keyscan <hostname> 2>/dev/null | grep ed25519
```
### 3. Edit secrets/secrets.nix
```nix
let
user = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...";
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...";
allKeys = [ user host ];
in {
"wifi-home.age".publicKeys = allKeys;
"github-token.age".publicKeys = allKeys;
}
```
### 4. Create a Secret
```bash
cd ~/.config/nomarchy
agenix -e secrets/wifi-home.age
```
This opens your editor. Enter the secret content, save, and exit.
### 5. Use the Secret in Your Config
```nix
# In your custom module
{ config, ... }: {
age.secrets.wifi-home = {
file = ./secrets/wifi-home.age;
owner = "root";
mode = "0400";
};
# Use the decrypted secret
networking.wireless.networks."MyNetwork".pskRaw =
"file:${config.age.secrets.wifi-home.path}";
}
```
## Common Use Cases
### WiFi Passwords
```nix
age.secrets.wifi-password.file = ./secrets/wifi.age;
# For NetworkManager (wpa_supplicant)
networking.wireless.networks."NetworkName".psk =
builtins.readFile config.age.secrets.wifi-password.path;
```
### API Keys
```nix
age.secrets.github-token = {
file = ./secrets/github-token.age;
owner = "youruser";
mode = "0400";
};
# In your shell config
home.sessionVariables.GITHUB_TOKEN =
"$(cat ${config.age.secrets.github-token.path})";
```
### Service Credentials
```nix
age.secrets.syncthing-key = {
file = ./secrets/syncthing-key.age;
owner = "youruser";
};
services.syncthing.key = config.age.secrets.syncthing-key.path;
```
## Re-keying Secrets
If you change hosts or keys, re-encrypt all secrets:
```bash
cd ~/.config/nomarchy
agenix --rekey
```
## Security Notes
- **Never commit unencrypted secrets**
- Keep your SSH private key secure
- The host's SSH key is generated during install
- Secrets are decrypted to a tmpfs (`/run/agenix/`)
- Consider using separate keys for different security levels
## Troubleshooting
### "No identity found"
Ensure `/etc/ssh/ssh_host_ed25519_key` exists and is readable by root.
### "Failed to decrypt"
Check that the host's public key is in `secrets.nix` and re-encrypt:
```bash
agenix --rekey
```
### "Secret file not found"
Make sure the `.age` file exists and the path in your config is correct.
## File Structure
```
~/.config/nomarchy/
├── secrets/
│ ├── secrets.nix # Key definitions
│ ├── wifi.age # Encrypted WiFi password
│ └── github.age # Encrypted API key
└── flake.nix
```