254 lines
6.4 KiB
Markdown
254 lines
6.4 KiB
Markdown
# Setup SSH Client
|
|
|
|
A composite GitHub Action that configures SSH client for running remote commands securely.
|
|
|
|
## Features
|
|
|
|
- 🔐 Secure SSH key management
|
|
- 🔧 Automatic SSH configuration
|
|
- 🔑 Known hosts setup with ssh-keyscan fallback
|
|
- ✅ Connection validation
|
|
- 🎯 Simple, reusable configuration
|
|
- 🚀 Custom shell wrapper for seamless remote command execution
|
|
|
|
## Usage
|
|
|
|
### Basic Example with Custom Shell
|
|
|
|
```yaml
|
|
name: Deploy Application
|
|
on: [push]
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup SSH
|
|
uses: your-username/setup-ssh-client@v1
|
|
with:
|
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
ssh-host: ${{ secrets.SSH_HOST }}
|
|
ssh-user: ${{ secrets.SSH_USER }}
|
|
|
|
- name: Run remote commands with custom shell
|
|
shell: ssh-remote
|
|
run: |
|
|
cd /var/www
|
|
git pull origin main
|
|
npm install
|
|
systemctl restart myapp
|
|
|
|
- name: Or use direct SSH commands
|
|
run: |
|
|
ssh github-action-host "uptime"
|
|
ssh github-action-host "df -h"
|
|
```
|
|
|
|
### Basic Example (Direct SSH)
|
|
|
|
```yaml
|
|
name: Deploy Application
|
|
on: [push]
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup SSH
|
|
uses: your-username/setup-ssh-client@v1
|
|
with:
|
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
ssh-host: ${{ secrets.SSH_HOST }}
|
|
ssh-user: ${{ secrets.SSH_USER }}
|
|
|
|
- name: Run remote commands
|
|
run: |
|
|
ssh github-action-host "cd /var/www && git pull"
|
|
ssh github-action-host "systemctl restart myapp"
|
|
```
|
|
|
|
### Advanced Example
|
|
|
|
```yaml
|
|
- name: Setup SSH with custom configuration
|
|
uses: your-username/setup-ssh-client@v1
|
|
with:
|
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
ssh-host: example.com
|
|
ssh-user: deploy
|
|
ssh-port: '2222'
|
|
strict-host-key-checking: 'yes'
|
|
ssh-known-hosts: |
|
|
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...
|
|
|
|
- name: Deploy application
|
|
run: |
|
|
ssh github-action-host "cd /var/www/app && ./deploy.sh"
|
|
```
|
|
|
|
### Using Different Remote Shells
|
|
|
|
```yaml
|
|
- name: Setup SSH with zsh
|
|
uses: your-username/setup-ssh-client@v1
|
|
with:
|
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
ssh-host: example.com
|
|
ssh-user: deploy
|
|
remote-shell: 'zsh'
|
|
|
|
- name: Run commands in remote zsh
|
|
shell: ssh-remote
|
|
run: |
|
|
source ~/.zshrc
|
|
echo "Running in zsh: $SHELL"
|
|
```
|
|
|
|
### Disable Shell Wrapper (SSH Direct Only)
|
|
|
|
```yaml
|
|
- name: Setup SSH without shell wrapper
|
|
uses: your-username/setup-ssh-client@v1
|
|
with:
|
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
ssh-host: example.com
|
|
ssh-user: deploy
|
|
use-shell-wrapper: 'false'
|
|
|
|
- name: Use direct SSH commands
|
|
run: |
|
|
ssh github-action-host "command1"
|
|
ssh github-action-host "command2"
|
|
```
|
|
|
|
## Inputs
|
|
|
|
| Input | Description | Required | Default |
|
|
|-------|-------------|----------|---------|
|
|
| `ssh-private-key` | SSH private key for authentication | Yes | - |
|
|
| `ssh-host` | SSH host to connect to | Yes | - |
|
|
| `ssh-user` | SSH username | Yes | - |
|
|
| `ssh-port` | SSH port | No | `22` |
|
|
| `ssh-known-hosts` | Known hosts content (uses ssh-keyscan if not provided) | No | `''` |
|
|
| `strict-host-key-checking` | Enable strict host key checking (`yes`/`no`/`accept-new`) | No | `accept-new` |
|
|
| `use-shell-wrapper` | Create shell wrapper for remote execution (enables `shell: ssh-remote`) | No | `true` |
|
|
| `remote-shell` | Shell to use on remote server (`bash`, `sh`, `zsh`, etc.) | No | `bash` |
|
|
|
|
## Outputs
|
|
|
|
| Output | Description |
|
|
|--------|-------------|
|
|
| `ssh-config-path` | Path to the SSH config file |
|
|
| `ssh-key-path` | Path to the SSH private key |
|
|
| `shell-wrapper-path` | Path to the SSH remote shell wrapper script |
|
|
|
|
## Remote Command Execution
|
|
|
|
This action provides two ways to execute commands remotely:
|
|
|
|
### 1. Custom Shell Wrapper (Recommended)
|
|
|
|
Use `shell: ssh-remote` in any step to execute the entire script on the remote server:
|
|
|
|
```yaml
|
|
- name: Deploy application
|
|
shell: ssh-remote
|
|
run: |
|
|
cd /var/www/myapp
|
|
git pull origin main
|
|
npm install --production
|
|
pm2 restart myapp
|
|
```
|
|
|
|
**Benefits:**
|
|
- Natural multi-line script syntax
|
|
- Automatic error handling with `set -e`
|
|
- Works like a local shell
|
|
- No need to wrap commands in SSH
|
|
|
|
### 2. SSH Host Alias (Direct)
|
|
|
|
Use the `github-action-host` alias for direct SSH commands:
|
|
|
|
```yaml
|
|
- name: Run single commands
|
|
run: |
|
|
ssh github-action-host "uptime"
|
|
ssh github-action-host "df -h"
|
|
```
|
|
|
|
This eliminates the need to specify the host, user, port, and key path in every SSH command.
|
|
|
|
## Security Best Practices
|
|
|
|
### Generating SSH Keys
|
|
|
|
```bash
|
|
# Generate a dedicated SSH key pair for GitHub Actions
|
|
ssh-keygen -t ed25519 -C "github-actions" -f github_actions_key
|
|
|
|
# Or use RSA if ed25519 is not supported
|
|
ssh-keygen -t rsa -b 4096 -C "github-actions" -f github_actions_key
|
|
```
|
|
|
|
### Setting up Secrets
|
|
|
|
1. Copy your private key content:
|
|
```bash
|
|
cat github_actions_key
|
|
```
|
|
|
|
2. Add it to GitHub Secrets:
|
|
- Go to your repository → Settings → Secrets and variables → Actions
|
|
- Click "New repository secret"
|
|
- Name: `SSH_PRIVATE_KEY`
|
|
- Value: Paste the entire private key content
|
|
|
|
3. Add the public key to your server:
|
|
```bash
|
|
cat github_actions_key.pub >> ~/.ssh/authorized_keys
|
|
```
|
|
|
|
### Getting Known Hosts
|
|
|
|
To pre-populate known hosts (recommended for security):
|
|
|
|
```bash
|
|
ssh-keyscan -H your-server.com
|
|
```
|
|
|
|
Add the output to a GitHub secret named `SSH_KNOWN_HOSTS`.
|
|
|
|
## Troubleshooting
|
|
|
|
### Connection Timeout
|
|
|
|
If the connection test fails with a timeout:
|
|
- Verify the host and port are correct
|
|
- Check firewall rules allow connections from GitHub Actions IPs
|
|
- Ensure SSH service is running on the remote server
|
|
|
|
### Permission Denied
|
|
|
|
If you get "Permission denied":
|
|
- Verify the public key is in `~/.ssh/authorized_keys` on the remote server
|
|
- Check the private key format is correct (should include header/footer)
|
|
- Ensure the SSH user has appropriate permissions
|
|
|
|
### Host Key Verification Failed
|
|
|
|
If you encounter host key verification issues:
|
|
- Set `strict-host-key-checking: 'no'` (not recommended for production)
|
|
- Or provide `ssh-known-hosts` input with the correct host key
|
|
|
|
## License
|
|
|
|
MIT License - see [LICENSE](LICENSE) file for details
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please feel free to submit a Pull Request.
|