708 lines
13 KiB
Markdown
708 lines
13 KiB
Markdown
# Installation Guide
|
|
|
|
Complete step-by-step tutorial for setting up Tailscale SSH Sync Agent.
|
|
|
|
## Table of Contents
|
|
|
|
1. [Prerequisites](#prerequisites)
|
|
2. [Step 1: Install Tailscale](#step-1-install-tailscale)
|
|
3. [Step 2: Install sshsync](#step-2-install-sshsync)
|
|
4. [Step 3: Configure SSH](#step-3-configure-ssh)
|
|
5. [Step 4: Configure sshsync Groups](#step-4-configure-sshsync-groups)
|
|
6. [Step 5: Install Agent](#step-5-install-agent)
|
|
7. [Step 6: Test Installation](#step-6-test-installation)
|
|
8. [Troubleshooting](#troubleshooting)
|
|
|
|
## Prerequisites
|
|
|
|
Before you begin, ensure you have:
|
|
|
|
- **Operating System**: macOS, Linux, or BSD
|
|
- **Python**: Version 3.10 or higher
|
|
- **pip**: Python package installer
|
|
- **Claude Code**: Installed and running
|
|
- **Remote machines**: At least one machine you want to manage
|
|
- **SSH access**: Ability to SSH to remote machines
|
|
|
|
**Check Python version**:
|
|
```bash
|
|
python3 --version
|
|
# Should show: Python 3.10.x or higher
|
|
```
|
|
|
|
**Check pip**:
|
|
```bash
|
|
pip3 --version
|
|
# Should show: pip xx.x.x from ...
|
|
```
|
|
|
|
## Step 1: Install Tailscale
|
|
|
|
Tailscale provides secure networking between your machines.
|
|
|
|
### macOS
|
|
|
|
```bash
|
|
# Install via Homebrew
|
|
brew install tailscale
|
|
|
|
# Start Tailscale
|
|
sudo tailscale up
|
|
|
|
# Follow authentication link in terminal
|
|
# This will open browser to log in
|
|
```
|
|
|
|
### Linux (Ubuntu/Debian)
|
|
|
|
```bash
|
|
# Install Tailscale
|
|
curl -fsSL https://tailscale.com/install.sh | sh
|
|
|
|
# Start and authenticate
|
|
sudo tailscale up
|
|
|
|
# Follow authentication link
|
|
```
|
|
|
|
### Linux (Fedora/RHEL)
|
|
|
|
```bash
|
|
# Add repository
|
|
sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/fedora/tailscale.repo
|
|
|
|
# Install
|
|
sudo dnf install tailscale
|
|
|
|
# Enable and start
|
|
sudo systemctl enable --now tailscaled
|
|
sudo tailscale up
|
|
```
|
|
|
|
### Verify Installation
|
|
|
|
```bash
|
|
# Check Tailscale status
|
|
tailscale status
|
|
|
|
# Should show list of machines in your tailnet
|
|
# Example output:
|
|
# 100.64.1.10 homelab-1 user@ linux -
|
|
# 100.64.1.11 laptop user@ macOS -
|
|
```
|
|
|
|
**Important**: Install and authenticate Tailscale on **all machines** you want to manage.
|
|
|
|
## Step 2: Install sshsync
|
|
|
|
sshsync is the CLI tool for managing SSH operations across multiple hosts.
|
|
|
|
```bash
|
|
# Install via pip
|
|
pip3 install sshsync
|
|
|
|
# Or use pipx for isolated installation
|
|
pipx install sshsync
|
|
```
|
|
|
|
### Verify Installation
|
|
|
|
```bash
|
|
# Check version
|
|
sshsync --version
|
|
|
|
# Should show: sshsync, version x.x.x
|
|
```
|
|
|
|
### Common Installation Issues
|
|
|
|
**Issue**: `pip3: command not found`
|
|
|
|
**Solution**:
|
|
```bash
|
|
# macOS
|
|
brew install python3
|
|
|
|
# Linux (Ubuntu/Debian)
|
|
sudo apt install python3-pip
|
|
|
|
# Linux (Fedora/RHEL)
|
|
sudo dnf install python3-pip
|
|
```
|
|
|
|
**Issue**: Permission denied during install
|
|
|
|
**Solution**:
|
|
```bash
|
|
# Install for current user only
|
|
pip3 install --user sshsync
|
|
|
|
# Or use pipx
|
|
pip3 install --user pipx
|
|
pipx install sshsync
|
|
```
|
|
|
|
## Step 3: Configure SSH
|
|
|
|
SSH configuration defines how to connect to each machine.
|
|
|
|
### Step 3.1: Generate SSH Keys (if you don't have them)
|
|
|
|
```bash
|
|
# Generate ed25519 key (recommended)
|
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
|
|
|
# Press Enter to use default location (~/.ssh/id_ed25519)
|
|
# Enter passphrase (or leave empty for no passphrase)
|
|
```
|
|
|
|
**Output**:
|
|
```
|
|
Your identification has been saved in /Users/you/.ssh/id_ed25519
|
|
Your public key has been saved in /Users/you/.ssh/id_ed25519.pub
|
|
```
|
|
|
|
### Step 3.2: Copy Public Key to Remote Machines
|
|
|
|
For each remote machine:
|
|
|
|
```bash
|
|
# Copy SSH key to remote
|
|
ssh-copy-id user@machine-hostname
|
|
|
|
# Example:
|
|
ssh-copy-id admin@100.64.1.10
|
|
```
|
|
|
|
**Manual method** (if ssh-copy-id doesn't work):
|
|
|
|
```bash
|
|
# Display public key
|
|
cat ~/.ssh/id_ed25519.pub
|
|
|
|
# SSH to remote machine
|
|
ssh user@remote-host
|
|
|
|
# On remote machine:
|
|
mkdir -p ~/.ssh
|
|
chmod 700 ~/.ssh
|
|
echo "your-public-key-here" >> ~/.ssh/authorized_keys
|
|
chmod 600 ~/.ssh/authorized_keys
|
|
exit
|
|
```
|
|
|
|
### Step 3.3: Test SSH Connection
|
|
|
|
```bash
|
|
# Test connection (should not ask for password)
|
|
ssh user@remote-host "hostname"
|
|
|
|
# If successful, should print remote hostname
|
|
```
|
|
|
|
### Step 3.4: Create SSH Config File
|
|
|
|
Edit `~/.ssh/config`:
|
|
|
|
```bash
|
|
vim ~/.ssh/config
|
|
```
|
|
|
|
**Add host entries**:
|
|
|
|
```
|
|
# Production servers
|
|
Host prod-web-01
|
|
HostName prod-web-01.tailnet.ts.net
|
|
User deploy
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
Port 22
|
|
|
|
Host prod-web-02
|
|
HostName 100.64.1.21
|
|
User deploy
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
|
|
Host prod-db-01
|
|
HostName 100.64.1.30
|
|
User deploy
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
|
|
# Development
|
|
Host dev-laptop
|
|
HostName dev-laptop.tailnet.ts.net
|
|
User developer
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
|
|
Host dev-desktop
|
|
HostName 100.64.1.40
|
|
User developer
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
|
|
# Homelab
|
|
Host homelab-1
|
|
HostName 100.64.1.10
|
|
User admin
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
|
|
Host homelab-2
|
|
HostName 100.64.1.11
|
|
User admin
|
|
IdentityFile ~/.ssh/id_ed25519
|
|
```
|
|
|
|
**Important fields**:
|
|
- **Host**: Alias you'll use (e.g., "homelab-1")
|
|
- **HostName**: Actual hostname or IP (Tailscale hostname or IP)
|
|
- **User**: SSH username on remote machine
|
|
- **IdentityFile**: Path to SSH private key
|
|
|
|
### Step 3.5: Set Correct Permissions
|
|
|
|
```bash
|
|
# SSH config should be readable only by you
|
|
chmod 600 ~/.ssh/config
|
|
|
|
# SSH directory permissions
|
|
chmod 700 ~/.ssh
|
|
|
|
# Private key permissions
|
|
chmod 600 ~/.ssh/id_ed25519
|
|
|
|
# Public key permissions
|
|
chmod 644 ~/.ssh/id_ed25519.pub
|
|
```
|
|
|
|
### Step 3.6: Verify All Hosts
|
|
|
|
Test each host in your config:
|
|
|
|
```bash
|
|
# Test each host
|
|
ssh homelab-1 "echo 'Connection successful'"
|
|
ssh prod-web-01 "echo 'Connection successful'"
|
|
ssh dev-laptop "echo 'Connection successful'"
|
|
|
|
# Should connect without asking for password
|
|
```
|
|
|
|
## Step 4: Configure sshsync Groups
|
|
|
|
Groups organize your hosts for easy management.
|
|
|
|
### Step 4.1: Initialize sshsync Configuration
|
|
|
|
```bash
|
|
# Sync hosts and create groups
|
|
sshsync sync
|
|
```
|
|
|
|
**What this does**:
|
|
1. Reads all hosts from `~/.ssh/config`
|
|
2. Prompts you to assign hosts to groups
|
|
3. Creates `~/.config/sshsync/config.yaml`
|
|
|
|
### Step 4.2: Follow Interactive Prompts
|
|
|
|
```
|
|
Found 7 ungrouped hosts:
|
|
1. homelab-1
|
|
2. homelab-2
|
|
3. prod-web-01
|
|
4. prod-web-02
|
|
5. prod-db-01
|
|
6. dev-laptop
|
|
7. dev-desktop
|
|
|
|
Assign groups now? [Y/n]: Y
|
|
|
|
Enter group name for homelab-1 (or skip): homelab
|
|
Enter group name for homelab-2 (or skip): homelab
|
|
Enter group name for prod-web-01 (or skip): production,web
|
|
Enter group name for prod-web-02 (or skip): production,web
|
|
Enter group name for prod-db-01 (or skip): production,database
|
|
Enter group name for dev-laptop (or skip): development
|
|
Enter group name for dev-desktop (or skip): development
|
|
```
|
|
|
|
**Tips**:
|
|
- Hosts can belong to multiple groups (separate with commas)
|
|
- Use meaningful group names (production, development, web, database, homelab)
|
|
- Skip hosts you don't want to group yet
|
|
|
|
### Step 4.3: Verify Configuration
|
|
|
|
```bash
|
|
# View generated config
|
|
cat ~/.config/sshsync/config.yaml
|
|
```
|
|
|
|
**Expected output**:
|
|
```yaml
|
|
groups:
|
|
production:
|
|
- prod-web-01
|
|
- prod-web-02
|
|
- prod-db-01
|
|
web:
|
|
- prod-web-01
|
|
- prod-web-02
|
|
database:
|
|
- prod-db-01
|
|
development:
|
|
- dev-laptop
|
|
- dev-desktop
|
|
homelab:
|
|
- homelab-1
|
|
- homelab-2
|
|
```
|
|
|
|
### Step 4.4: Test sshsync
|
|
|
|
```bash
|
|
# List hosts
|
|
sshsync ls
|
|
|
|
# List with status
|
|
sshsync ls --with-status
|
|
|
|
# Test command execution
|
|
sshsync all "hostname"
|
|
|
|
# Test group execution
|
|
sshsync group homelab "uptime"
|
|
```
|
|
|
|
## Step 5: Install Agent
|
|
|
|
### Step 5.1: Navigate to Agent Directory
|
|
|
|
```bash
|
|
cd /path/to/tailscale-sshsync-agent
|
|
```
|
|
|
|
### Step 5.2: Verify Agent Structure
|
|
|
|
```bash
|
|
# List files
|
|
ls -la
|
|
|
|
# Should see:
|
|
# .claude-plugin/
|
|
# scripts/
|
|
# tests/
|
|
# references/
|
|
# SKILL.md
|
|
# README.md
|
|
# VERSION
|
|
# CHANGELOG.md
|
|
# etc.
|
|
```
|
|
|
|
### Step 5.3: Validate marketplace.json
|
|
|
|
```bash
|
|
# Check JSON is valid
|
|
python3 -c "import json; json.load(open('.claude-plugin/marketplace.json')); print('✅ Valid JSON')"
|
|
|
|
# Should output: ✅ Valid JSON
|
|
```
|
|
|
|
### Step 5.4: Install via Claude Code
|
|
|
|
In Claude Code:
|
|
|
|
```
|
|
/plugin marketplace add /absolute/path/to/tailscale-sshsync-agent
|
|
```
|
|
|
|
**Example**:
|
|
```
|
|
/plugin marketplace add /Users/you/tailscale-sshsync-agent
|
|
```
|
|
|
|
**Expected output**:
|
|
```
|
|
✓ Plugin installed successfully
|
|
✓ Skill: tailscale-sshsync-agent
|
|
✓ Description: Manages distributed workloads and file sharing...
|
|
```
|
|
|
|
### Step 5.5: Verify Installation
|
|
|
|
In Claude Code:
|
|
|
|
```
|
|
"Which of my machines are online?"
|
|
```
|
|
|
|
**Expected response**: Agent should activate and check your Tailscale network.
|
|
|
|
## Step 6: Test Installation
|
|
|
|
### Test 1: Host Status
|
|
|
|
**Query**:
|
|
```
|
|
"Which of my machines are online?"
|
|
```
|
|
|
|
**Expected**: List of hosts with online/offline status
|
|
|
|
### Test 2: List Groups
|
|
|
|
**Query**:
|
|
```
|
|
"What groups do I have configured?"
|
|
```
|
|
|
|
**Expected**: List of your sshsync groups
|
|
|
|
### Test 3: Execute Command
|
|
|
|
**Query**:
|
|
```
|
|
"Check disk space on homelab machines"
|
|
```
|
|
|
|
**Expected**: Disk usage for hosts in homelab group
|
|
|
|
### Test 4: Dry-Run
|
|
|
|
**Query**:
|
|
```
|
|
"Show me what would happen if I ran 'uptime' on all machines (dry-run)"
|
|
```
|
|
|
|
**Expected**: Preview without execution
|
|
|
|
### Test 5: Run Test Suite
|
|
|
|
```bash
|
|
cd /path/to/tailscale-sshsync-agent
|
|
|
|
# Run all tests
|
|
python3 tests/test_integration.py
|
|
|
|
# Should show:
|
|
# Results: 11/11 passed
|
|
# 🎉 All tests passed!
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Agent Not Activating
|
|
|
|
**Symptoms**: Agent doesn't respond to queries about machines/hosts
|
|
|
|
**Solutions**:
|
|
|
|
1. **Check installation**:
|
|
```
|
|
/plugin list
|
|
```
|
|
Should show `tailscale-sshsync-agent` in list.
|
|
|
|
2. **Reinstall**:
|
|
```
|
|
/plugin remove tailscale-sshsync-agent
|
|
/plugin marketplace add /path/to/tailscale-sshsync-agent
|
|
```
|
|
|
|
3. **Check marketplace.json**:
|
|
```bash
|
|
cat .claude-plugin/marketplace.json
|
|
# Verify "description" field matches SKILL.md frontmatter
|
|
```
|
|
|
|
### SSH Connection Fails
|
|
|
|
**Symptoms**: "Permission denied" or "Connection refused"
|
|
|
|
**Solutions**:
|
|
|
|
1. **Check SSH key**:
|
|
```bash
|
|
ssh-add -l
|
|
# Should list your SSH key
|
|
```
|
|
|
|
If not listed:
|
|
```bash
|
|
ssh-add ~/.ssh/id_ed25519
|
|
```
|
|
|
|
2. **Test SSH directly**:
|
|
```bash
|
|
ssh -v hostname
|
|
# -v shows verbose debug info
|
|
```
|
|
|
|
3. **Verify authorized_keys on remote**:
|
|
```bash
|
|
ssh hostname "cat ~/.ssh/authorized_keys"
|
|
# Should contain your public key
|
|
```
|
|
|
|
### Tailscale Connection Issues
|
|
|
|
**Symptoms**: Hosts show as offline in Tailscale
|
|
|
|
**Solutions**:
|
|
|
|
1. **Check Tailscale status**:
|
|
```bash
|
|
tailscale status
|
|
```
|
|
|
|
2. **Restart Tailscale**:
|
|
```bash
|
|
# macOS
|
|
brew services restart tailscale
|
|
|
|
# Linux
|
|
sudo systemctl restart tailscaled
|
|
```
|
|
|
|
3. **Re-authenticate**:
|
|
```bash
|
|
sudo tailscale up
|
|
```
|
|
|
|
### sshsync Errors
|
|
|
|
**Symptoms**: "sshsync: command not found"
|
|
|
|
**Solutions**:
|
|
|
|
1. **Reinstall sshsync**:
|
|
```bash
|
|
pip3 install --upgrade sshsync
|
|
```
|
|
|
|
2. **Check PATH**:
|
|
```bash
|
|
which sshsync
|
|
# Should show path to sshsync
|
|
```
|
|
|
|
If not found, add to PATH:
|
|
```bash
|
|
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
|
source ~/.bashrc
|
|
```
|
|
|
|
### Config File Issues
|
|
|
|
**Symptoms**: "Group not found" or "Host not found"
|
|
|
|
**Solutions**:
|
|
|
|
1. **Verify SSH config**:
|
|
```bash
|
|
cat ~/.ssh/config
|
|
# Check host aliases are correct
|
|
```
|
|
|
|
2. **Verify sshsync config**:
|
|
```bash
|
|
cat ~/.config/sshsync/config.yaml
|
|
# Check groups are defined
|
|
```
|
|
|
|
3. **Re-sync**:
|
|
```bash
|
|
sshsync sync
|
|
```
|
|
|
|
### Test Failures
|
|
|
|
**Symptoms**: Tests fail with errors
|
|
|
|
**Solutions**:
|
|
|
|
1. **Check dependencies**:
|
|
```bash
|
|
pip3 list | grep -E "sshsync|pyyaml"
|
|
```
|
|
|
|
2. **Check Python version**:
|
|
```bash
|
|
python3 --version
|
|
# Must be 3.10+
|
|
```
|
|
|
|
3. **Run tests individually**:
|
|
```bash
|
|
python3 tests/test_helpers.py
|
|
python3 tests/test_validation.py
|
|
python3 tests/test_integration.py
|
|
```
|
|
|
|
## Post-Installation
|
|
|
|
### Recommended Next Steps
|
|
|
|
1. **Create more groups** for better organization:
|
|
```bash
|
|
sshsync gadd staging
|
|
sshsync gadd backup-servers
|
|
```
|
|
|
|
2. **Test file operations**:
|
|
```
|
|
"Push test file to homelab machines (dry-run)"
|
|
```
|
|
|
|
3. **Set up automation**:
|
|
- Create scripts for common tasks
|
|
- Schedule backups
|
|
- Automate deployments
|
|
|
|
4. **Review documentation**:
|
|
- Read `references/sshsync-guide.md` for advanced sshsync usage
|
|
- Read `references/tailscale-integration.md` for Tailscale tips
|
|
|
|
### Security Checklist
|
|
|
|
- ✅ SSH keys are password-protected
|
|
- ✅ SSH config has correct permissions (600)
|
|
- ✅ Private keys have correct permissions (600)
|
|
- ✅ Tailscale ACLs configured (if using teams)
|
|
- ✅ Only necessary hosts have SSH access
|
|
- ✅ Regularly review connected devices in Tailscale
|
|
|
|
## Summary
|
|
|
|
You now have:
|
|
|
|
1. ✅ Tailscale installed and connected
|
|
2. ✅ sshsync installed and configured
|
|
3. ✅ SSH keys set up on all machines
|
|
4. ✅ SSH config with all hosts
|
|
5. ✅ sshsync groups organized
|
|
6. ✅ Agent installed in Claude Code
|
|
7. ✅ Tests passing
|
|
|
|
**Start using**:
|
|
|
|
```
|
|
"Which machines are online?"
|
|
"Run this on the least loaded machine"
|
|
"Push files to production servers"
|
|
"Deploy to staging then production"
|
|
```
|
|
|
|
For more examples, see README.md and SKILL.md.
|
|
|
|
## Support
|
|
|
|
If you encounter issues:
|
|
|
|
1. Check this troubleshooting section
|
|
2. Review references/ for detailed guides
|
|
3. Check DECISIONS.md for architecture rationale
|
|
4. Run tests to verify installation
|
|
|
|
Happy automating! 🚀
|