Files
gh-human-frontier-labs-inc-…/INSTALLATION.md
2025-11-29 18:47:40 +08:00

13 KiB

Installation Guide

Complete step-by-step tutorial for setting up Tailscale SSH Sync Agent.

Table of Contents

  1. Prerequisites
  2. Step 1: Install Tailscale
  3. Step 2: Install sshsync
  4. Step 3: Configure SSH
  5. Step 4: Configure sshsync Groups
  6. Step 5: Install Agent
  7. Step 6: Test Installation
  8. 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:

python3 --version
# Should show: Python 3.10.x or higher

Check pip:

pip3 --version
# Should show: pip xx.x.x from ...

Step 1: Install Tailscale

Tailscale provides secure networking between your machines.

macOS

# 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)

# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Start and authenticate
sudo tailscale up

# Follow authentication link

Linux (Fedora/RHEL)

# 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

# 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.

# Install via pip
pip3 install sshsync

# Or use pipx for isolated installation
pipx install sshsync

Verify Installation

# Check version
sshsync --version

# Should show: sshsync, version x.x.x

Common Installation Issues

Issue: pip3: command not found

Solution:

# 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:

# 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)

# 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:

# 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):

# 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

# 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:

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

# 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:

# 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

# 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

# View generated config
cat ~/.config/sshsync/config.yaml

Expected output:

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

# 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

cd /path/to/tailscale-sshsync-agent

Step 5.2: Verify Agent Structure

# 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

# 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

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:

    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:

    ssh-add -l
    # Should list your SSH key
    

    If not listed:

    ssh-add ~/.ssh/id_ed25519
    
  2. Test SSH directly:

    ssh -v hostname
    # -v shows verbose debug info
    
  3. Verify authorized_keys on remote:

    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:

    tailscale status
    
  2. Restart Tailscale:

    # macOS
    brew services restart tailscale
    
    # Linux
    sudo systemctl restart tailscaled
    
  3. Re-authenticate:

    sudo tailscale up
    

sshsync Errors

Symptoms: "sshsync: command not found"

Solutions:

  1. Reinstall sshsync:

    pip3 install --upgrade sshsync
    
  2. Check PATH:

    which sshsync
    # Should show path to sshsync
    

    If not found, add to PATH:

    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:

    cat ~/.ssh/config
    # Check host aliases are correct
    
  2. Verify sshsync config:

    cat ~/.config/sshsync/config.yaml
    # Check groups are defined
    
  3. Re-sync:

    sshsync sync
    

Test Failures

Symptoms: Tests fail with errors

Solutions:

  1. Check dependencies:

    pip3 list | grep -E "sshsync|pyyaml"
    
  2. Check Python version:

    python3 --version
    # Must be 3.10+
    
  3. Run tests individually:

    python3 tests/test_helpers.py
    python3 tests/test_validation.py
    python3 tests/test_integration.py
    

Post-Installation

  1. Create more groups for better organization:

    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! 🚀