Secrets Management
Current state: Secrets are managed via .env files (gitignored), backed up with backup-env.sh, master copies in KeePassXC. SOPS/age described below is planned for future use.
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)
| 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
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
.env files
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
References