๐Ÿš€ SCP for GitHub Actions

April 27, 2025 ยท View on GitHub

็น้ซ”ไธญๆ–‡ | ็ฎ€ไฝ“ไธญๆ–‡

GitHub Action for copying files and artifacts via SSH.

v1 version lint and test

Note: Only supports Linux docker containers.


โœจ Features

  • โœ… Copy files and artifacts to one or multiple remote servers via SSH
  • โœ… Supports both SSH key and password authentication
  • โœ… Full SSH Proxy (jump host) support
  • โœ… Handles Linux โ†” Windows path conversion
  • โœ… Integrates with GitHub Artifacts workflow
  • โœ… Incremental and differential file transfer
  • โœ… Rich configuration options for advanced use cases

๐Ÿ“ฆ Table of Contents


๐Ÿš€ Quick Start

Copy files and artifacts via SSH in your GitHub Actions workflow:

name: scp files
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Copy files via SSH
        uses: appleboy/scp-action@v1
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          source: "tests/a.txt,tests/b.txt"
          target: your_server_target_folder_path

โš™๏ธ Configuration

๐Ÿ”Œ Connection Settings

VariableDescriptionDefaultRequired
hostRemote host(s), comma-separated for multiple-โœ“
portSSH port22
usernameSSH username-โœ“
passwordSSH password (prefer SSH key for security)-
keySSH private key content-
key_pathPath to SSH private key file-
passphrasePassphrase for SSH private key-
fingerprintSHA256 fingerprint for host key verification-
protocolIP protocol: 'tcp', 'tcp4', or 'tcp6'tcp
timeoutSSH connection timeout30s
command_timeoutSCP command timeout10m

๐Ÿ“ File Transfer Settings

VariableDescriptionDefaultSecurity Note
sourceLocal files/directories to transfer (comma-separated)-Use explicit paths
targetTarget directory on remote server (must be a directory)-Avoid root directories
rmRemove target directory before upload-Use with caution
strip_componentsRemove leading path elements when extracting-
overwriteOverwrite existing files with tar-
tar_dereferenceFollow symlinks with tar-
tar_tmp_pathTemp path for tar file on destination-
tar_execPath to tar executable on destinationtar
debugEnable debug output-
curl_insecureUse --insecure with curlfalseNot recommended
capture_stdoutCapture command stdout as action outputfalse
versionVersion of drone-scp to use-

๐ŸŒ Proxy Settings

VariableDescriptionDefaultRequired
proxy_hostSSH proxy host-
proxy_portSSH proxy port22
proxy_usernameSSH proxy username-
proxy_passwordSSH proxy password-
proxy_keySSH proxy private key content-
proxy_key_pathPath to SSH proxy private key file-
proxy_passphrasePassphrase for SSH proxy private key-
proxy_fingerprintSHA256 fingerprint for proxy host-
proxy_use_insecure_cipherEnable less secure ciphers for proxy-
proxy_timeoutSSH proxy connection timeout30s

๐Ÿ›ก๏ธ Best Practices & Security

  • Prefer SSH key authentication over passwords for better security.
  • Store all sensitive values (host, username, password, key) in GitHub Secrets.
  • Regularly rotate deployment keys (suggested every 90 days).
  • Restrict write permissions on the target server directory.
  • Enable host key fingerprint verification to prevent MITM attacks.
  • Avoid using root as the SSH user.

๐Ÿ–ฅ๏ธ Cross-Platform Notes

ScenarioLinux ServerWindows Server
Path Format/path/to/dir/c/path/to/dir
Required SettingNonetar_dereference: true
PermissionsPreservedMay require manual ACL
Shellbash (default)Git Bash via OpenSSH

๐Ÿšฉ Important:
When copying to Windows servers:

  • Install Git for Windows and set OpenSSH default shell to Git Bash
  • Use Unix-style target paths (e.g., /c/Users/...)
  • Enable tar_dereference for symlink handling

๐Ÿ’ก Usage Examples

๐Ÿงฉ Scenario Guide


Example 1: Basic SSH Password

- name: Copy file via SSH password
  uses: appleboy/scp-action@v1
  with:
    host: example.com
    username: foo
    password: bar
    port: 22
    source: "tests/a.txt,tests/b.txt"
    target: your_server_target_folder_path

Example 2: Multi-server

- name: Copy to multiple servers
  uses: appleboy/scp-action@v1
  with:
    host: "foo.com,bar.com"
    username: foo
    password: bar
    port: 22
    source: "tests/a.txt,tests/b.txt"
    target: your_server_target_folder_path

Example 3: Changed Files Only

- name: Get changed files
  id: changed-files
  uses: tj-actions/changed-files@v35
  with:
    since_last_remote_commit: true
    separator: ","

- name: Copy changed files to server
  uses: appleboy/scp-action@v1
  with:
    host: ${{ secrets.HOST }}
    username: ${{ secrets.USERNAME }}
    key: ${{ secrets.KEY }}
    port: ${{ secrets.PORT }}
    source: ${{ steps.changed-files.outputs.all_changed_files }}
    target: your_server_target_folder_path

Example 4: Artifacts Integration

- uses: actions/upload-artifact@v4
  with:
    name: my-artifact
    path: world.txt

- uses: actions/download-artifact@v4
  with:
    name: my-artifact
    path: distfiles

- name: Copy artifact to server
  uses: appleboy/scp-action@v1
  with:
    host: ${{ secrets.HOST }}
    username: ${{ secrets.USERNAME }}
    key: ${{ secrets.KEY }}
    port: ${{ secrets.PORT }}
    source: distfiles/*
    target: your_server_target_folder_path

Example 5: Windows Server

- name: Copy to Windows
  uses: appleboy/scp-action@v1
  with:
    host: ${{ secrets.HOST }}
    username: ${{ secrets.USERNAME }}
    key: ${{ secrets.SSH_PRIVATE_KEY }}
    port: 22
    source: "your_source_path"
    target: "/c/path/to/target/"
    tar_dereference: true
    rm: true

๐Ÿ—๏ธ SSH Key Setup

  1. Generate SSH Key (on your local machine):

    # RSA
    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    # ED25519
    ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
    
  2. Add Public Key to Server:

    cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys'
    # or for ed25519
    cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys'
    
  3. Copy Private Key Content to GitHub Secrets:

    clip < ~/.ssh/id_rsa
    # or
    clip < ~/.ssh/id_ed25519
    

See SSH login without password for more details.

OpenSSH Note:
If you see ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], ensure your key algorithm is supported.
On Ubuntu 20.04+, add to /etc/ssh/sshd_config or /etc/ssh/sshd_config.d/:

CASignatureAlgorithms +ssh-rsa

Or use ed25519 keys, which are accepted by default.


๐Ÿงฐ Common Error Codes

Error CodePossible CauseSolution
ECONNREFUSEDWrong port / firewall blocksCheck port and firewall settings
ENOENTSource file not foundUse absolute path or check checkout step
EAUTHAuthentication failedCheck key format and permissions (PEM format)

๐Ÿ”„ Workflow Diagram

sequenceDiagram
    participant G as GitHub Runner
    participant S as Target Server
    G->>S: Establish SSH connection
    S-->>G: Authenticate credentials
    G->>S: (Optional) Remove target directory
    G->>G: Archive source files
    G->>S: Transfer archive
    S->>S: Extract and process files
    S-->>G: Return result

FAQ & Troubleshooting

  • Q: Why does authentication fail?
    A: Check SSH key format, permissions, and that the key is added to the server.

  • Q: How do I copy only changed files?
    A: Use tj-actions/changed-files to get changed files and pass to source.

  • Q: How to deploy to multiple servers?
    A: Use comma-separated host list: host: "foo.com,bar.com"

  • Q: How to copy to Windows?
    A: Set up Git Bash, use Unix-style paths, and enable tar_dereference.


๐Ÿ“ License

MIT License