SSH Command & Port Forwarding
Actions🛠️ SSH Remote commands and Port forwarding with extensive configuration options. Supports Windows, macOS, Linux
v1.0.1
LatestBy lexbritvin
Tags
(2)A powerful GitHub Action for executing SSH commands and establishing secure port forwarding tunnels with support for jump hosts, dynamic port allocation, and comprehensive authentication methods.
- 🚀 Remote Command Execution - Execute commands on remote servers
- 🔗 Port Forwarding - Local and remote port forwarding with dynamic allocation
- 🦘 Jump Host Support - Multi-hop SSH connections through bastion hosts
- 🔐 Multiple Authentication - Private keys, passwords, and SSH agent support
- 🌐 Cross-Platform - Works on Linux, macOS, and Windows runners
- 🛡️ Security First - Known hosts verification and secure key handling
- 📊 Comprehensive Logging - Detailed output for debugging and monitoring
- name: Deploy Application
uses: lexbritvin/ssh-action@v1
with:
host: your-server.com
username: deploy
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
command: |
cd /var/www/app
git pull origin main
npm install --production
pm2 restart app
- name: Forward Database Port
uses: lexbritvin/ssh-action@v1
with:
host: database-server.com
username: dbadmin
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
local-forwards: "5432:localhost:5432"
- name: Expose Local Service
uses: lexbritvin/ssh-action@v1
with:
host: tunnel.example.com
username: tunnel
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
remote-forwards: "0:localhost:3000"
name: Database Migration
on: [ push ]
jobs:
migrate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Database Tunnels
uses: lexbritvin/ssh-action@v1
with:
host: production-bastion.company.com
username: devops
private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
local-forwards: |
5432:postgres-primary.internal:5432,
6379:redis-cluster.internal:6379,
3306:mysql-replica.internal:3306
timeout: 60
keep-alive: 30
- name: Run Database Migration
run: |
# Now you can connect to localhost:5432, localhost:6379, localhost:3306
npm run migrate:production
- name: Access Internal Server via Bastion
uses: lexbritvin/ssh-action@v1
with:
host: internal-server.private
username: admin
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
jump-hosts: "bastion1.company.com:22,bastion2.company.com:2222"
command: "systemctl status nginx"
name: Production Deployment
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy to Production
uses: lexbritvin/ssh-action@v1
with:
host: ${{ secrets.PRODUCTION_HOST }}
username: ${{ secrets.PRODUCTION_USER }}
private-key: ${{ secrets.PRODUCTION_SSH_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }}
timeout: 120
command: |
set -e
echo "🚀 Starting deployment..."
# Backup current version
sudo cp -r /var/www/app /var/www/app.backup.$(date +%Y%m%d_%H%M%S)
# ...
echo "✅ Deployment completed successfully!"
post-command: |
echo "🧹 Cleaning up old backups..."
find /var/www -name "app.backup.*" -mtime +7 -delete
echo "✅ Cleanup completed"
Parameter | Description | Required | Default |
---|---|---|---|
host |
Target SSH host | Yes | - |
port |
SSH port | No | 22 |
username |
SSH username | No | Current user |
Parameter | Description | Required | Default |
---|---|---|---|
private-key |
SSH private key content | No | - |
private-key-path |
Path to SSH private key file | No | - |
password |
SSH password (not recommended) | No | - |
known-hosts |
SSH known_hosts content | No | - |
Parameter | Description | Required | Default |
---|---|---|---|
local-forwards |
Local port forwards (-L ) |
No | - |
remote-forwards |
Remote port forwards (-R ) |
No | - |
Parameter | Description | Required | Default |
---|---|---|---|
jump-hosts |
Comma-separated jump hosts | No | - |
extra-flags |
Additional SSH flags | No | - |
command |
Command to execute | No | - |
post-command |
Cleanup command | No | - |
timeout |
Connection timeout (seconds) | No | 30 |
keep-alive |
Keep-alive interval (seconds) | No | 60 |
dry-run |
Show command without executing | No | false |
Output | Description |
---|---|
pid |
Process ID of the SSH tunnel |
allocated-host |
Public host for remote forward (dynamic allocation) |
allocated-port |
Allocated port for remote forward (dynamic allocation) |
Forward local ports to remote destinations:
local-forwards: "8080:web-server:80" # localhost:8080 → web-server:80
local-forwards: "127.0.0.1:8080:database:5432" # 127.0.0.1:8080 → database:5432
local-forwards: "3000:localhost:3000,8080:nginx:80" # Multiple forwards
Forward remote ports to local destinations:
remote-forwards: "8080:localhost:3000" # remote:8080 → localhost:3000
remote-forwards: "0:localhost:3000" # Dynamic port allocation
remote-forwards: "0.0.0.0:9000:localhost:9000" # Bind to all interfaces
# Store your private key in GitHub Secrets
- name: Secure SSH Connection
uses: lexbritvin/ssh-action@v1
with:
host: secure-server.com
username: deploy
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
known-hosts: ${{ secrets.KNOWN_HOSTS }}
Enable detailed logging and disable hosts checking for troubleshooting:
- name: Debug SSH Connection
uses: lexbritvin/ssh-action@v1
with:
host: problematic-server.com
username: debug-user
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
# Do not check a server key and use verbose SSH output
extra-flags: "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -vvv"
dry-run: true # Test command generation
- 📖 SSH Port Forwarding Guide
- 🔐 SSH Key Management
- 🛡️ GitHub Secrets Management
- 🌐 SSH Jump Host Configuration
This project is licensed under the MIT License - see the LICENSE file for details.
⭐ Star this repo if you find it useful!
Made with ❤️ for the GitHub Actions community
SSH Command & Port Forwarding is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.