From 8bddc004a78546107bd85a8712823ff3344be7af Mon Sep 17 00:00:00 2001 From: David F Glidden Date: Sun, 27 Jul 2025 13:23:22 +0200 Subject: [PATCH] Add SSH key backup script and fix git config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Copy actual .gitconfig instead of placeholder - Create encrypted SSH key backup script with GPG - Add SSH-based remote setup script - Include restore instructions and security notes 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude --- .gitconfig | 14 +++ scripts/backup-ssh-keys.sh | 182 +++++++++++++++++++++++++++++++++++++ setup-remotes-ssh.sh | 92 +++++++++++++++++++ setup-remotes.sh | 61 +++++++++++++ 4 files changed, 349 insertions(+) create mode 100644 .gitconfig create mode 100755 scripts/backup-ssh-keys.sh create mode 100755 setup-remotes-ssh.sh create mode 100755 setup-remotes.sh diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..9b67785 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,14 @@ +# This is Git's per-user configuration file. +[user] + name = David F Glidden + email = d@davidglidden.eu +# Please adapt and uncomment the following lines: +# name = David GLIDDEN +# email = davidglidden@Macintosh.home +[filter "lfs"] + clean = git-lfs clean -- %f + smudge = git-lfs smudge -- %f + process = git-lfs filter-process + required = true +[url "git@github.com:"] + insteadOf = https://github.com/ diff --git a/scripts/backup-ssh-keys.sh b/scripts/backup-ssh-keys.sh new file mode 100755 index 0000000..4dbd974 --- /dev/null +++ b/scripts/backup-ssh-keys.sh @@ -0,0 +1,182 @@ +#!/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 \ No newline at end of file diff --git a/setup-remotes-ssh.sh b/setup-remotes-ssh.sh new file mode 100755 index 0000000..712a729 --- /dev/null +++ b/setup-remotes-ssh.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# Setup GitHub and Gitea remotes using SSH + +set -euo pipefail + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +echo -e "${BLUE}Setting up Git remotes with SSH${NC}" +echo "==================================" + +cd ~/dotfiles + +# Get GitHub username +echo -e "${YELLOW}What's your GitHub username?${NC}" +read -p "GitHub username: " GITHUB_USER + +# Get Gitea details (optional) +echo "" +echo -e "${YELLOW}Gitea setup (optional - press Enter to skip):${NC}" +read -p "Gitea server URL (e.g., git.yourdomain.com): " GITEA_SERVER +if [ -n "$GITEA_SERVER" ]; then + read -p "Gitea username: " GITEA_USER +fi + +echo "" +echo -e "${BLUE}Setting up remotes...${NC}" + +# Add GitHub remote +if ! git remote get-url github >/dev/null 2>&1; then + git remote add github git@github.com:${GITHUB_USER}/dotfiles.git + echo -e "${GREEN}✓ Added GitHub remote${NC}" +else + echo -e "${YELLOW}GitHub remote already exists${NC}" +fi + +# Add Gitea remote if provided +if [ -n "$GITEA_SERVER" ] && [ -n "$GITEA_USER" ]; then + if ! git remote get-url gitea >/dev/null 2>&1; then + git remote add gitea git@${GITEA_SERVER}:${GITEA_USER}/dotfiles.git + echo -e "${GREEN}✓ Added Gitea remote${NC}" + else + echo -e "${YELLOW}Gitea remote already exists${NC}" + fi +fi + +echo "" +echo -e "${BLUE}Manual steps required:${NC}" +echo "" +echo "1. 📋 Create repositories manually:" +echo " • GitHub: https://github.com/new" +echo " - Repository name: dotfiles" +echo " - Description: 🖖 Complete macOS dotfiles system - 'Engage!'" +echo " - Public repository" +echo " - Don't initialize with README, .gitignore, or license" + +if [ -n "$GITEA_SERVER" ]; then + echo " • Gitea: https://${GITEA_SERVER}/repo/create" + echo " - Repository name: dotfiles" + echo " - Description: 🖖 Complete macOS dotfiles system - 'Engage!'" + echo " - Public repository" +fi + +echo "" +echo "2. 🔑 Test SSH access:" +echo " ssh -T git@github.com" +if [ -n "$GITEA_SERVER" ]; then + echo " ssh -T git@${GITEA_SERVER}" +fi + +echo "" +echo "3. 🚀 Push to remotes:" +echo " git push -u github master" +if [ -n "$GITEA_SERVER" ]; then + echo " git push -u gitea master" +fi + +echo "" +echo -e "${GREEN}Remote setup complete!${NC}" +echo "" +echo "Your repositories will be available at:" +echo "• GitHub: https://github.com/${GITHUB_USER}/dotfiles" +if [ -n "$GITEA_SERVER" ]; then + echo "• Gitea: https://${GITEA_SERVER}/${GITEA_USER}/dotfiles" +fi +echo "" +echo -e "${BLUE}Clone command for new machines:${NC}" +echo "git clone git@github.com:${GITHUB_USER}/dotfiles.git ~/dotfiles && ~/dotfiles/engage" \ No newline at end of file diff --git a/setup-remotes.sh b/setup-remotes.sh new file mode 100755 index 0000000..5046451 --- /dev/null +++ b/setup-remotes.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# Setup GitHub and Gitea remotes for dotfiles repository + +set -euo pipefail + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +echo -e "${BLUE}Setting up Git remotes for dotfiles repository${NC}" +echo "==============================================" + +cd ~/dotfiles + +# Check if we have gh CLI +if ! command -v gh >/dev/null 2>&1; then + echo -e "${YELLOW}GitHub CLI (gh) not found. Please install it first: brew install gh${NC}" + exit 1 +fi + +# Check if logged into GitHub +if ! gh auth status >/dev/null 2>&1; then + echo -e "${YELLOW}Please login to GitHub first: gh auth login${NC}" + exit 1 +fi + +echo -e "${YELLOW}Creating GitHub repository...${NC}" + +# Create GitHub repository +gh repo create dotfiles --public --description "🖖 Complete macOS dotfiles system - From zero to fully configured in minutes. 'Engage!'" --homepage "" + +# Add GitHub remote +git remote add github https://github.com/$(gh api user --jq .login)/dotfiles.git + +echo -e "${GREEN}✓ GitHub repository created${NC}" + +# Push to GitHub +echo -e "${YELLOW}Pushing to GitHub...${NC}" +git push -u github master + +echo -e "${GREEN}✓ Pushed to GitHub${NC}" + +echo "" +echo -e "${BLUE}Gitea Setup${NC}" +echo "For Gitea, you'll need to:" +echo "1. Create repository manually on your Gitea instance" +echo "2. Add the remote:" +echo " git remote add gitea https://your-gitea-instance.com/username/dotfiles.git" +echo "3. Push to Gitea:" +echo " git push -u gitea master" + +echo "" +echo -e "${GREEN}Setup complete! 🎉${NC}" +echo "" +echo "Repository URLs:" +echo "• GitHub: https://github.com/$(gh api user --jq .login)/dotfiles" +echo "• Clone command: git clone https://github.com/$(gh api user --jq .login)/dotfiles.git ~/dotfiles && ~/dotfiles/engage" +echo "" +echo -e "${BLUE}Your 'engage' command is ready for the world! 🖖${NC}" \ No newline at end of file