#!/usr/bin/env bash # Backup and encrypt SSH keys set -euo pipefail SSH_DIR="$HOME/.ssh" BACKUP_DIR="$HOME/dotfiles/backups/ssh" TIMESTAMP=$(date +%Y%m%d_%H%M%S) # Colors GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' BLUE='\033[0;34m' NC='\033[0m' echo -e "${BLUE}SSH Keys Backup & Encryption${NC}" echo "===============================" # Check if SSH directory exists if [ ! -d "$SSH_DIR" ]; then echo -e "${RED}❌ SSH directory not found: $SSH_DIR${NC}" exit 1 fi # Check if GPG is available if ! command -v gpg >/dev/null 2>&1; then echo -e "${RED}❌ GPG not found. Please install GPG first.${NC}" echo "Install with: brew install gnupg" exit 1 fi # Create backup directory mkdir -p "$BACKUP_DIR" echo -e "${YELLOW}🔍 Scanning SSH directory...${NC}" # Find private keys (files without .pub extension and not config/known_hosts) PRIVATE_KEYS=() while IFS= read -r -d '' file; do filename=$(basename "$file") # Skip public keys, config files, and known_hosts if [[ ! "$filename" =~ \.(pub|ppk)$ ]] && \ [[ "$filename" != "config" ]] && \ [[ "$filename" != "known_hosts" ]] && \ [[ "$filename" != "authorized_keys" ]]; then PRIVATE_KEYS+=("$file") fi done < <(find "$SSH_DIR" -type f -print0) if [ ${#PRIVATE_KEYS[@]} -eq 0 ]; then echo -e "${YELLOW}⚠️ No private keys found to backup${NC}" exit 0 fi echo -e "${GREEN}Found ${#PRIVATE_KEYS[@]} private key(s):${NC}" for key in "${PRIVATE_KEYS[@]}"; do echo " • $(basename "$key")" done echo "" # Ask for confirmation read -p "Proceed with backup and encryption? (y/N) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo "Backup cancelled." exit 0 fi # Create tarball of SSH directory TEMP_TAR="/tmp/ssh_backup_${TIMESTAMP}.tar" echo -e "${YELLOW}📦 Creating backup archive...${NC}" # Create tar with only the files we want tar -cf "$TEMP_TAR" -C "$HOME" .ssh/config 2>/dev/null || true # Add private keys to tar for key in "${PRIVATE_KEYS[@]}"; do relative_path=$(echo "$key" | sed "s|$HOME/||") tar -rf "$TEMP_TAR" -C "$HOME" "$relative_path" 2>/dev/null || true echo " ✓ Added: $(basename "$key")" done # Add public keys corresponding to private keys for key in "${PRIVATE_KEYS[@]}"; do pub_key="${key}.pub" if [ -f "$pub_key" ]; then relative_path=$(echo "$pub_key" | sed "s|$HOME/||") tar -rf "$TEMP_TAR" -C "$HOME" "$relative_path" 2>/dev/null || true echo " ✓ Added: $(basename "$pub_key")" fi done # Compress the tar gzip "$TEMP_TAR" TEMP_TAR="${TEMP_TAR}.gz" # Encrypt with GPG ENCRYPTED_FILE="$BACKUP_DIR/ssh_keys_${TIMESTAMP}.tar.gz.gpg" echo -e "${YELLOW}🔐 Encrypting backup...${NC}" echo "You will be prompted for a passphrase to encrypt the backup." if gpg --symmetric --cipher-algo AES256 --compress-algo 1 --s2k-mode 3 \ --s2k-digest-algo SHA512 --s2k-count 65536 \ --output "$ENCRYPTED_FILE" "$TEMP_TAR"; then # Clean up temporary file rm "$TEMP_TAR" echo -e "${GREEN}✅ SSH keys backup completed!${NC}" echo "" echo "Backup details:" echo " 📁 Location: $ENCRYPTED_FILE" echo " 📏 Size: $(du -h "$ENCRYPTED_FILE" | cut -f1)" echo " 🔑 Encryption: AES256" echo "" # Create restore instructions cat > "$BACKUP_DIR/RESTORE_INSTRUCTIONS.md" << EOF # SSH Keys Restore Instructions ## Decrypting and Restoring SSH Keys To restore from backup: \`ssh_keys_${TIMESTAMP}.tar.gz.gpg\` ### Step 1: Decrypt the backup \`\`\`bash gpg --decrypt ssh_keys_${TIMESTAMP}.tar.gz.gpg > ssh_keys_${TIMESTAMP}.tar.gz \`\`\` ### Step 2: Extract the archive \`\`\`bash tar -xzf ssh_keys_${TIMESTAMP}.tar.gz -C ~/ \`\`\` ### Step 3: Set correct permissions \`\`\`bash chmod 700 ~/.ssh chmod 600 ~/.ssh/config chmod 600 ~/.ssh/*_key ~/.ssh/id_* chmod 644 ~/.ssh/*.pub \`\`\` ### Step 4: Add keys to SSH agent (if needed) \`\`\`bash ssh-add ~/.ssh/your_key_name \`\`\` ## Security Notes - Keep this encrypted backup in a secure location - The backup contains your private keys - treat it as highly sensitive - Consider storing a copy in a different location (cloud storage, external drive) - Test the restore process periodically ## Backup Contents This backup includes: - SSH configuration file - Private keys found in ~/.ssh/ - Corresponding public keys - Proper directory structure Created: $(date) System: $(sw_vers -productVersion) EOF echo -e "${YELLOW}📋 Restore instructions created: $BACKUP_DIR/RESTORE_INSTRUCTIONS.md${NC}" # Clean up old backups (keep last 5) cd "$BACKUP_DIR" ls -t ssh_keys_*.tar.gz.gpg 2>/dev/null | tail -n +6 | xargs -r rm echo -e "${GREEN}🎉 Backup process complete!${NC}" else # Clean up on failure rm -f "$TEMP_TAR" echo -e "${RED}❌ Encryption failed!${NC}" exit 1 fi