Secrets Management¶
How to handle sensitive data across the homelab without compromising security.
Principles¶
- Never commit plaintext secrets to git
- Encrypt secrets at rest (age + SOPS)
- Minimal secret exposure (only where needed)
- Reproducible deployments (secrets in git, encrypted)
Tools¶
| Tool | Purpose |
|---|---|
| age | Modern encryption (replaces GPG) | | SOPS | Encrypt YAML/JSON files, works with age | | .env files | Runtime secrets (gitignored) | | Restic | Encrypted backups |
Workflow¶
1. Generate age Key¶
# Generate key
age-keygen -o ~/.config/sops/age/keys.txt
# View public key
age-keygen -y ~/.config/sops/age/keys.txt
2. Configure SOPS¶
Create .sops.yaml in repo root:
creation_rules:
- path_regex: \.enc\.yaml$
age: >-
age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3. Encrypt Secrets¶
# Create secrets file
cat > docker/fixed/nas/git/.env.enc.yaml << EOF
forgejo_secret_key: "your-secret-key-here"
EOF
# Encrypt it
sops -e -i docker/fixed/nas/git/.env.enc.yaml
# Decrypt to .env at deploy time
sops -d docker/fixed/nas/git/.env.enc.yaml > docker/fixed/nas/git/.env
4. Gitignore Pattern¶
# Plaintext secrets (never commit)
.env
*.secret
# Encrypted secrets (safe to commit)
!*.enc.yaml
!*.enc.json
Secret Types by Location¶
Mobile (RPi 5)¶
| Secret | Storage | Method |
|---|---|---|
| Headscale API key | .env | SOPS encrypted in git |
| Pi-hole web password | .env | SOPS encrypted in git |
| age private key | ~/.config/sops/age/ | Manual backup only |
Fixed Homelab¶
| Secret | Storage | Method |
|---|---|---|
| Vaultwarden admin token | .env | SOPS encrypted in git |
| Jellyfin API key | .env | SOPS encrypted in git |
| OPNsense root password | OPNsense config | Export encrypted backup |
| Start9 master password | Start9 | Manual, not in git |
| Proxmox root password | Proxmox | Manual, not in git |
VPS¶
| Secret | Storage | Method |
|---|---|---|
| Uptime Kuma password | .env | SOPS encrypted in git |
| ntfy admin password | .env | SOPS encrypted in git |
| Restic repository password | .env | SOPS encrypted in git |
Backup of Encryption Keys¶
| Key | Backup Location | Method |
|---|---|---|
| age private key | Paper + secure storage | Print QR code | | Restic repo passwords | Vaultwarden | Encrypted password manager | | Start9 seed phrase | Paper | Offline only |
Recovery Procedure¶
- Restore age key from paper backup
- Clone repo from git (Forgejo or backup)
- Decrypt secrets with
sops -d - Deploy services with decrypted
.envfiles
Commands Cheatsheet¶
# Encrypt file in place
sops -e -i secrets.yaml
# Decrypt file in place
sops -d -i secrets.yaml
# Decrypt to stdout
sops -d secrets.yaml
# Edit encrypted file (decrypts, opens editor, re-encrypts)
sops secrets.yaml
# Encrypt specific keys only
sops --encrypt --encrypted-regex '^(password|api_key)$' config.yaml