| name | remote-server-guide |
| description | Guide for connecting to remote servers via SSH, managing containers, and executing commands remotely. Covers SSH connection setup with multiple authentication methods (SSH key, sshpass, Paramiko, Fabric, tmux interactive), Docker container connection and command execution, file transfer, and troubleshooting. Use this skill whenever users need to: (1) Connect to a remote server or VPS via SSH, (2) Execute commands on remote machines, (3) Transfer files to/from remote servers, (4) Connect to Docker containers on remote hosts, (5) Set up SSH password authentication tools. Even if the user just says 'help me run something on my server' or 'connect to my machine', this skill applies. |
Remote Server Guide
A workflow for connecting to remote servers, executing commands, and managing containers over SSH. This skill is tool-agnostic — it helps you pick the right SSH tool for the job and walks through the full lifecycle from connection to cleanup.
When to Use This Skill
- User needs to connect to a remote server (cloud VM, on-prem server, dev machine, etc.)
- User wants to run commands on a remote host
- User needs to connect to a Docker container on a remote server
- User wants to transfer files to/from a remote server
- User is having trouble with SSH authentication
Authentication Methods
| Method | Security | Convenience | Best For |
|---|
| SSH Key | Highest | High | Production, frequent use |
| tmux (interactive) | High (password never exposed to AI) | Medium | One-time access, security-conscious users |
| sshpass | Medium (password in command) | High | Quick scripts, trusted environment |
| paramiko/fabric | Medium | Medium | Python automation |
Workflow
Phase 1: Gather Connection Details
Before connecting, collect from the user:
- Host address (IP or hostname)
- SSH port (default: 22)
- Username (e.g., root, ubuntu, user)
- Authentication method:
- SSH key (recommended)
- Password (requires tool selection — see Phase 2)
- Jump host (optional, for bastion/proxy setups)
Phase 2: Set Up Authentication
SSH Key (preferred)
ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -i <key-path> <user>@<host> -p <port> "echo 'Connection successful'"
Password Authentication
If the user needs password auth, first detect available tools:
which sshpass >/dev/null 2>&1 && echo "sshpass: available" || echo "sshpass: not found"
python3 -c "import paramiko" 2>/dev/null && echo "paramiko: available" || echo "paramiko: not found"
python3 -c "import fabric" 2>/dev/null && echo "fabric: available" || echo "fabric: not found"
which tmux >/dev/null 2>&1 && echo "tmux: available" || echo "tmux: not found"
If the user is concerned about password security, always recommend tmux interactive — the password is typed by the user directly and never seen by the AI.
Tool selection guidance:
| Scenario | Recommended Tool | Reason |
|---|
| Security-conscious user | tmux | Password never exposed to AI |
| One-time access | tmux | No credential storage needed |
| Quick shell script | sshpass | Simple, no dependencies |
| Python application | paramiko | Full control, lower level |
| Deployment automation | fabric | High-level API, cleaner code |
| Need SFTP | paramiko or fabric | Built-in support |
| Interactive terminal | tmux or sshpass | Native TTY support |
If no tools are available, offer to install one:
sudo apt-get install -y tmux
sudo apt-get install -y sshpass
pip install paramiko
pip install fabric
Phase 3: Test Connection
Verify the connection works before proceeding.
sshpass:
sshpass -p '<password>' ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no <user>@<host> -p <port> "echo 'Connection successful'"
tmux (interactive):
tmux new-session -d -s remote_session "ssh -o StrictHostKeyChecking=no <user>@<host> -p <port>"
tmux capture-pane -t remote_session -p
paramiko:
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname='<host>', port=<port>, username='<user>', password='<password>')
print('Connection successful')
client.close()
fabric:
from fabric import Connection
conn = Connection(host='<host>', user='<user>', connect_kwargs={'password': '<password>'})
conn.run('echo "Connection successful"', hide=True)
conn.close()
If connection fails, troubleshoot:
- Check host address and port
- Verify credentials
- Check network/firewall/VPN
- Verify jump host configuration (if used)
Phase 4: Choose Execution Environment
Ask the user where commands will run:
- Directly on host — most common, no extra setup
- Inside an existing Docker container — connect to a running container
- Inside a new Docker container — create a container first (for specialized workloads, consider hardware-specific skills like
npu-docker-launcher for NPU servers)
Connecting to an Existing Container
Important: tmux vs other tools behave very differently for container work.
tmux (persistent session): Enter the container shell once, then send all subsequent commands directly — they execute inside the container automatically. The session maintains state (working directory, environment variables, shell context).
tmux send-keys -t remote_session "docker ps" Enter
tmux capture-pane -t remote_session -p
tmux send-keys -t remote_session "docker exec -it <container-name> bash" Enter
tmux send-keys -t remote_session "cd /workspace" Enter
tmux send-keys -t remote_session "python inference.py" Enter
tmux send-keys -t remote_session "cat result.txt" Enter
tmux capture-pane -t remote_session -p
tmux send-keys -t remote_session "exit" Enter
Other tools (stateless): Each command is a separate SSH connection with no shared state. You must prefix every command with docker exec:
ssh <user>@<host> "docker exec <container-name> ls /workspace"
ssh <user>@<host> "docker exec <container-name> python inference.py"
ssh <user>@<host> "docker exec <container-name> cat result.txt"
Phase 5: Execute Commands
Use the selected SSH tool consistently for all operations.
Single Command
tmux: Since tmux maintains a persistent shell session, just send the command directly. If you previously entered a container, the command runs inside the container.
tmux send-keys -t remote_session "<command>" Enter
tmux capture-pane -t remote_session -p
Other tools (stateless, each command is independent):
| Tool | On host | In container |
|---|
| SSH key | ssh -i <key> <user>@<host> "<command>" | ssh -i <key> <user>@<host> "docker exec <container> <command>" |
| sshpass | sshpass -p '<pwd>' ssh <user>@<host> "<command>" | sshpass -p '<pwd>' ssh <user>@<host> "docker exec <container> <command>" |
| paramiko | client.exec_command("<command>") | client.exec_command("docker exec <container> <command>") |
| fabric | conn.run("<command>") | conn.run("docker exec <container> <command>") |
File Transfer
| Tool | Upload | Download |
|---|
| scp | scp <local> <user>@<host>:<remote> | scp <user>@<host>:<remote> <local> |
| sshpass+scp | sshpass -p '<pwd>' scp <local> <user>@<host>:<remote> | sshpass -p '<pwd>' scp <user>@<host>:<remote> <local> |
| paramiko | sftp.put('local', 'remote') | sftp.get('remote', 'local') |
| fabric | conn.put('local', 'remote/') | conn.get('remote', 'local') |
Multi-Step Script
For complex operations, upload a script and execute it:
scp setup.sh <user>@<host>:/tmp/
ssh <user>@<host> "bash /tmp/setup.sh"
ssh <user>@<host> "rm /tmp/setup.sh"
Phase 6: Cleanup
When done, clean up resources:
- Close SSH connections (
client.close(), conn.close())
- Kill tmux sessions (
tmux kill-session -t remote_session)
- Stop/remove temporary containers if applicable
Operations Reference
tmux (Interactive)
tmux new-session -d -s remote_session "ssh -o StrictHostKeyChecking=no <user>@<host> -p <port>"
tmux send-keys -t remote_session "<command>" Enter
tmux capture-pane -t remote_session -p
tmux kill-session -t remote_session
sshpass
sshpass -p '<password>' ssh <user>@<host> "<command>"
sshpass -p '<password>' scp <local> <user>@<host>:<remote>
sshpass -p '<password>' ssh <user>@<host> "docker exec <container> <command>"
paramiko
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname='<host>', username='<user>', password='<password>')
stdin, stdout, stderr = client.exec_command('<command>')
print(stdout.read().decode())
sftp = client.open_sftp()
sftp.put('local.txt', '/remote/path/remote.txt')
sftp.get('/remote/file.txt', 'local.txt')
client.close()
fabric
from fabric import Connection
conn = Connection(host='<host>', user='<user>',
connect_kwargs={'password': '<password>'})
result = conn.run('<command>', hide=True)
print(result.stdout)
conn.put('local.txt', '/remote/path/')
conn.get('/remote/file.txt', 'local.txt')
conn.close()
Error Handling
| Error | Cause | Solution |
|---|
| Connection refused | SSH not running | Check SSH service on remote |
| Permission denied | Wrong credentials | Verify username/password/key |
| Host key verification failed | First connection | Add -o StrictHostKeyChecking=no |
| Network unreachable | Network issue | Check firewall, VPN |
| Tool not found | Not installed | Run installation command |
| Container not found | Wrong name | docker ps -a to list all |
Security Best Practices
- Prefer SSH keys over passwords when possible
- Avoid hardcoding passwords — use environment variables or
SSHPASS env var
- Restrict key permissions:
chmod 600 ~/.ssh/id_rsa
- Use tmux method if you don't want the AI to handle your password
- Clean up temporary containers and sessions when done
Detailed Reference Files
For in-depth usage of each tool, consult: