A robust GitHub Action for uploading a local directory to a remote server via SSH2 SFTP protocol. Built with TypeScript and comprehensive error handling.
- π TypeScript - Type-safe with comprehensive error handling
- π Multiple Auth Methods - Password, private key, or SSH agent authentication
- π Directory Upload - Upload entire directories with progress tracking
- πΎ Backup Support - Optional remote directory backup before upload
- π Retry Logic - Configurable connection retries with exponential backoff
- π Detailed Outputs - Track uploaded files count and operation status
- β‘ Concurrent Operations - Configurable promise limit for optimal performance
- π‘οΈ Security First - No secrets logged, secure connection handling
name: Deploy to Server
on:
  push:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Upload to Server
        uses: 2ue/ssh2-to-remote-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          password: ${{ secrets.SERVER_PASSWORD }}
          local_dir: './dist'
          remote_base_dir: '/var/www/html'      - name: Upload with Backup
        uses: 2ue/ssh2-to-remote-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          port: 2222
          username: ${{ secrets.SERVER_USERNAME }}
          privateKey: ${{ secrets.SSH_PRIVATE_KEY }}
          passphrase: ${{ secrets.SSH_PASSPHRASE }}
          local_dir: './build'
          remote_base_dir: '/home/user/app'
          remote_bak_path: '/home/user/backups'
          retries: 3
          retry_factor: 2
          readyTimeout: 30000
          debug: true| Input | Description | Example | 
|---|---|---|
| host | Remote server hostname or IP | example.com | 
| username | SSH username | ubuntu | 
| local_dir | Local directory to upload | ./dist | 
| remote_base_dir | Remote destination directory | /var/www/html | 
| Input | Description | Example | 
|---|---|---|
| password | SSH password | ${{ secrets.PASSWORD }} | 
| privateKey | SSH private key content | ${{ secrets.SSH_KEY }} | 
| agent | Path to SSH agent socket | /tmp/ssh-agent.sock | 
| Input | Description | Default | Example | 
|---|---|---|---|
| port | SSH port | 22 | 2222 | 
| passphrase | Private key passphrase | ${{ secrets.PASSPHRASE }} | |
| remote_bak_path | Backup directory path | /backups | |
| forceIPv4 | Force IPv4 connection | false | true | 
| forceIPv6 | Force IPv6 connection | false | true | 
| readyTimeout | SSH handshake timeout (ms) | 20000 | 30000 | 
| strictVendor | Strict server vendor check | false | true | 
| debug | Enable debug logging | false | true | 
| retries | Connection retry attempts | 1 | 3 | 
| retry_factor | Retry delay multiplier | 2 | 1.5 | 
| retry_minTimeout | Min retry delay (ms) | 1000 | 2000 | 
| promiseLimit | Concurrent operation limit | 10 | 5 | 
| Output | Description | Example | 
|---|---|---|
| uploaded_files | Number of files uploaded | 42 | 
| success | Upload operation status | true | 
| error | Error message if failed | Connection timeout | 
Store sensitive information as GitHub repository secrets:
- Go to your repository β Settings β Secrets and variables β Actions
- Add the following secrets:
- SERVER_HOST- Your server hostname
- SERVER_USERNAME- SSH username
- SERVER_PASSWORD- SSH password (if using password auth)
- SSH_PRIVATE_KEY- SSH private key content (if using key auth)
- SSH_PASSPHRASE- Private key passphrase (if needed)
 
For better security, use SSH key authentication:
# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -C "github-actions@your-repo"
# Copy public key to server
ssh-copy-id -i ~/.ssh/id_rsa.pub user@server
# Add private key content to GitHub secrets as SSH_PRIVATE_KEY
cat ~/.ssh/id_rsaname: Deploy React App
on:
  push:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          
      - name: Install and Build
        run: |
          npm ci
          npm run build
          
      - name: Deploy to Server
        uses: 2ue/ssh2-to-remote-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USERNAME }}
          privateKey: ${{ secrets.SSH_PRIVATE_KEY }}
          local_dir: './build'
          remote_base_dir: '/var/www/html'
          remote_bak_path: '/var/backups/www'
          
      - name: Check Deployment
        if: success()
        run: echo "β
 Deployed ${{ steps.deploy.outputs.uploaded_files }} files successfully!"name: Multi-Environment Deploy
on:
  push:
    branches: [ main, staging ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: 
          - name: staging
            branch: staging
            host: staging.example.com
            path: /var/www/staging
          - name: production
            branch: main
            host: example.com
            path: /var/www/html
            
    steps:
      - uses: actions/checkout@v4
        if: github.ref == format('refs/heads/{0}', matrix.environment.branch)
        
      - name: Deploy to ${{ matrix.environment.name }}
        if: github.ref == format('refs/heads/{0}', matrix.environment.branch)
        uses: 2ue/ssh2-to-remote-action@v1
        with:
          host: ${{ matrix.environment.host }}
          username: ${{ secrets.SERVER_USERNAME }}
          privateKey: ${{ secrets.SSH_PRIVATE_KEY }}
          local_dir: './dist'
          remote_base_dir: ${{ matrix.environment.path }}
          remote_bak_path: '/backups/${{ matrix.environment.name }}'
          retries: 3
          debug: true- Node.js 20+
- TypeScript
- Jest for testing
# Clone repository
git clone https://github.com/2ue/ssh2-to-remote-action.git
cd ssh2-to-remote-action
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run tests
npm test
# Run all checks
npm run allsrc/
βββ config/          # Input validation and processing
βββ ssh/             # SSH connection management
βββ upload/          # File upload logic
βββ types/           # TypeScript type definitions
βββ main.ts          # Main action logic
βββ index.ts         # Entry point
__tests__/           # Test files
dist/                # Compiled output
- Fork the repository
- Create a feature branch: git checkout -b feature/amazing-feature
- Make your changes and add tests
- Run the test suite: npm run all
- Commit your changes: git commit -m 'Add amazing feature'
- Push to the branch: git push origin feature/amazing-feature
- Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with ssh2-sftp-client
- Powered by GitHub Actions
- TypeScript support via @actions/core
- π Report Issues
- π‘ Request Features
- π Documentation
Made with β€οΈ for the GitHub Actions community