scp-action/README.md
appleboy 7f18bf0ec8
Some checks failed
v1 version / test deploy artifact (push) Failing after 49s
v1 version / test changed-files (push) Failing after 2m36s
v1 version / test target folder (push) Failing after 5m20s
lint and test / test scp action (push) Failing after 2m50s
lint and test / test deploy artifact (push) Failing after 31s
lint and test / test changed-files (push) Failing after 51s
v1 version / test Multiple Host (push) Failing after 7m10s
lint and test / test target folder (push) Failing after 1m58s
lint and test / test Multiple Host (push) Failing after 1m57s
v1 version / test scp action (push) Failing after 11m12s
docs: add v1 workflow version badge to all README files
- Add a v1 version badge for the stable workflow to all README files

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 12:46:41 +08:00

12 KiB

🚀 SCP for GitHub Actions

繁體中文 | 简体中文

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

Variable Description Default Required
host Remote host(s), comma-separated for multiple -
port SSH port 22
username SSH username -
password SSH password (prefer SSH key for security) -
key SSH private key content -
key_path Path to SSH private key file -
passphrase Passphrase for SSH private key -
fingerprint SHA256 fingerprint for host key verification -
protocol IP protocol: 'tcp', 'tcp4', or 'tcp6' tcp
timeout SSH connection timeout 30s
command_timeout SCP command timeout 10m

📁 File Transfer Settings

Variable Description Default Security Note
source Local files/directories to transfer (comma-separated) - Use explicit paths
target Target directory on remote server (must be a directory) - Avoid root directories
rm Remove target directory before upload - Use with caution
strip_components Remove leading path elements when extracting -
overwrite Overwrite existing files with tar -
tar_dereference Follow symlinks with tar -
tar_tmp_path Temp path for tar file on destination -
tar_exec Path to tar executable on destination tar
debug Enable debug output -
curl_insecure Use --insecure with curl false Not recommended
capture_stdout Capture command stdout as action output false
version Version of drone-scp to use -

🌐 Proxy Settings

Variable Description Default Required
proxy_host SSH proxy host -
proxy_port SSH proxy port 22
proxy_username SSH proxy username -
proxy_password SSH proxy password -
proxy_key SSH proxy private key content -
proxy_key_path Path to SSH proxy private key file -
proxy_passphrase Passphrase for SSH proxy private key -
proxy_fingerprint SHA256 fingerprint for proxy host -
proxy_use_insecure_cipher Enable less secure ciphers for proxy -
proxy_timeout SSH proxy connection timeout 30s

🛡️ 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

Scenario Linux Server Windows Server
Path Format /path/to/dir /c/path/to/dir
Required Setting None tar_dereference: true
Permissions Preserved May require manual ACL
Shell bash (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 Code Possible Cause Solution
ECONNREFUSED Wrong port / firewall blocks Check port and firewall settings
ENOENT Source file not found Use absolute path or check checkout step
EAUTH Authentication failed Check 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