SSH Homelab Setup: - Add mobile device SSH access documentation (Termius setup) - Include prerequisites checklist and key transfer process - Document network discovery commands for mobile access Tdarr Timeout Monitor: - Add comprehensive debug logging with structured levels (INFO/DEBUG/ERROR/WARN/SUCCESS) - Implement command execution timing and detailed error tracking - Enhance container status verification and error handling - Add log entry counting and detailed output analysis - Improve cleanup operations with better failure detection - Add performance metrics and duration tracking for all operations Tdarr Node Startup: - Add unmapped node cache volume mapping for media access - Complete production configuration for distributed transcoding 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
368 lines
9.5 KiB
Markdown
368 lines
9.5 KiB
Markdown
# 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` |