Secrets Recovery

Overview

Post-restore procedure for SSH and GPG keys. After recovering from backup, keys must be decrypted and agents configured.

Post-Restore Checklist

Quick recovery steps
# 1. Decrypt keys
~/.secrets/bin/decrypt-ssh-keys.sh
~/.secrets/bin/decrypt-gpg-keys.sh

# 2. Start SSH agent and load keys
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_* ~/.ssh/id_rsa_*

# 3. Verify
ssh-add -l
ssh -T git@github.com
gpg --list-secret-keys
echo "test" | gpg --sign --armor

SSH Agent Setup

Start Agent

Bash/Zsh
eval "$(ssh-agent -s)"
Fish shell
eval (ssh-agent -c)

Load SSH Keys

Add keys individually
ssh-add ~/.ssh/id_ed25519_github
ssh-add ~/.ssh/id_ed25519_gitlab
ssh-add ~/.ssh/id_ed25519_codeberg
ssh-add ~/.ssh/id_ed25519_bitbucket
ssh-add ~/.ssh/id_rsa_azure
Add all keys at once
ssh-add ~/.ssh/id_ed25519_* ~/.ssh/id_rsa_*
Verify keys loaded
ssh-add -l
ssh -T git@github.com

SSH Troubleshooting

Symptom Cause Fix

Permission denied (publickey)

Keys not in agent

ssh-add ~/.ssh/id_ed25519_*

Could not open connection to agent

Agent not running

eval "$(ssh-agent -s)"

Unsupported use of '='

Fish shell syntax

Use eval (ssh-agent -c)

GPG Recovery

GPG Database Lock Issue

Symptom:

gpg: Note: database_open 134217901 waiting for lock (held by 244009) ...
gpg: keydb_search_first failed: Connection timed out

Cause: Stale lock files from terminated processes or synced .gnupg directories.

Fix: Clear stale locks
gpgconf --kill all
rm -f ~/.gnupg/public-keys.d/.#lk* 2>/dev/null
rm -f ~/.gnupg/public-keys.d/*.lock 2>/dev/null
gpg --list-secret-keys

GPG Lock Files from Synced .gnupg

When .gnupg is synced between machines, lock files from other hosts cause GPG to hang.

Diagnosis
ls -la ~/.gnupg/public-keys.d/
# Shows .#lk* files with OTHER hostnames:
# .#lk0x00007f4254000ce0.modestus-x1.36661
Fix
rm -f ~/.gnupg/public-keys.d/.#lk*
rm -f ~/.gnupg/public-keys.d/pubring.db.lock
gpg --list-secret-keys
Prevention (before syncing to new machine)
gpgconf --kill all
rm -f ~/.gnupg/public-keys.d/.#lk*
rm -f ~/.gnupg/public-keys.d/*.lock

Pinentry Configuration

Arch Linux

Arch requires gcr package for pinentry-gnome3:

Symptom
gpg: signing failed: No pinentry
Fix
sudo pacman -S gcr
pkill -9 gpg-agent
rm -f /run/user/$(id -u)/gnupg/S.gpg-agent*
echo "test" | gpg --sign --armor

WSL / Headless Systems

WSL has no GUI. Use terminal pinentry:

Install terminal pinentry (Fedora)
sudo dnf install pinentry-tty -y
Install terminal pinentry (Arch)
sudo pacman -S pinentry
Configure for terminal
echo "pinentry-program /usr/bin/pinentry-tty" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent
export GPG_TTY=$(tty)

Add to .zshrc / .bashrc:

export GPG_TTY=$(tty)

Verification Commands

SSH verification
ssh-add -l
ssh -T git@github.com
GPG verification
gpg --list-secret-keys
echo "test" | gpg --sign --armor
Check for GPG locks
ls -la ~/.gnupg/public-keys.d/*.lock 2>/dev/null
Check for orphaned GPG processes
ps aux | grep -E "gpg|keybox" | grep -v grep

Credential Locations

Credential Storage Access

SSH keys

~/.ssh/ (encrypted in .secrets)

~/.secrets/bin/decrypt-ssh-keys.sh

GPG keys

~/.gnupg/ (encrypted in .secrets)

~/.secrets/bin/decrypt-gpg-keys.sh

age key

~/.config/age/key.txt

Direct file access

LUKS passphrases

gopass

gopass show ARCANA/storage/seagate-primary

Borg passphrase

gopass/dsec

dsec source d000 dev/storage

Service credentials

dsec

dsource d000 dev/network