Skills ssh-deploy-skill
Universal SSH remote deployment tool - multi-server management, batch deployment, installation script templates with domestic mirror optimization. Supports remote installation of Git, Docker, MySQL, PostgreSQL, Nginx, Node.js, Redis, Python and more.
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/awamwang/ssh-deploy-skill" ~/.claude/skills/openclaw-skills-ssh-deploy-skill && rm -rf "$T"
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.openclaw/skills && cp -r "$T/skills/awamwang/ssh-deploy-skill" ~/.openclaw/skills/openclaw-skills-ssh-deploy-skill && rm -rf "$T"
skills/awamwang/ssh-deploy-skill/SKILL.mdSSH Deploy Skill
A universal SSH remote deployment tool for managing Linux servers with batch operations, file transfers, and templated software installations. Optimized for domestic network environments with built-in mirror configuration for Chinese mirrors (Aliyun, Tsinghua, etc.).
Quick Start
1. Initial Setup
cd /root/.openclaw/workspace/skills/ssh-deploy-skill # Auto setup (checks dependencies, creates config) bash scripts/setup.sh # Manual dependency install if auto fails pip3 install --user paramiko
2. Configure Servers (Two Methods)
Method A: Use inventory.json (Traditional)
Edit
~/.ssh-deploy/inventory.json or add servers via CLI:
python3 scripts/inventory.py add web-01 \ --host 192.168.1.101 \ --user root \ --ssh-key ~/.ssh/id_rsa \ --groups production,web \ --tags "aliyun"
Config location: All server configurations are saved in
~/.ssh-deploy/inventory.json.
Method B: Read Directly from ~/.ssh/config (New!)
If you already have Host entries in
~/.ssh/config, use them without any additional configuration:
# ~/.ssh/config example Host dy-c1 HostName 101.126.92.30 User root IdentityFile ~/.ssh/mypc_id_rsa Port 22 # Execute directly using host name python3 scripts/deploy.py exec dy-c1 "ls -la /opt"
The tool automatically parses
Host, HostName, Port, User, IdentityFile fields from your SSH config.
Note: Servers loaded from SSH config are read-only and not saved to inventory. To add groups/tags, import them:
.inventory.py add --from-ssh-config
3. Execute Remote Commands
# Single server python3 scripts/deploy.py exec web-01 "uptime && df -h" # Batch by group python3 scripts/deploy.py exec group:production "docker ps" # Batch by tag python3 scripts/deploy.py exec tag:aliyun "systemctl status nginx" # Sequential execution (avoid high load) python3 scripts/deploy.py exec group:large "apt update" --sequential
4. File Transfers
# Upload file python3 scripts/deploy.py upload web-01 ./nginx.conf /etc/nginx/nginx.conf # Batch upload to all group servers python3 scripts/deploy.py upload group:web ./config.json /opt/app/config.json # Download file python3 scripts/deploy.py download web-01 /var/log/nginx/access.log ./logs/
5. Use Templates for Software Installation
All templates in
templates/ come pre-configured with domestic mirrors.
# Install Docker (auto-configured with China mirrors) cat templates/install_docker.sh | python3 scripts/deploy.py exec tag:docker "bash -s" # Install MySQL (password via environment variable) MYSQL_ROOT_PASSWORD=YourPass123 cat templates/install_mysql.sh | \ python3 scripts/deploy.py exec db-01 "bash -s" # Base setup (system updates + mirrors) cat templates/base_setup.sh | python3 scripts/deploy.py exec group:all "bash -s"
📦 Installation Script Templates
| Template | Software | China Mirror | Env Vars |
|---|---|---|---|
| Base environment | ✅ | - |
| Git | ❌ | GIT_USER_NAME, GIT_USER_EMAIL |
| Docker CE +加速器 | ✅ | - |
| MySQL 8.0 | ✅ | MYSQL_ROOT_PASSWORD |
| PostgreSQL 15 | ✅ | PG_VERSION |
| Nginx | ❌ | - |
| Node.js | ✅ (npm) | NODE_VERSION |
| Redis | ❌ | - |
| Python | ✅ (pip) | PYTHON_VERSION |
Note: All added server configs are saved to
.~/.ssh-deploy/inventory.json
🎯 Core Features
Server Inventory Management (inventory.py
)
inventory.py# List all servers python3 scripts/inventory.py list # Filter by group python3 scripts/inventory.py list --group production # Filter by tag python3 scripts/inventory.py list --tag aliyun # Add server python3 scripts/inventory.py add SERVER_NAME \ --host IP_OR_HOSTNAME \ --port 22 \ --user USERNAME \ --ssh-key PATH_TO_KEY \ --groups GROUP1,GROUP2 \ --tags TAG1,TAG2 \ --desc "description"
Target Syntax (used in
deploy.py):
- Specific serverserver-name
- All servers in that groupgroup:groupname
- All servers with that tagtag:tagname
- All servers*
Remote Command Execution (deploy.py
)
deploy.py# Parallel batch (default) python3 scripts/deploy.py exec group:web "docker pull nginx" # Sequential (large batches or to avoid overload) python3 scripts/deploy.py exec group:large "apt upgrade -y" --sequential # Use environment variables export MYSQL_VERSION="8.0" cat templates/install_mysql.sh | python3 scripts/deploy.py exec db-01 "bash -s"
File Operations
# Upload (single) python3 scripts/deploy.py upload web-01 ./local.conf /etc/app/conf.d/conf.conf # Batch upload python3 scripts/deploy.py upload group:web ./nginx.conf /etc/nginx/nginx.conf # Download python3 scripts/deploy.py download web-01 /var/log/app.log ./logs/
🌏 Domestic Network Optimization
Mirror Configuration
This skill uses Aliyun mirrors by default and configures:
- Ubuntu/Debian →
mirrors.aliyun.com - CentOS/RHEL →
mirrors.aliyun.com - npm →
(Taobao)registry.npmmirror.com - pip →
mirrors.aliyun.com/pypi/simple - Docker → USTC, NetEase, Baidu mirrors
- Go →
goproxy.cn - Maven → Aliyun repository
Detailed config:
references/mirrors.md
One-Click Mirror Setup
# Configure system mirrors on all servers cat templates/base_setup.sh | python3 scripts/deploy.py exec group:all "bash -s" # Manual Docker mirror config (if needed) cat <<'EOF' | python3 scripts/deploy.py exec group:all "bash -s" cat > /etc/docker/daemon.json <<DOCKER { "registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://hub-mirror.c.163.com", "https://mirror.baidubce.com" ] } DOCKER systemctl restart docker EOF
🔒 Security Best Practices
-
SSH Key Management
- Use key auth, disable passwords
- Key permissions:
chmod 600 ~/.ssh/id_rsa - Different keys for different environments
-
Least Privilege
- Create dedicated deploy users (not root)
- Configure passwordless sudo (only necessary commands)
- Server
:sshd_config
,PermitRootLogin noPasswordAuthentication no
-
Sensitive Data
- Never store passwords in
inventory.json - Use environment variables for passwords (e.g.,
)MYSQL_ROOT_PASSWORD - Config file permissions
, owner640root:appgroup
- Never store passwords in
-
Audit
- Keep all deployment logs
- Record command, server, time, result
Full security guide:
references/best-practices.md
🐛 Troubleshooting
Quick Diagnostics
# 1. Network test ping <host> telnet <host> 22 # 2. Manual SSH test ssh -i ~/.ssh/id_rsa root@<host> "uptime" # 3. View connection details python3 scripts/deploy.py exec <server> "uptime" 2>&1 # 4. Verify key permissions ls -la ~/.ssh/id_rsa*
Common Issues
| Symptom | Solution |
|---|---|
| Connection refused/timeout | Check server status, SSH service, firewall/security group |
| Permission denied (publickey) | Check public key in server's , key perms 600 |
| sudo: a password is required | Configure passwordless sudo or use root user |
| Command not found | Use absolute path or ensure PATH includes command |
| Slow downloads in China | Run to configure mirrors, see |
Detailed troubleshooting:
references/troubleshooting.md
📊 Batch Operations Examples
Scenario 1: New Server Initialization
# 1. Add server to inventory python3 scripts/inventory.py add web-01 --host 1.2.3.101 --groups web --tags production # 2. Base setup (mirrors, tools) cat templates/base_setup.sh | python3 scripts/deploy.py exec web-01 "bash -s" # 3. Install core software cat templates/install_docker.sh | python3 scripts/deploy.py exec web-01 "bash -s" cat templates/install_nginx.sh | python3 scripts/deploy.py exec web-01 "bash -s" # 4. Upload app config python3 scripts/deploy.py upload web-01 ./app-config.json /opt/app/config.json # 5. Start application python3 scripts/deploy.py exec web-01 "docker-compose up -d"
Scenario 2: Rolling Updates Across Multiple Servers
# Canary release: update first batch cat deploy-v2.sh | python3 scripts/deploy.py exec tag:"canary" "bash -s" # Check monitoring metrics... # Full rollout cat deploy-v2.sh | python3 scripts/deploy.py exec tag:production "bash -s"
Scenario 3: Configuration Sync
# Sync config file to all Web servers python3 scripts/deploy.py upload group:web ./nginx.conf /etc/nginx/nginx.conf # Batch restart python3 scripts/deploy.py exec group:web "nginx -t && systemctl reload nginx"
Scenario 4: Health Checks & Monitoring
# Collect status from all servers python3 scripts/deploy.py exec "*" "uptime" > uptime-$(date +%F).log python3 scripts/deploy.py exec "*" "df -h" > disk-$(date +%F).log python3 scripts/deploy.py exec "*" "docker ps --format 'table {{.Names}}\t{{.Status}}'" > containers-$(date +%F).log
🔄 CI/CD Integration
GitLab CI Example
stages: - deploy deploy_production: stage: deploy script: - pip3 install --user paramiko - export TARGET="group:production" - cat deploy.sh | python3 skills/ssh-deploy-skill/scripts/deploy.py exec "$TARGET" "bash -s" only: - main
GitHub Actions Example
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install paramiko run: pip3 install paramiko - name: Deploy to servers run: | cat deploy.sh | python3 skills/ssh-deploy-skill/scripts/deploy.py exec "group:staging" "bash -s"
🛠️ Developer Guide
Adding New Installation Templates
- Create
file in.shtemplates/ - Use
and#!/bin/bashset -e - Detect OS type and adapt (see existing templates)
- Use env vars for parameters, never hardcode secrets
- Add domestic mirror config where applicable
Custom Script Structure
#!/bin/bash set -e echo "===== Installing XXX =====" # 1. Detect OS if [ -f /etc/debian_version ]; then OS="debian" elif [ -f /etc/redhat-release ]; then OS="redhat" else echo "Unsupported OS" exit 1 fi # 2. Configure domestic mirrors (if needed) # ... # 3. Install software if [ "$OS" = "debian" ]; then apt-get update apt-get install -y xxx elif [ "$OS" = "redhat" ]; then yum install -y xxx fi # 4. Start service systemctl start xxx systemctl enable xxx echo "XXX installation complete!"
Using Python API Directly
from inventory import Inventory, Server from deploy import SSHDeployer # Load inventory inv = Inventory() server = inv.get_server("web-01") # Create deployer deployer = SSHDeployer() # Execute command result = deployer.execute(server, "docker ps") print(result.success, result.output) # Upload file res = deployer.upload_file(server, "./local.conf", "/etc/conf.d/local.conf") deployer.close()
📚 Additional Documentation
Detailed documentation (some in Chinese):
- Complete usage guide with API referenceREADME.md
- Full Chinese manualREADME.zh-CN.md
- Domestic mirror configuration detailsreferences/mirrors.md
- Best practices and code examplesreferences/best-practices.md
- Complete troubleshooting handbookreferences/troubleshooting.md
🤝 Contributing
Issues and Pull Requests are welcome!
📄 License
MIT License