19 Commits
docs ... master

Author SHA1 Message Date
73bea174b4 离线工具 2025-09-04 02:53:52 +08:00
07b0b286de 更新 entrypoint.sh
Some checks failed
v1 version / test scp action (push) Has been cancelled
v1 version / test deploy artifact (push) Has been cancelled
v1 version / test changed-files (push) Has been cancelled
v1 version / test target folder (push) Has been cancelled
v1 version / test Multiple Host (push) Has been cancelled
lint and test / test scp action (push) Has been cancelled
lint and test / test deploy artifact (push) Has been cancelled
lint and test / test changed-files (push) Has been cancelled
lint and test / test target folder (push) Has been cancelled
lint and test / test Multiple Host (push) Has been cancelled
使用本地drone-scp
2025-09-04 02:48:25 +08:00
Bo-Yi Wu
eb443bd494 feat: avoid redundant binary downloads and notify when skipping (#210)
Some checks failed
v1 version / test scp action (push) Failing after 7s
v1 version / test deploy artifact (push) Failing after 1s
v1 version / test changed-files (push) Failing after 2s
v1 version / test target folder (push) Failing after 2s
v1 version / test Multiple Host (push) Failing after 2s
lint and test / test scp action (push) Failing after 2s
lint and test / test deploy artifact (push) Failing after 2s
lint and test / test changed-files (push) Failing after 1s
lint and test / test target folder (push) Failing after 2s
lint and test / test Multiple Host (push) Failing after 2s
* feat: avoid redundant binary downloads and notify when skipping

- Skip downloading the binary if it already exists, and print a message instead

Signed-off-by: appleboy <appleboy.tw@gmail.com>

* Update entrypoint.sh

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Signed-off-by: appleboy <appleboy.tw@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-08-31 10:31:45 +08:00
appleboy
9132c85c5f ci: update GitHub Actions to latest major versions
- Update actions/checkout to version 5 throughout workflow files
- Update actions/download-artifact to version 5
- Update tj-actions/changed-files to version 46 in the testing workflow

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-08-31 10:04:38 +08:00
appleboy
7f18bf0ec8 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
appleboy
35c03a241d ci: rename testing workflow to clarify versioning
- Update workflow name from "testing v1" to "v1 version"

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 12:46:01 +08:00
appleboy
8b7c180c3f ci: add comprehensive GitHub Actions tests for scp-action
- Add GitHub Actions workflow to test multiple scp-action configurations and scenarios
- Include job to test deployment of uploaded and downloaded artifacts via scp
- Include job to copy only changed files detected by tj-actions/changed-files
- Add test for stripping leading path components when copying files
- Add coverage for copying files to single and multiple hosts, including target folder variations
- Test scp-action usage with both SSH key and password authentication, with and without passphrases, and option for insecure cipher

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 12:45:00 +08:00
appleboy
ff85246aca docs: update documentation to use latest scp-action version
Some checks failed
Goreleaser / goreleaser (push) Has been cancelled
lint and test / test scp action (push) Has been cancelled
lint and test / test deploy artifact (push) Has been cancelled
lint and test / test changed-files (push) Has been cancelled
lint and test / test target folder (push) Has been cancelled
lint and test / test Multiple Host (push) Has been cancelled
- Update all usage references of appleboy/scp-action from v0.1.7 to v1 in documentation and examples

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 12:42:05 +08:00
appleboy
6aff6492ae chore: bump default DRONE_SCP_VERSION to 1.8.0
- Update the default DRONE_SCP_VERSION from 1.7.0 to 1.8.0

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 12:41:00 +08:00
appleboy
6b2d3092e3 docs: update README badges to reference lint and test workflow
- Update the badge in all READMEs to use the lint and test workflow instead of the previous Actions status badge

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:39:19 +08:00
appleboy
f5c6c234bd ci: align workflow naming with updated testing conventions
- Rename the workflow file to testing.yml
- Rename the workflow from "scp files" to "lint and test"

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:38:05 +08:00
appleboy
17026f90b8 docs: add comprehensive Chinese documentation and localization support
- Add links to Traditional and Simplified Chinese documentation in the README
- Add a complete README in Simplified Chinese, including setup, configuration, usage examples, best practices, troubleshooting, and FAQ
- Add a complete README in Traditional Chinese, including setup, configuration, usage examples, best practices, troubleshooting, and FAQ

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:37:08 +08:00
appleboy
bf323b8729 docs: overhaul and enrich documentation for clarity and onboarding
- Revamp and reorganize the documentation with a new feature list and table of contents
- Add sections dedicated to features, configuration options, best practices, cross-platform usage, troubleshooting, workflow diagram, and FAQ
- Update and expand usage examples, including multi-server, changed-files-only, artifact integration, and Windows scenarios
- Improve clarity, formatting, and structure throughout the README
- Remove redundant and outdated examples and notes
- Provide clearer and more secure SSH key setup instructions
- Document common error codes and their solutions
- Improve quick start and workflow setup steps for better user onboarding

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:26:37 +08:00
appleboy
e55e4eabdc docs: refine and expand documentation for variable configuration
- Rewrite and clarify SCP action and SSH proxy table variable descriptions for accuracy and detail
- Add new variables: debug, curl_insecure, capture_stdout, and version to the documentation
- Improve formatting and make default values more consistent and explicit in documentation

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:21:28 +08:00
appleboy
bc835cba55 docs: refine input descriptions for clarity and user guidance
- Improve and clarify input descriptions for better usability and understanding
- Add guidance on defaults, security considerations, and example values in several input descriptions
- Reword descriptions to be more user-friendly and precise throughout configuration

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:16:12 +08:00
Bo-Yi Wu
98b7132065 feat: migrate to composite action with dynamic drone-scp support (#197)
- Remove Dockerfile and switch the action implementation from Docker to composite actions
- Add support for specifying the drone-scp version and automatically download the appropriate binary at runtime
- Add new inputs: curl_insecure, capture_stdout, and version for improved flexibility and output handling
- Add output for capturing standard output from executed commands when enabled
- entrypoint.sh refactored from sh to bash and made more robust with error handling, dynamic platform/architecture detection, and secure downloading of the binary
- Action now works cross-platform rather than being tied to a specific Docker image

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 10:38:00 +08:00
appleboy
3d59448764 docs: enhance SSH configuration documentation and testing
- Replace detailed SCP and SSH proxy settings with a table format for better readability
- Improve clarity and grammar in instructions for creating and using SSH keys

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-12-25 09:04:14 +08:00
appleboy
2a829c0ed2 docs: improve API performance and update documentation
- Fix grammar in README to clarify Linux Docker container support

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-12-24 22:15:22 +08:00
Bo-Yi Wu
4f2c27bbc2 docs: improve documentation and testing configurations (#193)
- Add example for using environment variables with `scp-action` in README.md

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2024-12-24 22:09:30 +08:00
9 changed files with 1227 additions and 301 deletions

150
.github/workflows/stable.yml vendored Normal file
View File

@@ -0,0 +1,150 @@
name: v1 version
on: [push]
jobs:
testing:
name: test scp action
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v5
- name: copy file via ssh password
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: "test"
- name: copy file via ssh key
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: "tests/a.txt,tests/b.txt"
target: "test"
- name: remove the specified number of leading path elements
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: "tests/a.txt,tests/b.txt"
target: "foobar"
strip_components: 1
- name: ssh key with passphrase
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH2 }}
passphrase: ${{ secrets.PASSPHRASE }}
port: ${{ secrets.PORT }}
source: "tests/a.txt,tests/b.txt"
target: "test"
- name: use insecure cipher
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH2 }}
passphrase: ${{ secrets.PASSPHRASE }}
port: ${{ secrets.PORT }}
source: "tests/a.txt,tests/b.txt"
target: "test"
use_insecure_cipher: true
deploy:
name: test deploy artifact
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v5
- run: echo hello > world.txt
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: world.txt
- uses: actions/download-artifact@v5
with:
name: my-artifact
path: distfiles
- name: copy file to server
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: distfiles/*
target: test
changes:
name: test changed-files
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v5
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45
with:
since_last_remote_commit: true
separator: ","
- name: copy file 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: test
target:
name: test target folder
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v5
- name: copy file to server
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: tests/a.txt,tests/b.txt
target: foobar foobar 1234
multipleHost:
name: test Multiple Host
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v5
- name: copy file to server
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}:${{ secrets.PORT }},${{ secrets.HOST }}:${{ secrets.PORT }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: 1024
source: tests/a.txt,tests/b.txt
target: foobar

View File

@@ -1,4 +1,4 @@
name: scp files
name: lint and test
on: [push]
jobs:
testing:
@@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: copy file via ssh password
uses: ./
@@ -67,7 +67,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- run: echo hello > world.txt
@@ -76,7 +76,7 @@ jobs:
name: my-artifact
path: world.txt
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v5
with:
name: my-artifact
path: distfiles
@@ -96,11 +96,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45
uses: tj-actions/changed-files@v46
with:
since_last_remote_commit: true
separator: ","
@@ -120,7 +120,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: copy file to server
uses: ./
@@ -137,7 +137,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: copy file to server
uses: ./

View File

@@ -1,5 +0,0 @@
FROM ghcr.io/appleboy/drone-scp:1.6.14
COPY entrypoint.sh /bin/entrypoint.sh
ENTRYPOINT ["/bin/entrypoint.sh"]

504
README.md
View File

@@ -1,26 +1,69 @@
# 🚀 SCP for GitHub Actions
[繁體中文](README.zh-tw.md) | [简体中文](README.zh-cn.md)
[GitHub Action](https://github.com/features/actions) for copying files and artifacts via SSH.
[![Actions Status](https://github.com/appleboy/scp-action/workflows/scp%20files/badge.svg)](https://github.com/appleboy/scp-action/actions)
[![v1 version](https://github.com/appleboy/scp-action/actions/workflows/stable.yml/badge.svg)](https://github.com/appleboy/scp-action/actions/workflows/stable.yml)
[![lint and test](https://github.com/appleboy/scp-action/actions/workflows/testing.yml/badge.svg)](https://github.com/appleboy/scp-action/actions/workflows/testing.yml)
**Important**: Only support **Linux** [docker](https://www.docker.com/) container.
> **Note:** Only supports **Linux** [docker](https://www.docker.com/) containers.
## Usage
---
Copy files and artifacts via SSH:
## ✨ 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
- [🚀 SCP for GitHub Actions](#-scp-for-github-actions)
- [✨ Features](#-features)
- [📦 Table of Contents](#-table-of-contents)
- [🚀 Quick Start](#-quick-start)
- [⚙️ Configuration](#-configuration)
- [🔌 Connection Settings](#-connection-settings)
- [📁 File Transfer Settings](#-file-transfer-settings)
- [🌐 Proxy Settings](#-proxy-settings)
- [🛡️ Best Practices \& Security](#-best-practices--security)
- [🖥️ Cross-Platform Notes](#-cross-platform-notes)
- [💡 Usage Examples](#-usage-examples)
- [🧩 Scenario Guide](#-scenario-guide)
- [Example 1: Basic SSH Password](#example-1-basic-ssh-password)
- [Example 2: Multi-server](#example-2-multi-server)
- [Example 3: Changed Files Only](#example-3-changed-files-only)
- [Example 4: Artifacts Integration](#example-4-artifacts-integration)
- [Example 5: Windows Server](#example-5-windows-server)
- [🗝️ SSH Key Setup](#-ssh-key-setup)
- [🧰 Common Error Codes](#-common-error-codes)
- [🔄 Workflow Diagram](#-workflow-diagram)
- [FAQ \& Troubleshooting](#faq--troubleshooting)
- [📝 License](#-license)
---
## 🚀 Quick Start
Copy files and artifacts via SSH in your GitHub Actions workflow:
```yaml
name: scp files
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: copy file via ssh password
uses: appleboy/scp-action@v0.1.7
- name: Copy files via SSH
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@@ -30,115 +73,106 @@ jobs:
target: your_server_target_folder_path
```
## Input variables
---
See the [action.yml](./action.yml) file for more detail information.
## ⚙️ Configuration
- host - scp remote host
- port - scp remote port, default is `22`
- username - scp username
- password - scp password
- passphrase - the passphrase is usually to encrypt the private key
- protocol - The IP protocol to use. Valid values are `tcp`. `tcp4` or `tcp6`. Default to `tcp`.
- fingerprint - fingerprint SHA256 of the host public key, default is to skip verification
- timeout - timeout for ssh to remote host, default is `30s`
- command_timeout - timeout for scp command, default is `10m`
- key - content of ssh private key. ex raw content of ~/.ssh/id_rsa
- key_path - path of ssh private key
- target - target path on the server, must be a directory (**required**)
- source - scp file list (**required**)
- rm - remove target folder before upload data, default is `false`
- strip_components - remove the specified number of leading path elements.
- overwrite - use `--overwrite` flag with tar, overwrite existing files when extracting
- tar_tmp_path - temporary path for tar file on the dest host
- tar_exec - path to tar executable on the dest host. default is `tar`
- tar_dereference - use `--dereference` flag with tar, follow symlinks; archive and dump the files they point to
- use_insecure_cipher - include more ciphers with use_insecure_cipher (see [#15](https://github.com/appleboy/scp-action/issues/15))
### 🔌 Connection Settings
SSH Proxy Setting:
| 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 | |
- proxy_host - proxy host
- proxy_port - proxy port, default is `22`
- proxy_username - proxy username
- proxy_password - proxy password
- proxy_protocol - The IP protocol to use. Valid values are `tcp`. `tcp4` or `tcp6`. Default to `tcp`.
- proxy_passphrase - the passphrase is usually to encrypt the private key
- proxy_timeout - timeout for ssh to proxy host, default is `30s`
- proxy_key - content of ssh proxy private key.
- proxy_key_path - path of ssh proxy private key
- proxy_fingerprint - fingerprint SHA256 of the host public key, default is to skip verification
- proxy_use_insecure_cipher - include more ciphers with use_insecure_cipher (see [#15](https://github.com/appleboy/scp-action/issues/15))
### 📁 File Transfer Settings
## Setting up a SSH Key
| 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 | - | |
Make sure to follow the below steps while creating SSH Keys and using them.
The best practice is create the SSH Keys on local machine not remote machine.
Login with username specified in Github Secrets. Generate a RSA Key-Pair:
### 🌐 Proxy Settings
```bash
# rsa
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
| 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 | |
# ed25519
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
---
Add newly generated key into Authorized keys. Read more about authorized keys [here](https://www.ssh.com/ssh/authorized_keys/).
## 🛡️ Best Practices & Security
```bash
# rsa
cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
- **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.
# d25519
cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys'
```
---
Copy Private Key content and paste in Github Secrets.
## 🖥️ Cross-Platform Notes
```bash
# rsa
clip < ~/.ssh/id_rsa
| 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 |
# ed25519
clip < ~/.ssh/id_ed25519
```
> 🚩 **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
See the detail information about [SSH login without password](http://www.linuxproblem.org/art_9.html).
---
**A note** from one of our readers: Depending on your version of SSH you might also have to do the following changes:
## 💡 Usage Examples
- Put the public key in `.ssh/authorized_keys2`
- Change the permissions of `.ssh` to 700
- Change the permissions of `.ssh/authorized_keys2` to 640
### 🧩 Scenario Guide
### If you are using OpenSSH
- **Basic file transfer** → [Example 1](#example-1-basic-ssh-password)
- **Multi-server deployment** → [Example 2](#example-2-multi-server)
- **Incremental/changed files only** → [Example 3](#example-3-changed-files-only)
- **Artifacts integration** → [Example 4](#example-4-artifacts-integration)
- **Windows server setup** → [Example 5](#example-5-windows-server)
If you are currently using OpenSSH and are getting the following error:
---
```bash
ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]
```
Make sure that your key algorithm of choice is supported.
On Ubuntu 20.04 or later you must explicitly allow the use of the ssh-rsa algorithm. Add the following line to your OpenSSH daemon file (which is either `/etc/ssh/sshd_config` or a drop-in file under `/etc/ssh/sshd_config.d/`):
```bash
CASignatureAlgorithms +ssh-rsa
```
Alternatively, `ed25519` keys are accepted by default in OpenSSH. You could use this instead of rsa if needed:
```bash
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
## Example
Copy file via a SSH password:
#### Example 1: Basic SSH Password
```yaml
- name: copy file via ssh password
uses: appleboy/scp-action@v0.1.7
- name: Copy file via SSH password
uses: appleboy/scp-action@v1
with:
host: example.com
username: foo
@@ -148,41 +182,13 @@ Copy file via a SSH password:
target: your_server_target_folder_path
```
Copy file via a SSH key:
#### Example 2: Multi-server
```yaml
- name: copy file via ssh key
uses: appleboy/scp-action@v0.1.7
- name: Copy to multiple servers
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
port: ${{ secrets.PORT }}
key: ${{ secrets.KEY }}
source: "tests/a.txt,tests/b.txt"
target: your_server_target_folder_path
```
Example configuration for ignore list:
```yaml
- name: copy file via ssh key
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
port: ${{ secrets.PORT }}
key: ${{ secrets.KEY }}
source: "tests/*.txt,!tests/a.txt"
target: your_server_target_folder_path
```
Example configuration for multiple servers:
```diff
uses: appleboy/scp-action@v0.1.7
with:
- host: "example.com"
+ host: "foo.com,bar.com"
host: "foo.com,bar.com"
username: foo
password: bar
port: 22
@@ -190,155 +196,153 @@ Example configuration for multiple servers:
target: your_server_target_folder_path
```
Example configuration for exclude custom files:
#### Example 3: Changed Files Only
```yaml
uses: appleboy/scp-action@v0.1.7
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v35
with:
host: "example.com"
username: foo
password: bar
port: 22
- source: "tests/*.txt"
+ source: "tests/*.txt,!tests/a.txt,!tests/b.txt"
target: your_server_target_folder_path
```
since_last_remote_commit: true
separator: ","
Upload artifact files to remote server:
```yaml
deploy:
name: deploy artifact
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- run: echo hello > world.txt
- 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 file to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: distfiles/*
target: your_server_target_folder_path
```
Remove the specified number of leading path elements:
```yaml
- name: remove the specified number of leading path elements
uses: appleboy/scp-action@v0.1.7
- 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: "tests/a.txt,tests/b.txt"
source: ${{ steps.changed-files.outputs.all_changed_files }}
target: your_server_target_folder_path
strip_components: 1
```
Old target structure:
```sh
foobar
└── tests
├── a.txt
└── b.txt
```
New target structure:
```sh
foobar
├── a.txt
└── b.txt
```
Only copy files that are newer than the corresponding destination files:
#### Example 4: Artifacts Integration
```yaml
changes:
name: test changed-files
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: world.txt
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v35
with:
since_last_remote_commit: true
separator: ","
- uses: actions/download-artifact@v4
with:
name: my-artifact
path: distfiles
- name: copy file to server
uses: appleboy/scp-action@v0.1.7
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
- 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
```
Protecting a Private Key. The purpose of the passphrase is usually to encrypt the private key. This makes the key file by itself useless to an attacker. It is not uncommon for files to leak from backups or decommissioned hardware, and hackers commonly exfiltrate files from compromised systems.
#### Example 5: Windows Server
```diff
- name: ssh key with passphrase
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH2 }}
+ passphrase: ${{ secrets.PASSPHRASE }}
port: ${{ secrets.PORT }}
source: "tests/a.txt,tests/b.txt"
target: your_server_target_folder_path
```yaml
- 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
```
When copying files from a Linux runner to a Windows server, you should:
---
1. Download git for Windows
2. Change the default OpenSSH shell to git bach with the following powershell command.
3. Set `tar_dereference` and `rm` variable to `true` in the YAML file
4. Avoid putting the `port` value through a variable
5. Convert the target path to a Unix path: `/c/path/to/target/`
## 🗝️ SSH Key Setup
Change the default OpenSSH shell to git bach with the following powershell command.
1. **Generate SSH Key** (on your local machine):
```powershell
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "$env:Programfiles\Git\bin\bash.exe" -PropertyType String -Force
```bash
# 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**:
```bash
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**:
```bash
clip < ~/.ssh/id_rsa
# or
clip < ~/.ssh/id_ed25519
```
> See [SSH login without password](http://www.linuxproblem.org/art_9.html) 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/`:
```sh
CASignatureAlgorithms +ssh-rsa
```
Convert the target path to a Unix path: `/c/path/to/target/`
Or use ed25519 keys, which are accepted by default.
```diff
- name: Copy to Windows
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
source: 'your_source_path'
- target: 'C:\path\to\target'
+ target: '/c/path/to/target/'
+ tar_dereference: true
+ rm: true
---
## 🧰 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
```mermaid
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

348
README.zh-cn.md Normal file
View File

@@ -0,0 +1,348 @@
# 🚀 GitHub Actions 的 SCP
[English](README.md) | [繁體中文](README.zh-tw.md)
[GitHub Action](https://github.com/features/actions) 用于通过 SSH 复制文件和构建产物。
[![v1 version](https://github.com/appleboy/scp-action/actions/workflows/stable.yml/badge.svg)](https://github.com/appleboy/scp-action/actions/workflows/stable.yml)
[![lint and test](https://github.com/appleboy/scp-action/actions/workflows/testing.yml/badge.svg)](https://github.com/appleboy/scp-action/actions/workflows/testing.yml)
> **注意:** 仅支持 **Linux** [docker](https://www.docker.com/) 容器。
---
## ✨ 功能特性
- ✅ 通过 SSH 将文件和产物复制到一台或多台远程服务器
- ✅ 支持 SSH 密钥和密码认证
- ✅ 完全支持 SSH 代理(跳板机)
- ✅ 处理 Linux ↔ Windows 路径转换
- ✅ 集成 GitHub Artifacts 工作流
- ✅ 支持增量与差异文件传输
- ✅ 丰富的高级配置选项
---
## 📦 目录
- [🚀 GitHub Actions 的 SCP](#-github-actions-的-scp)
- [✨ 功能特性](#-功能特性)
- [📦 目录](#-目录)
- [🚀 快速开始](#-快速开始)
- [⚙️ 配置说明](#-配置说明)
- [🔌 连接设置](#-连接设置)
- [📁 文件传输设置](#-文件传输设置)
- [🌐 代理设置](#-代理设置)
- [🛡️ 最佳实践与安全性](#-最佳实践与安全性)
- [🖥️ 跨平台注意事项](#-跨平台注意事项)
- [💡 使用示例](#-使用示例)
- [🧩 场景导览](#-场景导览)
- [示例 1基本 SSH 密码](#示例-1基本-ssh-密码)
- [示例 2多台服务器](#示例-2多台服务器)
- [示例 3仅传输变更文件](#示例-3仅传输变更文件)
- [示例 4集成 Artifacts](#示例-4集成-artifacts)
- [示例 5Windows 服务器](#示例-5windows-服务器)
- [🗝️ SSH 密钥设置](#-ssh-密钥设置)
- [🧰 常见错误代码](#-常见错误代码)
- [🔄 工作流程图](#-工作流程图)
- [FAQ 与故障排查](#faq-与故障排查)
- [📝 许可证](#-许可证)
---
## 🚀 快速开始
在 GitHub Actions 工作流中通过 SSH 复制文件和产物:
```yaml
name: scp files
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 通过 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
```
---
## ⚙️ 配置说明
### 🔌 连接设置
| 变量 | 说明 | 默认值 | 必填 |
| --------------- | -------------------------------- | ------ | ---- |
| host | 远程主机(多台用逗号分隔) | - | ✓ |
| port | SSH 端口 | 22 | |
| username | SSH 用户名 | - | ✓ |
| password | SSH 密码(建议优先使用密钥认证) | - | |
| key | SSH 私钥内容 | - | |
| key_path | SSH 私钥文件路径 | - | |
| passphrase | SSH 私钥密码 | - | |
| fingerprint | 主机密钥 SHA256 指纹验证 | - | |
| protocol | IP 协议:'tcp'、'tcp4' 或 'tcp6' | tcp | |
| timeout | SSH 连接超时 | 30s | |
| command_timeout | SCP 命令超时 | 10m | |
### 📁 文件传输设置
| 变量 | 说明 | 默认值 | 安全性说明 |
| ---------------- | --------------------------------- | ------ | -------------- |
| source | 本地要传输的文件/目录(逗号分隔) | - | 请使用明确路径 |
| target | 远程目标目录(必须为目录) | - | 避免使用根目录 |
| rm | 上传前移除目标目录 | - | 谨慎使用 |
| strip_components | 传输时移除前置路径元素 | - | |
| overwrite | 使用 tar 覆盖现有文件 | - | |
| tar_dereference | tar 传输时跟随符号链接 | - | |
| tar_tmp_path | 目标端 tar 临时文件路径 | - | |
| tar_exec | 目标端 tar 执行文件路径 | tar | |
| debug | 启用调试输出 | - | |
| curl_insecure | curl 使用 --insecure | false | 不推荐 |
| capture_stdout | 将命令 stdout 作为 action 输出 | false | |
| version | 指定 drone-scp 版本 | - | |
### 🌐 代理设置
| 变量 | 说明 | 默认值 | 必填 |
| ------------------------- | -------------------------- | ------ | ---- |
| proxy_host | SSH 代理主机 | - | |
| proxy_port | SSH 代理端口 | 22 | |
| proxy_username | SSH 代理用户名 | - | |
| proxy_password | SSH 代理密码 | - | |
| proxy_key | SSH 代理私钥内容 | - | |
| proxy_key_path | SSH 代理私钥文件路径 | - | |
| proxy_passphrase | SSH 代理私钥密码 | - | |
| proxy_fingerprint | 代理主机 SHA256 指纹验证 | - | |
| proxy_use_insecure_cipher | 启用较不安全的代理加密算法 | - | |
| proxy_timeout | SSH 代理连接超时 | 30s | |
---
## 🛡️ 最佳实践与安全性
- **建议优先使用 SSH 密钥认证**,提升安全性。
- 将所有敏感信息host、username、password、key存放于 **GitHub Secrets**
- 定期**更换部署密钥**(建议每 90 天一次)。
- 限制目标服务器目录的写入权限。
- 启用主机密钥指纹验证以防止中间人攻击。
- 避免使用 root 用户登录 SSH。
---
## 🖥️ 跨平台注意事项
| 场景 | Linux 服务器 | Windows 服务器 |
| -------- | -------------- | ----------------------- |
| 路径格式 | `/path/to/dir` | `/c/path/to/dir` |
| 必要设置 | 无 | `tar_dereference: true` |
| 权限 | 保留 | 可能需手动设置 ACL |
| Shell | bash默认 | Git BashOpenSSH |
> 🚩 **重要提醒:**
> 复制到 Windows 服务器时:
>
> - 安装 Git for Windows 并将 OpenSSH 默认 shell 设为 Git Bash
> - 使用类 Unix 目标路径(如 `/c/Users/...`
> - 启用 `tar_dereference` 处理符号链接
---
## 💡 使用示例
### 🧩 场景导览
- **基本文件传输** → [示例 1](#示例-1基本-ssh-密码)
- **多台服务器部署** → [示例 2](#示例-2多台服务器)
- **仅传输变更文件** → [示例 3](#示例-3仅传输变更文件)
- **集成 Artifacts** → [示例 4](#示例-4集成-artifacts)
- **Windows 服务器设置** → [示例 5](#示例-5windows-服务器)
---
#### 示例 1基本 SSH 密码
```yaml
- name: 通过 SSH 密码复制文件
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
```
#### 示例 2多台服务器
```yaml
- name: 复制到多台服务器
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
```
#### 示例 3仅传输变更文件
```yaml
- name: 获取变更文件
id: changed-files
uses: tj-actions/changed-files@v35
with:
since_last_remote_commit: true
separator: ","
- name: 复制变更文件到服务器
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
```
#### 示例 4集成 Artifacts
```yaml
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: world.txt
- uses: actions/download-artifact@v4
with:
name: my-artifact
path: distfiles
- name: 复制 artifact 到服务器
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
```
#### 示例 5Windows 服务器
```yaml
- name: 复制到 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 密钥设置
1. **生成 SSH 密钥**(在本地执行):
```bash
# 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. **将公钥添加到服务器**
```bash
cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys'
# 或 ed25519
cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys'
```
3. **将私钥内容复制到 GitHub Secrets**
```bash
clip < ~/.ssh/id_rsa
# 或
clip < ~/.ssh/id_ed25519
```
> 更多细节请参考 [SSH 免密登录](http://www.linuxproblem.org/art_9.html)。
**OpenSSH 注意事项:**
如遇到 `ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]`,请确认密钥算法已被支持。
Ubuntu 20.04+ 可在 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 添加:
```sh
CASignatureAlgorithms +ssh-rsa
```
或使用 ed25519 密钥(默认支持)。
---
## 🧰 常见错误代码
| 错误代码 | 可能原因 | 解决方法 |
| -------------- | ------------------- | --------------------------------- |
| `ECONNREFUSED` | 端口错误/防火墙阻挡 | 检查端口和防火墙设置 |
| `ENOENT` | 找不到源文件 | 使用绝对路径或检查 checkout 步骤 |
| `EAUTH` | 认证失败 | 检查密钥格式和权限(需 PEM 格式) |
---
## 🔄 工作流程图
```mermaid
sequenceDiagram
participant G as GitHub Runner
participant S as Target Server
G->>S: 建立 SSH 连接
S-->>G: 验证凭证
G->>S: (可选)移除目标目录
G->>G: 打包源文件
G->>S: 传输打包文件
S->>S: 解压和处理文件
S-->>G: 返回结果
```
---
## FAQ 与故障排查
- **Q: 为什么认证失败?**
A: 请检查 SSH 密钥格式、权限,以及密钥是否已添加到服务器。
- **Q: 如何只复制变更文件?**
A: 使用 `tj-actions/changed-files` 获取变更文件并传递给 `source`。
- **Q: 如何部署到多台服务器?**
A: `host` 参数用逗号分隔多台主机,例如:`host: "foo.com,bar.com"`
- **Q: 如何复制到 Windows**
A: 设置 Git Bash使用类 Unix 路径,并启用 `tar_dereference`。
---
## 📝 许可证
MIT License

348
README.zh-tw.md Normal file
View File

@@ -0,0 +1,348 @@
# 🚀 GitHub Actions 的 SCP
[English](README.md) | [简体中文](README.zh-cn.md)
[GitHub Action](https://github.com/features/actions) 用於透過 SSH 複製檔案與產物。
[![v1 version](https://github.com/appleboy/scp-action/actions/workflows/stable.yml/badge.svg)](https://github.com/appleboy/scp-action/actions/workflows/stable.yml)
[![lint and test](https://github.com/appleboy/scp-action/actions/workflows/testing.yml/badge.svg)](https://github.com/appleboy/scp-action/actions/workflows/testing.yml)
> **注意:** 只支援 **Linux** [docker](https://www.docker.com/) 容器。
---
## ✨ 功能特色
- ✅ 透過 SSH 將檔案與產物複製到一台或多台遠端伺服器
- ✅ 支援 SSH 金鑰與密碼驗證
- ✅ 完整支援 SSH Proxy跳板機
- ✅ 處理 Linux ↔ Windows 路徑轉換
- ✅ 整合 GitHub Artifacts 工作流程
- ✅ 支援增量與差異檔案傳輸
- ✅ 豐富的進階設定選項
---
## 📦 目錄
- [🚀 GitHub Actions 的 SCP](#-github-actions-的-scp)
- [✨ 功能特色](#-功能特色)
- [📦 目錄](#-目錄)
- [🚀 快速開始](#-快速開始)
- [⚙️ 設定說明](#-設定說明)
- [🔌 連線設定](#-連線設定)
- [📁 檔案傳輸設定](#-檔案傳輸設定)
- [🌐 Proxy 設定](#-proxy-設定)
- [🛡️ 最佳實踐與安全性](#-最佳實踐與安全性)
- [🖥️ 跨平台注意事項](#-跨平台注意事項)
- [💡 使用範例](#-使用範例)
- [🧩 情境導覽](#-情境導覽)
- [範例 1基本 SSH 密碼](#範例-1基本-ssh-密碼)
- [範例 2多台伺服器](#範例-2多台伺服器)
- [範例 3僅傳送變更檔案](#範例-3僅傳送變更檔案)
- [範例 4整合 Artifacts](#範例-4整合-artifacts)
- [範例 5Windows 伺服器](#範例-5windows-伺服器)
- [🗝️ SSH 金鑰設定](#-ssh-金鑰設定)
- [🧰 常見錯誤代碼](#-常見錯誤代碼)
- [🔄 工作流程圖](#-工作流程圖)
- [FAQ 與疑難排解](#faq-與疑難排解)
- [📝 授權條款](#-授權條款)
---
## 🚀 快速開始
在 GitHub Actions 工作流程中透過 SSH 複製檔案與產物:
```yaml
name: scp files
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 透過 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
```
---
## ⚙️ 設定說明
### 🔌 連線設定
| 變數 | 說明 | 預設值 | 必填 |
| --------------- | ------------------------------------ | ------ | ---- |
| host | 遠端主機(多台以逗號分隔) | - | ✓ |
| port | SSH 連接埠 | 22 | |
| username | SSH 使用者名稱 | - | ✓ |
| password | SSH 密碼(建議使用金鑰以提升安全性) | - | |
| key | SSH 私鑰內容 | - | |
| key_path | SSH 私鑰檔案路徑 | - | |
| passphrase | SSH 私鑰密碼 | - | |
| fingerprint | 主機金鑰 SHA256 指紋驗證 | - | |
| protocol | IP 協定:'tcp'、'tcp4' 或 'tcp6' | tcp | |
| timeout | SSH 連線逾時 | 30s | |
| command_timeout | SCP 指令逾時 | 10m | |
### 📁 檔案傳輸設定
| 變數 | 說明 | 預設值 | 安全性說明 |
| ---------------- | --------------------------------- | ------ | -------------- |
| source | 本地要傳送的檔案/目錄(逗號分隔) | - | 請使用明確路徑 |
| target | 遠端目標目錄(必須為目錄) | - | 避免使用根目錄 |
| rm | 上傳前移除目標目錄 | - | 請小心使用 |
| strip_components | 傳送時移除前置路徑元素 | - | |
| overwrite | 使用 tar 覆蓋現有檔案 | - | |
| tar_dereference | tar 傳送時跟隨符號連結 | - | |
| tar_tmp_path | 目標端 tar 暫存檔路徑 | - | |
| tar_exec | 目標端 tar 執行檔路徑 | tar | |
| debug | 啟用除錯輸出 | - | |
| curl_insecure | curl 使用 --insecure | false | 不建議 |
| capture_stdout | 將指令 stdout 作為 action 輸出 | false | |
| version | 指定 drone-scp 版本 | - | |
### 🌐 Proxy 設定
| 變數 | 說明 | 預設值 | 必填 |
| ------------------------- | ------------------------------- | ------ | ---- |
| proxy_host | SSH Proxy 主機 | - | |
| proxy_port | SSH Proxy 連接埠 | 22 | |
| proxy_username | SSH Proxy 使用者名稱 | - | |
| proxy_password | SSH Proxy 密碼 | - | |
| proxy_key | SSH Proxy 私鑰內容 | - | |
| proxy_key_path | SSH Proxy 私鑰檔案路徑 | - | |
| proxy_passphrase | SSH Proxy 私鑰密碼 | - | |
| proxy_fingerprint | Proxy 主機 SHA256 指紋驗證 | - | |
| proxy_use_insecure_cipher | 啟用較不安全的 Proxy 加密演算法 | - | |
| proxy_timeout | SSH Proxy 連線逾時 | 30s | |
---
## 🛡️ 最佳實踐與安全性
- **建議優先使用 SSH 金鑰驗證**,提升安全性。
- 將所有敏感資訊host、username、password、key存放於 **GitHub Secrets**
- 定期**更換部署金鑰**(建議每 90 天一次)。
- 限制目標伺服器目錄的寫入權限。
- 啟用主機金鑰指紋驗證以防止中間人攻擊。
- 避免使用 root 帳號登入 SSH。
---
## 🖥️ 跨平台注意事項
| 情境 | Linux 伺服器 | Windows 伺服器 |
| -------- | -------------- | ----------------------- |
| 路徑格式 | `/path/to/dir` | `/c/path/to/dir` |
| 必要設定 | 無 | `tar_dereference: true` |
| 權限 | 保留 | 可能需手動設定 ACL |
| Shell | bash (預設) | Git BashOpenSSH |
> 🚩 **重要提醒:**
> 複製到 Windows 伺服器時:
>
> - 安裝 Git for Windows 並將 OpenSSH 預設 shell 設為 Git Bash
> - 使用 Unix 風格目標路徑(如 `/c/Users/...`
> - 啟用 `tar_dereference` 處理符號連結
---
## 💡 使用範例
### 🧩 情境導覽
- **基本檔案傳輸** → [範例 1](#範例-1基本-ssh-密碼)
- **多台伺服器部署** → [範例 2](#範例-2多台伺服器)
- **僅傳送變更檔案** → [範例 3](#範例-3僅傳送變更檔案)
- **整合 Artifacts** → [範例 4](#範例-4整合-artifacts)
- **Windows 伺服器設定** → [範例 5](#範例-5windows-伺服器)
---
#### 範例 1基本 SSH 密碼
```yaml
- name: 透過 SSH 密碼複製檔案
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
```
#### 範例 2多台伺服器
```yaml
- name: 複製到多台伺服器
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
```
#### 範例 3僅傳送變更檔案
```yaml
- name: 取得變更檔案
id: changed-files
uses: tj-actions/changed-files@v35
with:
since_last_remote_commit: true
separator: ","
- name: 複製變更檔案到伺服器
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
```
#### 範例 4整合 Artifacts
```yaml
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: world.txt
- uses: actions/download-artifact@v4
with:
name: my-artifact
path: distfiles
- name: 複製 artifact 到伺服器
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
```
#### 範例 5Windows 伺服器
```yaml
- name: 複製到 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 金鑰設定
1. **產生 SSH 金鑰**(於本地端執行):
```bash
# 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. **將公鑰加入伺服器**
```bash
cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys'
# 或 ed25519
cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys'
```
3. **將私鑰內容複製到 GitHub Secrets**
```bash
clip < ~/.ssh/id_rsa
# 或
clip < ~/.ssh/id_ed25519
```
> 更多細節請參考 [SSH 無密碼登入](http://www.linuxproblem.org/art_9.html)。
**OpenSSH 注意事項:**
若出現 `ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]`,請確認金鑰演算法支援。
Ubuntu 20.04+ 可於 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 加入:
```sh
CASignatureAlgorithms +ssh-rsa
```
或改用 ed25519 金鑰(預設支援)。
---
## 🧰 常見錯誤代碼
| 錯誤代碼 | 可能原因 | 解決方式 |
| -------------- | --------------------- | --------------------------------- |
| `ECONNREFUSED` | 連接埠錯誤/防火牆阻擋 | 檢查連接埠與防火牆設定 |
| `ENOENT` | 找不到來源檔案 | 請用絕對路徑或檢查 checkout 步驟 |
| `EAUTH` | 驗證失敗 | 檢查金鑰格式與權限(需 PEM 格式) |
---
## 🔄 工作流程圖
```mermaid
sequenceDiagram
participant G as GitHub Runner
participant S as Target Server
G->>S: 建立 SSH 連線
S-->>G: 驗證憑證
G->>S: (可選)移除目標目錄
G->>G: 封存來源檔案
G->>S: 傳送封存檔
S->>S: 解壓與處理檔案
S-->>G: 回傳結果
```
---
## FAQ 與疑難排解
- **Q: 為什麼驗證失敗?**
A: 請檢查 SSH 金鑰格式、權限,以及金鑰是否已加入伺服器。
- **Q: 如何只複製變更檔案?**
A: 使用 `tj-actions/changed-files` 取得變更檔案並傳給 `source`。
- **Q: 如何部署到多台伺服器?**
A: `host` 參數用逗號分隔多台主機,例如:`host: "foo.com,bar.com"`
- **Q: 如何複製到 Windows**
A: 設定 Git Bash使用 Unix 風格路徑,並啟用 `tar_dereference`。
---
## 📝 授權條款
MIT License

View File

@@ -1,79 +1,141 @@
name: "SCP Command to Transfer Files"
description: "How to Use SCP Command to Transfer Files/Folders in Linux"
description: "Easily transfer files and folders using the SCP command in Linux."
author: "Bo-Yi Wu"
inputs:
host:
description: "scp remote host"
description: "Remote host address for SCP (e.g., example.com or 192.168.1.1)."
port:
description: "scp remote port"
description: "Remote SSH port for SCP. Default: 22."
default: "22"
username:
description: "scp username"
description: "Username for SSH authentication."
password:
description: "scp password"
description: "Password for SSH authentication (not recommended; use SSH keys if possible)."
protocol:
description: "The IP protocol to use. Valid values are 'tcp'. 'tcp4' or 'tcp6'. Default to tcp."
description: "IP protocol to use. Valid values: 'tcp', 'tcp4', or 'tcp6'. Default: tcp."
default: "tcp"
timeout:
description: "timeout for ssh to remote host"
description: "Timeout for establishing SSH connection to the remote host. Default: 30s."
default: "30s"
command_timeout:
description: "timeout for scp command"
description: "Timeout for the SCP command execution. Default: 10m."
default: "10m"
key:
description: "content of ssh private key. ex raw content of ~/.ssh/id_rsa"
description: "Content of the SSH private key (e.g., the raw content of ~/.ssh/id_rsa)."
key_path:
description: "path of ssh private key"
description: "Path to the SSH private key file."
passphrase:
description: "ssh key passphrase"
description: "Passphrase for the SSH private key, if required."
fingerprint:
description: "fingerprint SHA256 of the host public key, default is to skip verification"
description: "SHA256 fingerprint of the host's public key. If not set, host key verification is skipped (not recommended for production)."
use_insecure_cipher:
description: "include more ciphers with use_insecure_cipher"
description: "Enable additional, less secure ciphers for compatibility. Not recommended unless required."
target:
description: "target path on the server, must be a directory path."
description: "Target directory path on the remote server. Must be a directory."
source:
description: "scp file list"
description: "List of files or directories to transfer (local paths)."
rm:
description: "remove target folder before upload data"
description: "Remove the target directory on the server before uploading new data."
debug:
description: "enable debug message"
description: "Enable debug messages for troubleshooting."
strip_components:
description: "remove the specified number of leading path elements"
description: "Remove the specified number of leading path elements when extracting files."
overwrite:
description: "use --overwrite flag with tar"
description: "Use the --overwrite flag with tar to overwrite existing files."
tar_dereference:
description: "use --dereference flag with tar"
description: "Use the --dereference flag with tar to follow symlinks."
tar_tmp_path:
description: "temporary path for tar file on the dest host"
description: "Temporary path for the tar file on the destination host."
tar_exec:
description: "temporary path for tar file on the dest host"
description: "Path to the tar executable on the destination host. Default: tar."
default: "tar"
proxy_host:
description: "ssh proxy remote host"
description: "Remote host address for SSH proxy."
proxy_port:
description: "ssh proxy remote port"
description: "SSH proxy port. Default: 22."
default: "22"
proxy_username:
description: "ssh proxy username"
description: "Username for SSH proxy authentication."
proxy_password:
description: "ssh proxy password"
description: "Password for SSH proxy authentication."
proxy_passphrase:
description: "ssh proxy key passphrase"
description: "Passphrase for the SSH proxy private key, if required."
proxy_timeout:
description: "timeout for ssh to proxy host"
description: "Timeout for establishing SSH connection to the proxy host. Default: 30s."
default: "30s"
proxy_key:
description: "content of ssh proxy private key. ex raw content of ~/.ssh/id_rsa"
description: "Content of the SSH proxy private key (e.g., the raw content of ~/.ssh/id_rsa)."
proxy_key_path:
description: "path of ssh proxy private key"
description: "Path to the SSH proxy private key file."
proxy_fingerprint:
description: "fingerprint SHA256 of the host public key, default is to skip verification"
description: "SHA256 fingerprint of the proxy host's public key. If not set, host key verification is skipped (not recommended for production)."
proxy_use_insecure_cipher:
description: "include more ciphers with use_insecure_cipher"
description: "Enable additional, less secure ciphers for the proxy connection. Not recommended unless required."
curl_insecure:
description: "When true, uses the --insecure option with curl for insecure downloads."
default: "false"
capture_stdout:
description: "When true, captures and returns standard output from the commands as action output."
default: "false"
version:
description: |
The version of drone-scp to use.
outputs:
stdout:
description: "Standard output of the executed commands when capture_stdout is enabled."
value: ${{ steps.entrypoint.outputs.stdout }}
runs:
using: "docker"
image: "Dockerfile"
using: "composite"
steps:
- name: Set GitHub Path
run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH
shell: bash
env:
GITHUB_ACTION_PATH: ${{ github.action_path }}
- id: entrypoint
name: Run entrypoint.sh
run: entrypoint.sh
shell: bash
env:
GITHUB_ACTION_PATH: ${{ github.action_path }}
INPUT_HOST: ${{ inputs.host }}
INPUT_PORT: ${{ inputs.port }}
INPUT_PROTOCOL: ${{ inputs.protocol }}
INPUT_USERNAME: ${{ inputs.username }}
INPUT_PASSWORD: ${{ inputs.password }}
INPUT_PASSPHRASE: ${{ inputs.passphrase }}
INPUT_KEY: ${{ inputs.key }}
INPUT_KEY_PATH: ${{ inputs.key_path }}
INPUT_FINGERPRINT: ${{ inputs.fingerprint }}
INPUT_PROXY_HOST: ${{ inputs.proxy_host }}
INPUT_PROXY_PORT: ${{ inputs.proxy_port }}
INPUT_PROXY_USERNAME: ${{ inputs.proxy_username }}
INPUT_PROXY_PASSWORD: ${{ inputs.proxy_password }}
INPUT_PROXY_PASSPHRASE: ${{ inputs.proxy_passphrase }}
INPUT_PROXY_KEY: ${{ inputs.proxy_key }}
INPUT_PROXY_KEY_PATH: ${{ inputs.proxy_key_path }}
INPUT_PROXY_FINGERPRINT: ${{ inputs.proxy_fingerprint }}
INPUT_USE_INSECURE_CIPHER: ${{ inputs.use_insecure_cipher }}
INPUT_CIPHER: ${{ inputs.cipher }}
INPUT_PROXY_USE_INSECURE_CIPHER: ${{ inputs.proxy_use_insecure_cipher }}
INPUT_PROXY_CIPHER: ${{ inputs.proxy_cipher }}
INPUT_DEBUG: ${{ inputs.debug }}
INPUT_TIMEOUT: ${{ inputs.timeout }}
INPUT_COMMAND_TIMEOUT: ${{ inputs.command_timeout }}
INPUT_TARGET: ${{ inputs.target }}
INPUT_SOURCE: ${{ inputs.source }}
INPUT_RM: ${{ inputs.rm }}
INPUT_STRIP_COMPONENTS: ${{ inputs.strip_components }}
INPUT_OVERWRITE: ${{ inputs.overwrite }}
INPUT_TAR_DEREFERENCE: ${{ inputs.tar_dereference }}
INPUT_TAR_TMP_PATH: ${{ inputs.tar_tmp_path }}
INPUT_TAR_EXEC: ${{ inputs.tar_exec }}
INPUT_PROXY_TIMEOUT: ${{ inputs.proxy_timeout }}
INPUT_CAPTURE_STDOUT: ${{ inputs.capture_stdout }}
INPUT_CURL_INSECURE: ${{ inputs.curl_insecure }}
DRONE_SCP_VERSION: ${{ inputs.version }}
branding:
icon: "copy"

BIN
drone-scp Executable file

Binary file not shown.

View File

@@ -1,7 +1,26 @@
#!/bin/sh
#!/usr/bin/env bash
set -eu
set -euo pipefail
[ -n "$INPUT_STRIP_COMPONENTS" ] && export INPUT_STRIP_COMPONENTS=$((INPUT_STRIP_COMPONENTS + 0))
export GITHUB="true"
sh -c "/bin/drone-scp $*"
GITHUB_ACTION_PATH="${GITHUB_ACTION_PATH%/}"
# 直接将 TARGET 定义为我们自己放在仓库里的 drone-scp 文件
TARGET="${GITHUB_ACTION_PATH}/drone-scp"
echo "======= Using local CLI Version ======="
"${TARGET}" --version
echo "======================================="
# 【已移除】: 删除了所有 curl 下载相关的代码块
if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then
{
echo 'stdout<<EOF'
"${TARGET}" "$@" | tee -a "${GITHUB_OUTPUT}"
echo 'EOF'
} >>"${GITHUB_OUTPUT}"
else
"${TARGET}" "$@"
fi