Secure secret management using SOPS with Yubikey PIV hardware keys and offline master key backup.
- π Physical Touch Required - Every decryption requires touching your Yubikey (prevents silent malware attacks)
- π Hardware-Backed Keys - Private keys never leave the Yubikey secure element
- πΎ Offline Master Key - Emergency backup stored safely offline
- π₯ Team-Friendly - Easy onboarding with individual Yubikeys per team member
- π Modern Crypto - X25519 elliptic curve cryptography via age-plugin-yubikey
macOS (Homebrew):
brew install sops age age-plugin-yubikey yubico-piv-toolLinux (Debian/Ubuntu):
# Install SOPS
wget https://github.com/mozilla/sops/releases/download/v3.8.1/sops_3.8.1_amd64.deb
sudo dpkg -i sops_3.8.1_amd64.deb
# Install age
sudo apt install age
# Install Yubikey tools
sudo apt install yubikey-manager yubico-piv-tool
# Install age-plugin-yubikey (requires Rust)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install age-plugin-yubikeyWindows (WSL2 + Ubuntu):
# Enable WSL2 and install Ubuntu from Microsoft Store first
# Then follow Linux instructions aboveWindows (Native - PowerShell):
# Install via Chocolatey
choco install sops age
# Download and install Yubikey tools from:
# https://www.yubico.com/support/download/yubikey-manager/
# Install age-plugin-yubikey (requires Rust)
# Install Rust from: https://rustup.rs/
cargo install age-plugin-yubikey# 1. Generate master key (backup offline!)
age-keygen -o master-key.txt
# 2. Change Yubikey PINs (default: 123456 / 12345678)
yubico-piv-tool -a change-pin
yubico-piv-tool -a change-puk
# 3. Generate Yubikey PIV key with touch policy
age-plugin-yubikey --generate \
--slot 1 \
--touch-policy always \
--pin-policy always \
--name "your-name"
# 4. Create identity file for SOPS
age-plugin-yubikey --identity > ~/.sops-age-keys.txt
# Add to shell profile (choose your shell):
# For zsh (macOS default):
echo 'export SOPS_AGE_KEY_FILE=~/.sops-age-keys.txt' >> ~/.zshrc && source ~/.zshrc
# For bash (Linux default):
echo 'export SOPS_AGE_KEY_FILE=~/.sops-age-keys.txt' >> ~/.bashrc && source ~/.bashrc
# For Windows PowerShell (add to $PROFILE):
# [System.Environment]::SetEnvironmentVariable('SOPS_AGE_KEY_FILE', "$env:USERPROFILE\.sops-age-keys.txt", 'User')
# 5. Configure SOPS (see .sops.yaml example in repo)
# 6. Test it!
echo "secret: password123" > test.yaml
sops -e test.yaml > test.enc.yaml
sops -d test.enc.yaml # Touch Yubikey when LED blinks β¨# Edit secrets (touch Yubikey twice: open + save)
sops secrets.enc.yaml
# Decrypt to view
sops -d secrets.enc.yaml
# Encrypt new file
sops -e secrets.yaml > secrets.enc.yaml- SETUP.md - Complete setup guide with all steps
- USAGE.md - Daily workflows and team management
- ONBOARDING.md - Guide for new team members
- TROUBLESHOOTING.md - Common issues and solutions
- PRE-COMMIT-CHECKLIST.md - Verify before committing
Traditional secret management often relies on keys stored on disk. With Yubikey PIV:
| Security Feature | Traditional | Yubikey PIV |
|---|---|---|
| Physical touch required | β | β |
| Malware can silently decrypt | β | β |
| User awareness of access | β | β (LED blinks) |
| Private key extractable | β | β |
| Hardware-backed crypto | β | β |
Example: If malware tries to decrypt secrets, your Yubikey LED blinks - you'll notice and can prevent the attack by not touching.
βββββββββββββββββββββββββββββββββββββββ
β Encrypted Secret File β
ββββββββββββββββ¬βββββββββββββββββββββββ
β
ββββ Decryption ββββ
β β
ββββββββββββΌβββββββββ ββββββΌββββββββββββββ
β Master Age Key β β Yubikey PIV β
β (offline/safe) β β + Touch + PIN β
ββββββββββββββββββββββ ββββββββββββββββββββ
- Team member generates Yubikey PIV key
- Shares public recipient (
age1yubikey1...) - Team lead adds to
.sops.yaml - Re-encrypt all secrets:
sops updatekeys secrets.enc.yaml - Team member can now decrypt (with Yubikey touch)
- Remove their recipient from
.sops.yaml - Re-encrypt all secrets (revokes their access)
- Commit changes
CI/CD can't provide physical touch, so use the master key:
# GitHub Actions example
- name: Decrypt secrets
env:
SOPS_AGE_KEY: ${{ secrets.SOPS_MASTER_KEY }}
run: sops -d secrets.enc.yaml > secrets.yamlβ DO:
- Store master key offline (safe, password manager)
- Use
--touch-policy alwaysfor all Yubikeys - Change default PINs immediately
- Re-encrypt when removing team members
- Commit encrypted files to git
β DON'T:
- Never commit master-key.txt
- Never commit unencrypted secrets
- Never disable touch policy
- Never share Yubikey or PIN
- Never ignore LED blink (signals secret access)
creation_rules:
- path_regex: .*\.(yaml|json|env|ini|txt)$
key_groups:
- age:
# Master key (offline backup, CI/CD)
- age1u3hs6xmw09l50sjwzhngd098e23ysruhn5mus8lv2drr6evs9s8sn5ygnq
# Team Yubikeys (daily use with touch)
- age1yubikey1qd... # Team member 1
- age1yubikey1qw... # Team member 2Hardware:
- Yubikey 5 or newer (with PIV support)
Operating Systems:
- macOS 10.15+ (Catalina or newer)
- Linux (Ubuntu 20.04+, Debian 11+, Fedora, Arch, etc.)
- Windows 10/11 (via WSL2 with Ubuntu, or native)
Software:
- SOPS 3.8+
- age 1.1+
- age-plugin-yubikey 0.5+
- yubico-piv-tool / yubikey-manager
"No identities found"
# Create identity file
age-plugin-yubikey --identity > ~/.sops-age-keys.txt
export SOPS_AGE_KEY_FILE=~/.sops-age-keys.txt"Touch timeout"
- Touch Yubikey more quickly when LED blinks (15 second timeout)
"Algorithm error"
# Try without pin-policy flag
age-plugin-yubikey --generate --slot 1 --touch-policy always --name "yourname"See TROUBLESHOOTING.md for more solutions.
Contributions welcome! Feel free to:
- Report issues
- Suggest documentation improvements
- Share your team's workflow adaptations
- SOPS - Secrets OPerationS
- age - Simple, modern file encryption
- age-plugin-yubikey - Age plugin for Yubikey PIV
- Yubikey PIV - Yubikey PIV documentation
This documentation is provided as-is for educational and practical use. Adapt it to your team's needs.
- π Read the complete setup guide
- π Open an issue for bugs or questions
- π‘ Check TROUBLESHOOTING.md for common issues
Security Note: This setup provides strong security through hardware-backed keys and physical touch requirements. However, no system is perfect - always follow your organization's security policies and best practices.