claude-home/networking/examples/ssh-homelab-setup.md
Cal Corum 4b7eca8a46
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
docs: add YAML frontmatter to all 151 markdown files
Adds title, description, type, domain, and tags frontmatter to every
doc for improved KB semantic search. The description field is prepended
to every search chunk, and domain/type/tags enable filtered queries.

Type values: context, guide, runbook, reference, troubleshooting
Domain values match directory structure (networking, docker, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:00:44 -05:00

376 lines
9.8 KiB
Markdown

---
title: "SSH Homelab Setup Implementation"
description: "Complete working SSH key-based auth setup with key generation scripts, SSH config, deployment commands, emergency keys, NAS backup, and mobile device access via Termius."
type: guide
domain: networking
tags: [ssh, keys, setup, deployment, backup, termius, mobile]
---
# SSH Home Lab Setup - Complete Implementation
## Overview
Complete working implementation for setting up secure SSH key-based authentication across a home lab environment with emergency backup keys and NAS storage.
## Server Inventory
### Home Network (10.10.0.0/24)
```yaml
servers:
database_apis: 10.10.0.42 # Database and API services
discord_bots: 10.10.0.33 # Discord bot hosting
home_docker: 10.10.0.124 # Main Docker container host
pihole: 10.10.0.16 # Pi-hole DNS and ad blocking
sba_pd_bots: 10.10.0.88 # SBa and PD bot services
tdarr: 10.10.0.43 # Media transcoding
vpn_docker: 10.10.0.121 # VPN and Docker services
```
### Cloud Servers
```yaml
remote_servers:
akamai_nano: 172.237.147.99 # Akamai cloud instance
vultr_host: 45.76.25.231 # Vultr cloud host
```
## SSH Key Generation Script
```bash
#!/bin/bash
# SSH Key Setup Script for Home Lab
# Creates primary + emergency keys with NAS backup
set -e
echo "🔐 Setting up SSH keys for Home Lab with Emergency Backup..."
# Create directories
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Create NAS backup directory
BACKUP_DIR="/mnt/NV2/ssh-keys/backup-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
chmod 700 "$BACKUP_DIR"
echo "📁 NAS backup directory created: $BACKUP_DIR"
# Generate primary keys
if [ ! -f ~/.ssh/homelab_rsa ]; then
ssh-keygen -t rsa -b 4096 -C "homelab-$(whoami)@$(hostname)" -f ~/.ssh/homelab_rsa -N ""
chmod 600 ~/.ssh/homelab_rsa
chmod 644 ~/.ssh/homelab_rsa.pub
echo "✅ Home lab SSH key generated"
fi
if [ ! -f ~/.ssh/cloud_servers_rsa ]; then
ssh-keygen -t rsa -b 4096 -C "cloud-$(whoami)@$(hostname)" -f ~/.ssh/cloud_servers_rsa -N ""
chmod 600 ~/.ssh/cloud_servers_rsa
chmod 644 ~/.ssh/cloud_servers_rsa.pub
echo "✅ Cloud servers SSH key generated"
fi
# Generate emergency keys
if [ ! -f ~/.ssh/emergency_homelab_rsa ]; then
ssh-keygen -t rsa -b 4096 -C "emergency-homelab-$(whoami)@$(hostname)" -f ~/.ssh/emergency_homelab_rsa -N ""
chmod 600 ~/.ssh/emergency_homelab_rsa
chmod 644 ~/.ssh/emergency_homelab_rsa.pub
echo "✅ Emergency home lab key generated"
fi
if [ ! -f ~/.ssh/emergency_cloud_rsa ]; then
ssh-keygen -t rsa -b 4096 -C "emergency-cloud-$(whoami)@$(hostname)" -f ~/.ssh/emergency_cloud_rsa -N ""
chmod 600 ~/.ssh/emergency_cloud_rsa
chmod 644 ~/.ssh/emergency_cloud_rsa.pub
echo "✅ Emergency cloud key generated"
fi
# Backup all keys to NAS
echo "💾 Backing up keys to NAS..."
cp ~/.ssh/*_rsa* "$BACKUP_DIR/" 2>/dev/null || true
cp ~/.ssh/config "$BACKUP_DIR/" 2>/dev/null || true
# Create recovery documentation
cat > "$BACKUP_DIR/RECOVERY_INSTRUCTIONS.md" << EOF
# SSH Key Recovery Instructions
Generated: $(date)
Location: $BACKUP_DIR
## Emergency Recovery Steps
### If you lose access to your primary keys:
1. **Copy emergency keys back:**
\`\`\`bash
cp $BACKUP_DIR/emergency_*_rsa* ~/.ssh/
chmod 600 ~/.ssh/emergency_*_rsa
chmod 644 ~/.ssh/emergency_*_rsa.pub
\`\`\`
2. **Test emergency access:**
\`\`\`bash
ssh -i ~/.ssh/emergency_homelab_rsa cal@10.10.0.16
ssh -i ~/.ssh/emergency_cloud_rsa root@172.237.147.99
\`\`\`
3. **If emergency keys weren't deployed, use console access:**
- Home servers: Physical console access
- Cloud servers: Provider web console
- Add emergency public key to ~/.ssh/authorized_keys
EOF
ls -la "$BACKUP_DIR" >> "$BACKUP_DIR/RECOVERY_INSTRUCTIONS.md"
echo "✅ Keys backed up to: $BACKUP_DIR"
echo "🎉 SSH keys and emergency backups created successfully!"
```
## SSH Configuration
```bash
# SSH Configuration for Home Lab (~/.ssh/config)
# Global defaults
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
StrictHostKeyChecking ask
VerifyHostKeyDNS yes
ForwardAgent no
ForwardX11 no
AddKeysToAgent yes
# Home Network Servers
Host strat-database pd-database sba-database strat-db pd-db sba-db
HostName 10.10.0.42
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
Host discord-bots
HostName 10.10.0.33
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
Host docker-home docker-main
HostName 10.10.0.124
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
Host pihole dns
HostName 10.10.0.16
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
Host sba-bots pd-bots
HostName 10.10.0.88
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
Host tdarr media
HostName 10.10.0.43
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
Host docker-vpn
HostName 10.10.0.121
User cal
Port 22
IdentityFile ~/.ssh/homelab_rsa
# Remote Cloud Servers
Host akamai-nano akamai
HostName 172.237.147.99
User root
Port 22
IdentityFile ~/.ssh/cloud_servers_rsa
Host vultr-host vultr
HostName 45.76.25.231
User root
Port 22
IdentityFile ~/.ssh/cloud_servers_rsa
# Home network wildcard for easy access
Host 10.10.0.*
User cal
IdentityFile ~/.ssh/homelab_rsa
StrictHostKeyChecking accept-new
```
## Key Deployment Commands
### Primary Keys
```bash
# Home lab servers
for ip in 42 33 124 16 88 43 121; do
ssh-copy-id -i ~/.ssh/homelab_rsa.pub cal@10.10.0.$ip
done
# Cloud servers
ssh-copy-id -i ~/.ssh/cloud_servers_rsa.pub root@172.237.147.99
ssh-copy-id -i ~/.ssh/cloud_servers_rsa.pub root@45.76.25.231
```
### Emergency Keys
```bash
# Home lab servers (use -f to force)
for ip in 42 33 124 16 88 43 121; do
ssh-copy-id -f -i ~/.ssh/emergency_homelab_rsa.pub cal@10.10.0.$ip
done
# Cloud servers
ssh-copy-id -f -i ~/.ssh/emergency_cloud_rsa.pub root@172.237.147.99
ssh-copy-id -f -i ~/.ssh/emergency_cloud_rsa.pub root@45.76.25.231
```
## Maintenance Script
```bash
#!/bin/bash
# SSH Key Maintenance and Backup Script
# Location: ~/bin/ssh_key_maintenance.sh
# Schedule: 0 2 1 * * (monthly at 2 AM)
echo "🔧 SSH Key Maintenance and Backup"
# Check NAS availability
if [ ! -d "/mnt/NV2" ]; then
echo "❌ ERROR: NAS not mounted at /mnt/NV2"
exit 1
fi
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
BACKUP_ROOT="/mnt/NV2/ssh-keys"
BACKUP_DIR="$BACKUP_ROOT/maintenance-$TIMESTAMP"
mkdir -p "$BACKUP_DIR"
chmod 700 "$BACKUP_DIR"
# Backup current state
cp ~/.ssh/*_rsa* "$BACKUP_DIR/" 2>/dev/null || true
cp ~/.ssh/config "$BACKUP_DIR/" 2>/dev/null || true
cp ~/.ssh/known_hosts "$BACKUP_DIR/" 2>/dev/null || true
# Check key ages and health
echo "🔍 Key Age Analysis:"
for key in ~/.ssh/*_rsa; do
if [ -f "$key" ]; then
age_days=$(( ($(date +%s) - $(stat -c %Y "$key")) / 86400 ))
basename_key=$(basename "$key")
if [ $age_days -gt 365 ]; then
echo "⚠️ $basename_key: $age_days days old - ROTATION RECOMMENDED"
elif [ $age_days -gt 180 ]; then
echo "⚡ $basename_key: $age_days days old - consider rotation"
else
echo "✅ $basename_key: $age_days days old - OK"
fi
fi
done
# Clean up old backups (keep last 10)
cd "$BACKUP_ROOT"
ls -dt backup-* maintenance-* 2>/dev/null | tail -n +11 | while read old_backup; do
if [ -d "$old_backup" ]; then
echo "🗑️ Removing old backup: $old_backup"
rm -rf "$old_backup"
fi
done
echo "✅ Maintenance backup completed: $BACKUP_DIR"
```
## Testing Procedures
### Test Primary Access
```bash
# Test aliases work
ssh strat-database 'echo "Primary access: $(hostname)"'
ssh pihole 'echo "Primary access: $(hostname)"'
ssh akamai 'echo "Primary access: $(hostname)"'
```
### Test Emergency Access
```bash
# Test emergency keys work
ssh -i ~/.ssh/emergency_homelab_rsa cal@10.10.0.16 'echo "Emergency access: $(hostname)"'
ssh -i ~/.ssh/emergency_cloud_rsa root@172.237.147.99 'echo "Emergency access: $(hostname)"'
```
## Cron Schedule Setup
```bash
# Open crontab editor
crontab -e
# Add monthly maintenance (1st of month at 2 AM)
0 2 1 * * /home/cal/bin/ssh_key_maintenance.sh
```
## Security Hardening
After key deployment, disable password authentication on servers:
```bash
# On each server, edit /etc/ssh/sshd_config:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no # Create non-root users first on cloud servers
AllowUsers cal # Restrict SSH access
# Restart SSH service
sudo systemctl restart sshd
```
## Mobile Device SSH Access
### Termius Setup (iPhone/iPad)
Connect to local development machine using existing homelab keys:
```yaml
Connection Details:
Host: 10.0.0.206 (or current eno1 IP)
Username: cal
Port: 22
Key: homelab_rsa (same key used for server access)
```
### Prerequisites Checklist
Before mobile SSH access works, ensure:
1. **SSH service is running:**
```bash
sudo systemctl start sshd
sudo systemctl enable sshd
```
2. **Firewall allows SSH:**
```bash
sudo firewall-cmd --list-services # Should include 'ssh'
# If not present, SSH was already allowed in this setup
```
3. **Authorized keys configured:**
```bash
# homelab_rsa.pub should be in ~/.ssh/authorized_keys
cat ~/.ssh/homelab_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```
### Key Transfer Process
1. Copy private key: `cp ~/.ssh/homelab_rsa ./homelab_rsa_for_mobile`
2. Transfer securely to mobile device (AirDrop, secure file share)
3. Import into Termius app
4. Clean up: `rm homelab_rsa_for_mobile`
### Network Discovery
Find local machine IP: `ip addr show eno1 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1`
## Related Documentation
- Patterns: `patterns/networking/ssh-key-management.md`
- Troubleshooting: `reference/networking/ssh-troubleshooting.md`