Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ammarshah/434f9e5c139851d30d5c634108b6faa7 to your computer and use it in GitHub Desktop.

Select an option

Save ammarshah/434f9e5c139851d30d5c634108b6faa7 to your computer and use it in GitHub Desktop.
Encrypted SSH and GPG Keys Backup & Restore

Encrypted SSH and GPG Keys Backup & Restore

A pair of bash scripts to securely backup and restore your SSH keys, GPG keys, and Git configuration with symmetric encryption.

Backup Script (backup-keys.sh)

This script creates an encrypted backup of the following:

  • All SSH keypairs in ~/.ssh/ starting with id_ (e.g., id_rsa, id_ed25519)
  • All GPG keys (private keys, public keys, and trust database)
  • Your Git global configuration (~/.gitconfig)

Usage

# Make the script executable
chmod +x backup-keys.sh

# Run the backup
./backup-keys.sh

You'll be prompted to enter a passphrase for encryption. Choose a strong passphrase and remember it - you'll need it to restore your keys.

Output

The script creates two items:

  1. ~/keys-backup/ - Temporary directory containing unencrypted copies of your keys
  2. ~/keys-backup-YYYYMMDD.tar.gz.gpg - Encrypted archive (safe to store anywhere)

Restore Script (restore-keys.sh)

This script restores the following from an encrypted backup:

  • All SSH keypairs to ~/.ssh/ with correct permissions
  • Adds SSH keys to ssh-agent
  • All GPG keys to your GPG keyring
  • Your Git global configuration to ~/.gitconfig

Usage

# Make the script executable
chmod +x restore-keys.sh

# Run the restore with the backup file as an argument
./restore-keys.sh keys-backup-YYYYMMDD.tar.gz.gpg

You'll be prompted to enter the passphrase you used during backup.

Security Notes

  • Use a strong passphrase - Your backup is only as secure as your passphrase
  • Keep your passphrase safe - It cannot be recovered if lost
  • Delete unencrypted directories - Always remove ~/keys-backup after creating/verifying the encrypted archive
  • Encrypted archives are safe - The .tar.gz.gpg files can be safely stored in cloud storage or external drives
  • AES256 encryption - Industry-standard encryption protects your keys

Typical Workflow

Setting up a new machine

  1. Download the encrypted backup to your new machine
  2. Download restore-keys.sh from this Gist
  3. Run the restore script with your backup file
  4. Test your connections
  5. Remove the unencrypted temporary directory (~/keys-backup)

Regular backups

  1. Download backup-keys.sh from this Gist
  2. Run the backup script periodically (e.g., after generating new keys)
  3. Verify and store the encrypted archive
  4. Remove the unencrypted temporary directory (~/keys-backup)
#!/usr/bin/env bash
set -euo pipefail
# Enable nullglob so that unmatched globs expand to nothing
shopt -s nullglob
# Colors
CYAN="\033[0;36m"
GREEN="\033[0;92m"
YELLOW="\033[0;33m"
RESET="\033[0m"
BACKUP_DIR_NAME="keys-backup"
BACKUP_DIR_PATH="$HOME/$BACKUP_DIR_NAME"
ENCRYPTED_BACKUP_ARCHIVE_PATH="$HOME/${BACKUP_DIR_NAME}-$(date +%Y%m%d).tar.gz.gpg"
# Backup all SSH keypairs starting with id_
mkdir -p "$BACKUP_DIR_PATH/ssh"
if ls "$HOME/.ssh/id_"* >/dev/null 2>&1; then
cp "$HOME/.ssh/id_"* "$BACKUP_DIR_PATH/ssh/"
else
echo -e "${YELLOW}No SSH keys found in $HOME/.ssh/, skipping.${RESET}"
echo
fi
# Backup all GPG keys and trust
mkdir -p "$BACKUP_DIR_PATH/gpg"
if gpg --list-secret-keys --keyid-format=long >/dev/null 2>&1; then
gpg --export-secret-keys -a > "$BACKUP_DIR_PATH/gpg/private.key"
gpg --export -a > "$BACKUP_DIR_PATH/gpg/public.key"
gpg --export-ownertrust > "$BACKUP_DIR_PATH/gpg/ownertrust.txt"
else
echo -e "${YELLOW}No GPG keys found, skipping.${RESET}"
echo
fi
# Backup Git configuration
if [[ -f "$HOME/.gitconfig" ]]; then
cp "$HOME/.gitconfig" "$BACKUP_DIR_PATH/.gitconfig"
else
echo -e "${YELLOW}No $HOME/.gitconfig found, skipping.${RESET}"
echo
fi
# Encrypt backup directory with GPG (symmetric)
tar -czf - -C "$HOME" "$BACKUP_DIR_NAME" | \
gpg --symmetric --cipher-algo AES256 -o "$ENCRYPTED_BACKUP_ARCHIVE_PATH"
echo "Backup directory created at:"
echo -e " ${GREEN}$BACKUP_DIR_PATH${RESET}"
echo
echo "Encrypted backup archive created at:"
echo -e " ${GREEN}$ENCRYPTED_BACKUP_ARCHIVE_PATH${RESET}"
echo
echo "You can safely upload the encrypted backup archive to the cloud or store it on an external drive."
echo
echo -e "You may delete the backup directory (${CYAN}$BACKUP_DIR_PATH${RESET}) after verifying the encrypted archive."
echo
echo "To verify, run:"
echo -e " ${CYAN}gpg -d $ENCRYPTED_BACKUP_ARCHIVE_PATH | tar -tzf -${RESET}"
echo
echo "Backup complete!"
#!/usr/bin/env bash
set -euo pipefail
# Enable nullglob so that unmatched globs expand to nothing
shopt -s nullglob
# Colors
CYAN="\033[0;36m"
GREEN="\033[0;92m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
RESET="\033[0m"
BACKUP_FILE="${1:-}"
if [[ -z "$BACKUP_FILE" ]]; then
echo -e "${YELLOW}No backup file provided.${RESET}"
echo
echo "Usage:"
echo -e " ${CYAN}$0 /path/to/your/keys-backup-YYYYMMDD.tar.gz.gpg${RESET}"
exit 1
fi
# Decrypt and extract backup
if gpg --quiet -d "$BACKUP_FILE" > /tmp/keys-restore.tar.gz 2>/dev/null; then
tar -xzf /tmp/keys-restore.tar.gz -C "$HOME"
rm -f /tmp/keys-restore.tar.gz
else
echo -e "${RED}Decryption failed. Wrong passphrase or corrupted file.${RESET}"
rm -f /tmp/keys-restore.tar.gz
exit 1
fi
BACKUP_DIR="$HOME/keys-backup"
# Restore SSH keys
mkdir -p "$HOME/.ssh"
if ls "$BACKUP_DIR/ssh/id_"* >/dev/null 2>&1; then
cp "$BACKUP_DIR/ssh/id_"* "$HOME/.ssh/"
chmod 700 "$HOME/.ssh/"
chmod 600 "$HOME/.ssh/id_"*
chmod 644 "$HOME/.ssh/id_"*.pub
eval "$(ssh-agent -s)" >/dev/null 2>&1
for key in "$HOME/.ssh/id_"*; do
if [[ -f "$key" && "$key" != *.pub ]]; then
ssh-add "$key" >/dev/null 2>&1 || true
fi
done
echo "Restored SSH keys:"
for file in "$HOME"/.ssh/id_*; do
echo -e " ${GREEN}${file}${RESET}"
done
echo
else
echo -e "${YELLOW}No SSH keys found in backup, skipping.${RESET}"
echo
fi
# Restore GPG keys
if [[ -f "$BACKUP_DIR/gpg/private.key" ]]; then
gpg --quiet --import "$BACKUP_DIR/gpg/private.key"
gpg --quiet --import "$BACKUP_DIR/gpg/public.key"
gpg --quiet --import-ownertrust < "$BACKUP_DIR/gpg/ownertrust.txt"
echo "Restored GPG keys:"
gpg --list-secret-keys --keyid-format=long 2>/dev/null | \
awk '/^sec|^ssb/ {print $2}' | cut -d'/' -f2 | while read -r keyid; do
echo -e " ${GREEN}${keyid}${RESET}"
done
echo
else
echo -e "${YELLOW}No GPG keys found in backup, skipping.${RESET}"
echo
fi
# Restore Git configuration
if [[ -f "$BACKUP_DIR/.gitconfig" ]]; then
cp "$BACKUP_DIR/.gitconfig" "$HOME/.gitconfig"
echo "Restored $HOME/.gitconfig:"
git config --global --list | while read -r line; do
echo -e " ${GREEN}${line}${RESET}"
done
echo
else
echo -e "${YELLOW}No .gitconfig found in backup, skipping.${RESET}"
echo
fi
echo "You may now safely delete:"
echo -e " ${CYAN}$BACKUP_DIR${RESET}"
echo
echo "Test your SSH connections:"
echo -e " ${CYAN}ssh -T [email protected]${RESET} (GitHub)"
echo -e " ${CYAN}ssh -T [email protected]${RESET} (GitLab)"
echo
echo "Restore complete!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment