Compare commits

...

24 Commits

Author SHA1 Message Date
Bo-Yi Wu
ffd1eec364
ci: add workflow step for multi-command SSH testing (#386)
- Add a workflow step to run multiple SSH commands for testing, including creating a directory, writing a file, listing files, and displaying file contents

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-05-18 11:26:30 +08:00
appleboy
8745f9583c
docs: restructure and clarify parameter documentation across all readmes
- Restructure input parameter documentation by splitting into distinct sections: Connection Settings, SSH Command Settings, and Proxy Settings for better clarity
- Move parameters related to command execution out of proxy section and into the new SSH Command Settings section
- Add/clarify descriptions for individual sections and parameters in all three language readmes
- Update and correct parameter ordering, grouping, and formatting for consistency across all documentation
- Add missing SSH Command Settings parameters and improve readability of parameter tables

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 12:35:14 +08:00
appleboy
8f3cc07719
docs: add comprehensive tables of contents to all README files
- Add a detailed table of contents to all three README files in English, Simplified Chinese, and Traditional Chinese for easier navigation.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:58:18 +08:00
appleboy
4d84f0522a
docs: revamp and unify multi-language readme documentation
- Remove the Table of Contents section to simplify documentation.
- Add and reorganize introduction sections for a clearer project overview.
- Rename and clarify section titles for improved structure and navigation.
- Consolidate and expand explanatory text around SSH key setup, OpenSSH compatibility, security, and troubleshooting.
- Provide richer descriptions for core concepts and advanced SSH usage scenarios.
- Apply the same documentation improvements and structural changes across English, Simplified Chinese, and Traditional Chinese readme files for consistency.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 11:52:09 +08:00
appleboy
c7fbbc9208
docs: add table of contents to multilingual README files
- Add a table of contents section to the English, Simplified Chinese, and Traditional Chinese readme files

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 09:53:26 +08:00
appleboy
b80f638dc4
docs: rewrite and unify documentation across all supported languages
- Rewrite and reorganize documentation for clarity and readability, including reworded introductions and consistent headings.
- Improve input parameter tables: clarify descriptions, unify formatting, and better explain parameter purposes across all three languages.
- Expand and update step-by-step SSH key setup guides, streamline copy instructions, and add practical notes and tips.
- Enhance usage examples with clearer titles, better labels, and updated YAML examples for different authentication methods and scenarios.
- Add new sections and tips on OpenSSH compatibility and troubleshooting "command not found" issues, with improved cross-platform guidance.
- Refine explanations for host fingerprint verification, proxy setup, and command environment management.
- Update and polish contributing and license sections for greater encouragement and style consistency.
- Apply the above documentation improvements to both Simplified and Traditional Chinese versions for parity.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-04-27 09:47:26 +08:00
Bo-Yi Wu
0e19dd962d
chore: improve robustness and consistency across multiple scripts
- Combine `errexit`, `nounset`, and `pipefail` options into a single `set -euo pipefail` command

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2025-04-10 16:56:18 +08:00
Bo-Yi Wu
bd83ba7e2b
docs: document and configure drone-ssh version usage (#381)
- Add `version` entry to README.md specifying drone-ssh binary version usage
- Add `version` entry to README.zh-cn.md specifying drone-ssh version usage in Chinese
- Add `version` entry to README.zh-tw.md specifying drone-ssh version usage in Traditional Chinese
- Add `version` input to action.yml with description for drone-ssh version
- Set DRONE_SSH_VERSION environment variable in action.yml to use specified version input

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2025-04-10 14:47:33 +08:00
appleboy
9ca1cd2174
docs: document the new curl_insecure configuration option
- Add `curl_insecure` option to README.md
- Add `curl_insecure` option to README.zh-cn.md
- Add `curl_insecure` option to README.zh-tw.md

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-29 12:46:43 +08:00
appleboy
20d5c5bbc9
feat: add configurable curl insecure flag to GitHub action
- Add input parameter `curl_insecure` to `action.yml` with a default value of false
- Pass `curl_insecure` input to the action's environment in `action.yml`
- Modify `entrypoint.sh` to conditionally add the `--insecure` option to curl if `INPUT_CURL_INSECURE` is true

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-29 12:43:09 +08:00
appleboy
b27b9f8968
chore: refactor system to improve efficiency and update API usage
- Update changelog order value from `4` to `5`

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-29 00:29:34 +08:00
appleboy
689de3cf64
docs: improve CLI messaging and error clarity for users
- Clarify error message for unsupported platforms
- Clarify error message for unsupported architectures
- Change download message to indicate ongoing action
- Expand CLI version header for clarity

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-29 00:27:32 +08:00
Bo-Yi Wu
b6690ee817
refactor: improve error handling and code readability across scripts (#374)
- Add `log_error` function for error handling
- Simplify the detection of client platform and architecture
- Use `log_error` for unsupported platform or architecture handling
- Use consistent quoting for variable expansions
- Improve readability for `curl` and `chmod` commands
- Simplify the commands for running and capturing stdout

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-29 00:25:15 +08:00
Bo-Yi Wu
52a1840ca6
docs: update SSH action version to v1 in all README files (#372)
- Update 'appleboy/ssh-action' version from 'v1.2.2' to 'v1' in various locations in the README.md file
- Update 'appleboy/ssh-action' version from 'v1.2.2' to 'v1' in various locations in README.zh-cn.md
- Update 'appleboy/ssh-action' version from 'v1.2.2' to 'v1' in various locations in README.zh-tw.md

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-15 15:01:18 +08:00
appleboy
2b3c6504b3
ci: unify and enhance GitHub workflow configurations
- Update appleboy/ssh-action to use the generic v1 version instead of v1.2.2 for multiple steps within the workflow

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-15 14:57:10 +08:00
appleboy
2ead5e3657
chore: update action version across workflows and documentation
- Update the version of `appleboy/ssh-action` from `v1.2.1` to `v1.2.2` in multiple files
- Modify the bug report template to reflect the updated action version
- Change the action version in the stable workflow file
- Adjust the action version in the README files for consistency across documentation
- Ensure the action version is updated in both Chinese language README files

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-09 22:08:40 +08:00
appleboy
a0a0326939
docs: clarify parameter descriptions for improved documentation
- Update descriptions for various input parameters to provide clearer guidance on their usage.
- Enhance the description for the `capture_stdout` parameter to specify its effect on action output.
- Modify the description for the `stdout` output to clarify its relation to the `capture_stdout` setting.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-09 22:02:08 +08:00
appleboy
b0a8f324e1
chore: bump DRONE_SSH version to 1.8.1
- Update the default version of DRONE_SSH from 1.8.0 to 1.8.1

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-09 21:54:21 +08:00
appleboy
039c9e07bb
docs: update README with private key instructions in multiple languages
- Add instructions for copying the private key to GitHub Secrets in English, Chinese (Simplified), and Chinese (Traditional) versions of the README.

ref: https://github.com/appleboy/ssh-action/issues/6#issuecomment-922368411
Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-08 15:55:34 +08:00
appleboy
48992f2e2c
docs: prioritize English in language selection options
- Change the language options to include English as the first option.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-08 15:50:53 +08:00
appleboy
01a53594eb
docs: enhance language support and improve documentation clarity
- Add Simplified Chinese as an option in the language selection
- Improve the phrasing of sentences for clarity in the GitHub Action description
- Update instructions for enabling synchronous execution for multiple hosts
- Clarify the default behavior for the cipher option
- Change the wording for SSH command execution to enhance readability
- Update the username in the example to a specific value
- Revise instructions for copying SSH keys to include installation steps for the `clip` command
- Adjust the phrasing for security practices regarding private key protection
- Update the license statement to specify the MIT license more clearly
- Change section titles for better consistency and clarity across languages

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-08 15:47:51 +08:00
appleboy
d99ccf8c09
docs: improve documentation clarity and consistency
- Change "GitHub Action" to "A GitHub Action" for clarity.
- Update phrasing from "built using" to "built with" for consistency.
- Revise "Make sure to follow the below steps" to "Follow the steps below" for improved readability.
- Modify "best practice is create" to "It is best practice to create" for grammatical correctness.
- Change "Add newly generated key into Authorized keys" to "Add the newly generated key to the Authorized keys" for clarity.
- Update "Copy Private Key content and paste in Github Secrets" to "Copy the Private Key content and paste it into GitHub Secrets" for consistency.
- Change "install `clip` command" to "install the `clip` command" for grammatical correctness.
- Revise "See the detail information about" to "See detailed information about" for improved readability.
- Update "A note from one of our readers" to "Note: Depending on your version of SSH" for clarity.
- Change "Make sure that your key algorithm of choice is supported" to "Ensure that your chosen key algorithm is supported" for conciseness.
- Revise "Alternatively, `ed25519` keys are accepted by default" to "Alternatively, `ed25519` keys are accepted by default in OpenSSH" for clarity.
- Update "if you are running a command in a non interactive shell" to "If you are running a command in a non-interactive shell" for grammatical correctness.

Signed-off-by: appleboy <appleboy.tw@gmail.com>
2025-03-08 15:42:40 +08:00
Bo-Yi Wu
92737056c0
docs: improve documentation and defaults for execution and security
- Clarify that synchronous execution is enabled if multiple hosts are specified
- Specify that sensible defaults are used for allowed cipher algorithms if unspecified
- Clarify that environment variables are passed to the shell script

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
2025-03-07 08:10:39 +08:00
Seth Landry
9817ef4a17
docs(readme): set -e for script_stop functionality (#368)
Fixes #367

Add a note in the "Input variables" section of `README.md` to mention that users can add `set -e` in their shell script to achieve similar functionality to the removed `script_stop` option.

Add a note in the "输入变量" section of `README.zh-cn.md` to mention that users can add `set -e` in their shell script to achieve similar functionality to the removed `script_stop` option.

Add a note in the "輸入變數" section of `README.zh-tw.md` to mention that users can add `set -e` in their shell script to achieve similar functionality to the removed `script_stop` option.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/appleboy/ssh-action/issues/367?shareId=XXXX-XXXX-XXXX-XXXX).
2025-02-24 20:31:51 +08:00
9 changed files with 823 additions and 535 deletions

View File

@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1.2.2
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}

View File

@ -51,6 +51,21 @@ jobs:
port: 2222
script_path: testdata/test.sh
# https://github.com/appleboy/ssh-action/issues/377
- name: multiple commands
uses: ./
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
password: password
port: 2222
script: |
mkdir -p /tmp/test
echo "hello world" > /tmp/test/hello.txt
cd /tmp/test
ls -al
cat /tmp/test/hello.txt
check-ssh-key:
runs-on: ubuntu-latest
steps:

View File

@ -31,7 +31,7 @@ jobs:
sleep 2
- name: ssh by username and password
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -43,7 +43,7 @@ jobs:
whoami
- name: ssh commands from a file
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -95,7 +95,7 @@ jobs:
sleep 2
- name: ssh by private key
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -104,7 +104,7 @@ jobs:
script: whoami
- name: wrong password but correct key
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -114,7 +114,7 @@ jobs:
script: whoami
- name: correct password but wrong key
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -167,7 +167,7 @@ jobs:
sleep 2
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -179,7 +179,7 @@ jobs:
ls -al
- name: missing ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
continue-on-error: true
with:
host: ${{ env.REMOTE_HOST }}
@ -192,7 +192,7 @@ jobs:
# https://github.com/appleboy/ssh-action/issues/75#issuecomment-668314271
- name: Multiline SSH commands interpreted as single lines
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -269,7 +269,7 @@ jobs:
# https://github.com/appleboy/ssh-action/issues/85
- name: Deployment to multiple hosts with different ports
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: "${{ env.REMOTE_HOST_01 }}:2222,${{ env.REMOTE_HOST_02 }}:2222"
username: linuxserver.io
@ -322,7 +322,7 @@ jobs:
sleep 2
- name: testing id_ed25519 key
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -375,7 +375,7 @@ jobs:
sleep 2
- name: testing id_ed25519 key
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io
@ -386,7 +386,7 @@ jobs:
ls -al
- name: pass environment
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
env:
FOO: "BAR"
with:
@ -400,7 +400,7 @@ jobs:
echo "I am $BAR, thanks"
- name: pass multiple environment
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
env:
FOO: "BAR"
BAR: "FOO"
@ -419,7 +419,7 @@ jobs:
echo "port: $PORT"
- name: custom envs format
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
env:
FOO: "BAR"
AAA: "BBB"
@ -437,7 +437,7 @@ jobs:
echo "I am $TEST_AAA, thanks"
- name: pass all ENV variables to script
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
env:
INPUT_FOO: "BAR"
INPUT_AAA: "BBB"
@ -454,7 +454,7 @@ jobs:
echo "$GITHUB_REF"
- name: switch to root user
uses: appleboy/ssh-action@v1.2.1
uses: appleboy/ssh-action@v1
with:
host: ${{ env.REMOTE_HOST }}
username: linuxserver.io

View File

@ -24,5 +24,5 @@ changelog:
order: 4
- title: "Documentation updates"
regexp: ^.*?docs?(\(.+\))??!?:.+$
order: 4
order: 5
- title: Others

360
README.md
View File

@ -1,69 +1,138 @@
# 🚀 SSH for GitHub Actions
[繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md)
English | [繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md)
[GitHub Action](https://github.com/features/actions) for executing remote SSH commands.
## Table of Contents
- [🚀 SSH for GitHub Actions](#-ssh-for-github-actions)
- [Table of Contents](#table-of-contents)
- [📖 Introduction](#-introduction)
- [🧩 Core Concepts \& Input Parameters](#-core-concepts--input-parameters)
- [🔌 Connection Settings](#-connection-settings)
- [🛠️ SSH Command Settings](#-ssh-command-settings)
- [🌐 Proxy Settings](#-proxy-settings)
- [⚡ Quick Start](#-quick-start)
- [🔑 SSH Key Setup \& OpenSSH Compatibility](#-ssh-key-setup--openssh-compatibility)
- [Setting Up SSH Keys](#setting-up-ssh-keys)
- [Generate RSA key](#generate-rsa-key)
- [Generate ED25519 key](#generate-ed25519-key)
- [OpenSSH Compatibility](#openssh-compatibility)
- [🛠️ Usage Scenarios \& Advanced Examples](#-usage-scenarios--advanced-examples)
- [Using password authentication](#using-password-authentication)
- [Using private key authentication](#using-private-key-authentication)
- [Multiple commands](#multiple-commands)
- [Run commands from a file](#run-commands-from-a-file)
- [Multiple hosts](#multiple-hosts)
- [Multiple hosts with different ports](#multiple-hosts-with-different-ports)
- [Synchronous execution on multiple hosts](#synchronous-execution-on-multiple-hosts)
- [Pass environment variables to shell script](#pass-environment-variables-to-shell-script)
- [🌐 Proxy \& Jump Host Usage](#-proxy--jump-host-usage)
- [🛡️ Security Best Practices](#-security-best-practices)
- [Protecting Your Private Key](#protecting-your-private-key)
- [Host Fingerprint Verification](#host-fingerprint-verification)
- [🚨 Error Handling \& Troubleshooting](#-error-handling--troubleshooting)
- [Q\&A](#qa)
- [Command not found (npm or other command)](#command-not-found-npm-or-other-command)
- [🤝 Contributing](#-contributing)
- [📝 License](#-license)
---
## 📖 Introduction
**SSH for GitHub Actions** is a powerful [GitHub Action](https://github.com/features/actions) for executing remote SSH commands easily and securely in your CI/CD workflows.
Built with [Golang](https://go.dev) and [drone-ssh](https://github.com/appleboy/drone-ssh), it supports a wide range of SSH scenarios, including multi-host, proxy, and advanced authentication.
![ssh workflow](./images/ssh-workflow.png)
[![testing main branch](https://github.com/appleboy/ssh-action/actions/workflows/main.yml/badge.svg)](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
This project is built using [Golang](https://go.dev) and [drone-ssh](https://github.com/appleboy/drone-ssh). 🚀
---
## Input variables
## 🧩 Core Concepts & Input Parameters
See [action.yml](./action.yml) for more detailed information.
This action provides flexible SSH command execution with a rich set of configuration options.
| Input Parameter | Description | Default Value |
| ------------------------- | ---------------------------------------------------------------------------------------- | ------------- |
| host | SSH host address | |
| port | SSH port number | 22 |
| passphrase | SSH key passphrase | |
| username | SSH username | |
| password | SSH password | |
| protocol | SSH protocol version (tcp, tcp4, tcp6) | tcp |
| sync | Enable synchronous execution if multiple hosts | false |
| use_insecure_cipher | Include more ciphers with use_insecure_cipher | false |
| cipher | Allowed cipher algorithms. If unspecified, a sensible default | |
| timeout | Timeout duration for SSH to host | 30s |
| command_timeout | Timeout duration for SSH command | 10m |
| key | Content of SSH private key. e.g., raw content of ~/.ssh/id_rsa | |
| key_path | Path of SSH private key | |
| fingerprint | SHA256 fingerprint of the host public key | |
| proxy_host | SSH proxy host | |
| proxy_port | SSH proxy port | 22 |
| proxy_protocol | SSH proxy protocol version (tcp, tcp4, tcp6) | tcp |
| proxy_username | SSH proxy username | |
| proxy_password | SSH proxy password | |
| proxy_passphrase | SSH proxy key passphrase | |
| proxy_timeout | Timeout for SSH to proxy host | 30s |
| proxy_key | Content of SSH proxy private key | |
| proxy_key_path | Path of SSH proxy private key | |
| proxy_fingerprint | SHA256 fingerprint of the proxy host public key | |
| proxy_cipher | Allowed cipher algorithms for the proxy | |
| proxy_use_insecure_cipher | Include more ciphers with use_insecure_cipher for the proxy | false |
| script | Execute commands | |
| script_path | Execute commands from a file | |
| envs | Pass environment variables to shell script | |
| envs_format | Flexible configuration of environment value transfer | |
| debug | Enable debug mode | false |
| allenvs | Pass the environment variables with prefix value of `GITHUB_` and `INPUT_` to the script | false |
| request_pty | Request a pseudo-terminal from the server | false |
For full details, see [action.yml](./action.yml).
## Usage
### 🔌 Connection Settings
Executing remote SSH commands.
These parameters control how the action connects to your remote host.
| Parameter | Description | Default |
| ------------------- | ----------------------------------------------------------------- | ------- |
| host | SSH host address | |
| port | SSH port number | 22 |
| username | SSH username | |
| password | SSH password | |
| protocol | SSH protocol version (`tcp`, `tcp4`, `tcp6`) | tcp |
| sync | Run synchronously if multiple hosts are specified | false |
| timeout | Timeout for SSH connection to host | 30s |
| key | Content of SSH private key (e.g., raw content of `~/.ssh/id_rsa`) | |
| key_path | Path to SSH private key | |
| passphrase | Passphrase for the SSH private key | |
| fingerprint | SHA256 fingerprint of the host public key | |
| use_insecure_cipher | Allow additional (less secure) ciphers | false |
| cipher | Allowed cipher algorithms. Uses sensible defaults if unspecified | |
---
### 🛠️ SSH Command Settings
These parameters control the commands executed on the remote host and related behaviors.
| Parameter | Description | Default |
| --------------- | --------------------------------------------------------------------------------- | ------- |
| script | Commands to execute remotely | |
| script_path | Path to a file containing commands to execute | |
| envs | Environment variables to pass to the shell script | |
| envs_format | Flexible configuration for environment variable transfer | |
| allenvs | Pass all environment variables with `GITHUB_` and `INPUT_` prefixes to the script | false |
| command_timeout | Timeout for SSH command execution | 10m |
| debug | Enable debug mode | false |
| request_pty | Request a pseudo-terminal from the server | false |
| curl_insecure | Allow curl to connect to SSL sites without certificates | false |
| version | drone-ssh binary version. If not specified, the latest version will be used. | |
---
### 🌐 Proxy Settings
These parameters control the use of a proxy (jump host) for connecting to your target host.
| Parameter | Description | Default |
| ------------------------- | ----------------------------------------------- | ------- |
| proxy_host | SSH proxy host | |
| proxy_port | SSH proxy port | 22 |
| proxy_username | SSH proxy username | |
| proxy_password | SSH proxy password | |
| proxy_passphrase | SSH proxy key passphrase | |
| proxy_protocol | SSH proxy protocol version | tcp |
| proxy_timeout | Timeout for SSH connection to proxy host | 30s |
| proxy_key | Content of SSH proxy private key | |
| proxy_key_path | Path to SSH proxy private key | |
| proxy_fingerprint | SHA256 fingerprint of the proxy host public key | |
| proxy_cipher | Allowed cipher algorithms for the proxy | |
| proxy_use_insecure_cipher | Allow insecure ciphers for the proxy | false |
> **Note:** To mimic the removed `script_stop` option, add `set -e` at the top of your shell script.
---
## ⚡ Quick Start
Run remote SSH commands in your workflow with minimal configuration:
```yaml
name: remote ssh command
name: Remote SSH Command
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
- name: Execute remote SSH commands using password
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: linuxserver.io
@ -72,7 +141,7 @@ jobs:
script: whoami
```
output:
**Output:**
```sh
======CMD======
@ -84,50 +153,37 @@ linuxserver.io
===============================================
```
### Setting up a SSH Key
---
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:
## 🔑 SSH Key Setup & OpenSSH Compatibility
### Generate rsa key
### Setting Up SSH Keys
It is best practice to create SSH keys on your local machine (not on a remote server). Log in with the username specified in GitHub Secrets and generate a key pair:
#### Generate RSA key
```bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
### Generate ed25519 key
#### Generate ED25519 key
```bash
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/).
### Add rsa key into Authorized keys
Add the new public key to the authorized keys on your server. [Learn more about authorized keys.](https://www.ssh.com/ssh/authorized_keys/)
```bash
cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
# Add RSA key
cat .ssh/id_rsa.pub | ssh user@host 'cat >> .ssh/authorized_keys'
# Add ED25519 key
cat .ssh/id_ed25519.pub | ssh user@host 'cat >> .ssh/authorized_keys'
```
### Add ed25519 key into Authorized keys
```bash
cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys'
```
Copy Private Key content and paste in Github Secrets.
### Copy rsa Private key
Before copying the private key, install `clip` command as shown below:
```bash
# Ubuntu
sudo apt-get install xclip
```
copy the private key:
Copy the private key content and paste it into GitHub Secrets.
```bash
# macOS
@ -136,7 +192,9 @@ pbcopy < ~/.ssh/id_rsa
xclip < ~/.ssh/id_rsa
```
### Copy ed25519 Private key
> **Tip:** Copy from `-----BEGIN OPENSSH PRIVATE KEY-----` to `-----END OPENSSH PRIVATE KEY-----` (inclusive).
For ED25519:
```bash
# macOS
@ -145,41 +203,45 @@ pbcopy < ~/.ssh/id_ed25519
xclip < ~/.ssh/id_ed25519
```
See the detail information about [SSH login without password](http://www.linuxproblem.org/art_9.html).
See more: [SSH login without a 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:
> **Note:** Depending on your SSH version, you may also need to:
>
> - Place the public key in `.ssh/authorized_keys2`
> - Set `.ssh` permissions to 700
> - Set `.ssh/authorized_keys2` permissions to 640
- Put the public key in `.ssh/authorized_keys2`
- Change the permissions of `.ssh` to 700
- Change the permissions of `.ssh/authorized_keys2` to 640
### OpenSSH Compatibility
### If you are using OpenSSH
If you are currently using OpenSSH and are getting the following error:
If you see this 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/`):
On Ubuntu 20.04+ you may need to explicitly allow the `ssh-rsa` algorithm. Add this to your OpenSSH daemon config (`/etc/ssh/sshd_config` or a drop-in 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:
Alternatively, use ED25519 keys (supported by default):
```bash
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
### Example
---
#### Executing remote ssh commands using password
## 🛠️ Usage Scenarios & Advanced Examples
This section covers common and advanced usage patterns, including multi-host, proxy, and environment variable passing.
### Using password authentication
```yaml
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
- name: Execute remote SSH commands using password
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -188,11 +250,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
script: whoami
```
#### Using private key
### Using private key authentication
```yaml
- name: executing remote ssh commands using ssh key
uses: appleboy/ssh-action@v1.2.1
- name: Execute remote SSH commands using SSH key
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -201,11 +263,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
script: whoami
```
#### Multiple Commands
### Multiple commands
```yaml
- name: multiple command
uses: appleboy/ssh-action@v1.2.1
- name: Multiple commands
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -218,11 +280,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
![result](./images/output-result.png)
#### Commands from a file
### Run commands from a file
```yaml
- name: file commands
uses: appleboy/ssh-action@v1.2.1
- name: File commands
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -231,11 +293,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
script_path: scripts/script.sh
```
#### Multiple Hosts
### Multiple hosts
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: Multiple hosts
uses: appleboy/ssh-action@v1
with:
- host: "foo.com"
+ host: "foo.com,bar.com"
@ -247,13 +309,13 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
ls -al
```
The default value of `port` is `22`.
Default `port` is `22`.
#### Multiple hosts with different port
### Multiple hosts with different ports
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: Multiple hosts
uses: appleboy/ssh-action@v1
with:
- host: "foo.com"
+ host: "foo.com:1234,bar.com:5678"
@ -264,11 +326,11 @@ The default value of `port` is `22`.
ls -al
```
#### Synchronous execution on multiple hosts
### Synchronous execution on multiple hosts
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: Multiple hosts
uses: appleboy/ssh-action@v1
with:
host: "foo.com,bar.com"
+ sync: true
@ -280,11 +342,11 @@ The default value of `port` is `22`.
ls -al
```
#### Pass environment variable to shell script
### Pass environment variables to shell script
```diff
- name: pass environment
uses: appleboy/ssh-action@v1.2.1
- name: Pass environment
uses: appleboy/ssh-action@v1
+ env:
+ FOO: "BAR"
+ BAR: "FOO"
@ -301,9 +363,13 @@ The default value of `port` is `22`.
echo "sha: $SHA"
```
_Inside `env` object, you need to pass every environment variable as a string, passing `Integer` data type or any other may output unexpected results._
> _All environment variables in the `env` object must be strings. Using integers or other types may cause unexpected results._
#### How to connect remote server using `ProxyCommand`?
---
## 🌐 Proxy & Jump Host Usage
You can connect to remote hosts via a proxy (jump host) for advanced network topologies.
```bash
+--------+ +----------+ +-----------+
@ -311,7 +377,7 @@ _Inside `env` object, you need to pass every environment variable as a string, p
+--------+ +----------+ +-----------+
```
in your `~/.ssh/config`, you will see the following.
Example `~/.ssh/config`:
```bash
Host Jumphost
@ -327,11 +393,11 @@ Host FooServer
ProxyCommand ssh -q -W %h:%p Jumphost
```
#### How to convert to YAML format of GitHubActions
**GitHub Actions YAML:**
```diff
- name: ssh proxy command
uses: appleboy/ssh-action@v1.2.1
- name: SSH proxy command
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -346,15 +412,17 @@ Host FooServer
ls -al
```
#### 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.
## 🛡️ Security Best Practices
### Protecting Your Private Key
A passphrase encrypts your private key, making it useless to attackers if leaked. Always store your private key securely.
```diff
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
- name: SSH key passphrase
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -366,21 +434,19 @@ It is not uncommon for files to leak from backups or decommissioned hardware, an
ls -al
```
#### Using host fingerprint verification
### Host Fingerprint Verification
Setting up SSH host fingerprint verification can help to prevent Person-in-the-Middle attacks. Before setting this up, run the command below to get your SSH host fingerprint. Remember to replace `ed25519` with your appropriate key type (`rsa`, `dsa`, etc.) that your server is using and `example.com` with your host.
In modern OpenSSH releases, the _default_ key types to be fetched are `rsa` (since version 5.1), `ecdsa` (since version 6.0), and `ed25519` (since version 6.7).
Verifying the SSH host fingerprint helps prevent man-in-the-middle attacks. To get your host's fingerprint (replace `ed25519` with your key type and `example.com` with your host):
```sh
ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2
```
Now you can adjust you config:
Update your config:
```diff
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
- name: SSH key passphrase
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -392,33 +458,33 @@ Now you can adjust you config:
ls -al
```
## Q&A
---
### Command not found (npm or other command)
## 🚨 Error Handling & Troubleshooting
See the [issue comment](https://github.com/appleboy/ssh-action/issues/31#issuecomment-1006565847) about interactive vs non interactive shell. Thanks @kocyigityunus for the solution.
### Q&A
Basically, if you are running a command in a non interactive shell, like ssh-action, on many linux distros,
#### Command not found (npm or other command)
`/etc/bash.bashrc` file has a specific command that returns only, so some of the files didn't run and some specific commands doesn't add to path,
If you encounter "command not found" errors, see [this issue comment](https://github.com/appleboy/ssh-action/issues/31#issuecomment-1006565847) about interactive vs non-interactive shells.
On many Linux distros, `/etc/bash.bashrc` contains:
```sh
# /etc/bash.bashrc
# System-wide .bashrc file for interactive bash(1) shells.
# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.
# If not running interactively, don't do anything
[ -z "$PS1" ] && return`
[ -z "$PS1" ] && return
```
just comment out the line that returns early and everything should work fine, or you can use the real paths of the commands that you would like to use.
Comment out this line or use absolute paths for your commands.
## Contributing
---
We would love for you to contribute to `appleboy/ssh-action`, pull requests are welcome!
## 🤝 Contributing
## License
Contributions are welcome! Please submit a pull request to help improve `appleboy/ssh-action`.
The scripts and documentation in this project are released under the [MIT License](LICENSE)
---
## 📝 License
This project is licensed under the [MIT License](LICENSE).

View File

@ -1,168 +1,247 @@
# 🚀 用于 GitHub Actions 的 SSH
[English](./README.md) | [繁體中文](./README.zh-tw.md)
[English](./README.md) | [繁體中文](./README.zh-tw.md) | 简体中文
[GitHub Action](https://github.com/features/actions) 用于执行远程 SSH 命令。
## 目录
- [🚀 用于 GitHub Actions 的 SSH](#-用于-github-actions-的-ssh)
- [目录](#目录)
- [📖 简介](#-简介)
- [🧩 核心概念与输入参数](#-核心概念与输入参数)
- [🔌 连接设置](#-连接设置)
- [🛠️ 指令设置](#-指令设置)
- [🌐 代理设置](#-代理设置)
- [⚡ 快速开始](#-快速开始)
- [🔑 SSH 密钥配置与 OpenSSH 兼容性](#-ssh-密钥配置与-openssh-兼容性)
- [配置 SSH 密钥](#配置-ssh-密钥)
- [生成 RSA 密钥](#生成-rsa-密钥)
- [生成 ED25519 密钥](#生成-ed25519-密钥)
- [OpenSSH 兼容性](#openssh-兼容性)
- [🛠️ 用法场景与进阶示例](#-用法场景与进阶示例)
- [使用密码认证](#使用密码认证)
- [使用私钥认证](#使用私钥认证)
- [多条命令](#多条命令)
- [从文件执行命令](#从文件执行命令)
- [多主机](#多主机)
- [多主机不同端口](#多主机不同端口)
- [多主机同步执行](#多主机同步执行)
- [传递环境变量到 shell 脚本](#传递环境变量到-shell-脚本)
- [🌐 代理与跳板机用法](#-代理与跳板机用法)
- [🛡️ 安全最佳实践](#-安全最佳实践)
- [保护你的私钥](#保护你的私钥)
- [主机指纹验证](#主机指纹验证)
- [🚨 错误处理与疑难解答](#-错误处理与疑难解答)
- [常见问题](#常见问题)
- [命令未找到npm 或其他命令)](#命令未找到npm-或其他命令)
- [🤝 贡献](#-贡献)
- [📝 许可证](#-许可证)
---
## 📖 简介
**SSH for GitHub Actions** 是一个强大的 [GitHub Action](https://github.com/features/actions),可让你在 CI/CD 工作流中轻松且安全地执行远程 SSH 命令。
本项目基于 [Golang](https://go.dev) 和 [drone-ssh](https://github.com/appleboy/drone-ssh) 构建,支持多主机、代理、高级认证等多种 SSH 场景。
![ssh workflow](./images/ssh-workflow.png)
[![testing main branch](https://github.com/appleboy/ssh-action/actions/workflows/main.yml/badge.svg)](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
该项目使用 [Golang](https://go.dev) 和 [drone-ssh](https://github.com/appleboy/drone-ssh) 构建。🚀
---
## 输入变量
## 🧩 核心概念与输入参数
更详细的信息,请参考 [action.yml](./action.yml)。
本 Action 提供灵活的 SSH 命令执行能力,并具备丰富的配置选项
| 输入参数 | 描述 | 默认值 |
| ------------------------- | ----------------------------------------------------- | ------ |
| host | SSH 主机地址 | |
| port | SSH 端口号 | 22 |
| passphrase | SSH 密钥密码短语 | |
| username | SSH 用户名 | |
| password | SSH 密码 | |
| protocol | SSH 协议版本tcp, tcp4, tcp6 | tcp |
| sync | 如果有多个主机,启用同步执行 | false |
| use_insecure_cipher | 使用不安全的密码算法 | false |
| cipher | 允许的密码算法。如果未指定,则使用适当的算法 | |
| timeout | SSH 连接到主机的超时时间 | 30s |
| command_timeout | SSH 命令的超时时间 | 10m |
| key | SSH 私钥的内容,例如 ~/.ssh/id_rsa 的原始内容 | |
| key_path | SSH 私钥的路径 | |
| fingerprint | 主机公钥的 SHA256 指纹 | |
| proxy_host | SSH 代理主机 | |
| proxy_port | SSH 代理端口 | 22 |
| proxy_protocol | SSH 代理协议版本tcp, tcp4, tcp6 | tcp |
| proxy_username | SSH 代理用户名 | |
| proxy_password | SSH 代理密码 | |
| proxy_passphrase | SSH 代理密钥密码短语 | |
| proxy_timeout | SSH 连接到代理主机的超时时间 | 30s |
| proxy_key | SSH 代理私钥的内容 | |
| proxy_key_path | SSH 代理私钥的路径 | |
| proxy_fingerprint | 代理主机公钥的 SHA256 指纹 | |
| proxy_cipher | 代理允许的密码算法 | |
| proxy_use_insecure_cipher | 使用不安全的密码算法 | false |
| script | 执行命令 | |
| script_path | 从文件执行命令 | |
| envs | 传递环境变量到 shell 脚本 | |
| envs_format | 环境变量传递的灵活配置 | |
| debug | 启用调试模式 | false |
| allenvs | 将带有 `GITHUB_``INPUT_` 前缀的环境变量传递给脚本 | false |
| request_pty | 请求伪终端 | false |
详细参数请参阅 [action.yml](./action.yml)。
## 使用方法
### 🔌 连接设置
执行远程 SSH 命令
这些参数用于控制如何连接到远程主机。
| 参数 | 描述 | 默认值 |
| ------------------- | --------------------------------------------- | ------ |
| host | SSH 主机地址 | |
| port | SSH 端口号 | 22 |
| username | SSH 用户名 | |
| password | SSH 密码 | |
| protocol | SSH 协议版本(`tcp``tcp4``tcp6` | tcp |
| sync | 指定多个主机时同步执行 | false |
| timeout | SSH 连接主机的超时时间 | 30s |
| key | SSH 私钥内容(如 `~/.ssh/id_rsa` 的原始内容) | |
| key_path | SSH 私钥路径 | |
| passphrase | SSH 私钥密码短语 | |
| fingerprint | 主机公钥的 SHA256 指纹 | |
| use_insecure_cipher | 允许额外(不安全)的加密算法 | false |
| cipher | 允许的加密算法,未指定时使用默认值 | |
---
### 🛠️ 指令设置
这些参数用于控制在远程主机上执行的命令及相关行为。
| 参数 | 描述 | 默认值 |
| --------------- | ----------------------------------------------------- | ------ |
| script | 远程执行的命令 | |
| script_path | 包含要执行命令的文件路径 | |
| envs | 传递给 shell 脚本的环境变量 | |
| envs_format | 环境变量传递的灵活配置 | |
| allenvs | 传递所有带 `GITHUB_``INPUT_` 前缀的环境变量到脚本 | false |
| command_timeout | SSH 命令执行超时时间 | 10m |
| debug | 启用调试模式 | false |
| request_pty | 向服务器请求伪终端 | false |
| curl_insecure | 允许 curl 连接无证书的 SSL 站点 | false |
| version | drone-ssh 二进制版本,未指定时使用最新版本 | |
---
### 🌐 代理设置
这些参数用于通过代理(跳板机)连接到目标主机。
| 参数 | 描述 | 默认值 |
| ------------------------- | ----------------------------------------- | ------ |
| proxy_host | SSH 代理主机 | |
| proxy_port | SSH 代理端口 | 22 |
| proxy_username | SSH 代理用户名 | |
| proxy_password | SSH 代理密码 | |
| proxy_passphrase | SSH 代理私钥密码短语 | |
| proxy_protocol | SSH 代理协议版本(`tcp``tcp4``tcp6` | tcp |
| proxy_timeout | SSH 连接代理主机的超时时间 | 30s |
| proxy_key | SSH 代理私钥内容 | |
| proxy_key_path | SSH 代理私钥路径 | |
| proxy_fingerprint | 代理主机公钥的 SHA256 指纹 | |
| proxy_cipher | 代理允许的加密算法 | |
| proxy_use_insecure_cipher | 代理允许额外(不安全)的加密算法 | false |
> **注意:** 如需实现已移除的 `script_stop` 功能,请在 shell 脚本顶部添加 `set -e`
---
## ⚡ 快速开始
只需简单配置,即可在工作流中执行远程 SSH 命令:
```yaml
name: remote ssh command
name: Remote SSH Command
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
- name: 执行远程 SSH 命令(密码认证)
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
username: linuxserver.io
password: ${{ secrets.PASSWORD }}
port: ${{ secrets.PORT }}
script: whoami
```
画面输出
**输出:**
```sh
======CMD======
whoami
======END======
out: ***
linuxserver.io
===============================================
✅ Successfully executed commands to all hosts.
===============================================
```
### 设置 SSH 密钥
---
请在创建 SSH 密钥并使用 SSH 密钥时遵循以下步骤。最佳做法是在本地机器上创建 SSH 密钥而不是远程机器上。请使用 Github Secrets 中指定的用户名登录。生成 RSA 密钥:
## 🔑 SSH 密钥配置与 OpenSSH 兼容性
### 生成 RSA 密钥
### 配置 SSH 密钥
建议在本地机器(而非远程服务器)上创建 SSH 密钥。请使用 GitHub Secrets 中指定的用户名登录并生成密钥对:
#### 生成 RSA 密钥
```bash
ssh-keygen -t rsa -b 4096 -C ”your_email@example.com“
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
### 生成 ed25519 密钥
#### 生成 ED25519 密钥
```bash
ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
将新生成的密钥添加到已授权的密钥中。详细了解已授权的密钥请点[此处](https://www.ssh.com/ssh/authorized_keys/)。
### 将 RSA 密钥添加到已授权密钥中
将新生成的公钥添加到服务器的 authorized_keys。 [了解更多 authorized_keys](https://www.ssh.com/ssh/authorized_keys/)
```bash
cat .ssh/id_rsa.pub | ssh b@B cat >> .ssh/authorized_keys
# 添加 RSA 公钥
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'
```
### 将 ed25519 密钥添加到已授权密钥中
复制私钥内容并粘贴到 GitHub Secrets。
```bash
cat .ssh/id_ed25519.pub | ssh b@B cat >> .ssh/authorized_keys
# macOS
pbcopy < ~/.ssh/id_rsa
# Ubuntu
xclip < ~/.ssh/id_rsa
```
复制私钥内容,然后将其粘贴到 Github Secrets 中。
> **提示:** 复制内容需包含 `-----BEGIN OPENSSH PRIVATE KEY-----``-----END OPENSSH PRIVATE KEY-----`(含)
### 复制 rsa 私钥内容
ED25519 同理:
```bash
clip < ~/.ssh/id_rsa
# macOS
pbcopy < ~/.ssh/id_ed25519
# Ubuntu
xclip < ~/.ssh/id_ed25519
```
### 复制 ed25519 私钥内容
更多信息:[SSH 无密码登录](http://www.linuxproblem.org/art_9.html)。
```bash
clip < ~/.ssh/id_ed25519
```
> **注意:** 根据 SSH 版本,可能还需:
>
> - 将公钥放入 `.ssh/authorized_keys2`
> - 设置 `.ssh` 权限为 700
> - 设置 `.ssh/authorized_keys2` 权限为 640
有关无需密码登录 SSH 的详细信息,请[见该网站](http://www.linuxproblem.org/art_9.html)。
### OpenSSH 兼容性
**来自读者的注意事项** 根据您的 SSH 版本,您可能还需要进行以下更改:
- 将公钥放在 `.ssh/authorized_keys2`
- 将 `.ssh` 的权限更改为 700
- 将 `.ssh/authorized_keys2` 的权限更改为 640
### 如果你使用的是 OpenSSH
如果您正在使用 OpenSSH并出现以下错误
如果出现如下错误:
```bash
ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]
```
请确保您所选择的密钥算法得到支持。在 Ubuntu 20.04 或更高版本上,您必须明确允许使用 SSH-RSA 算法。请在 OpenSSH 守护进程文件中添加以下行(它可以是 `/etc/ssh/sshd_config``/etc/ssh/sshd_config.d/` 中的一个附加文件)
在 Ubuntu 20.04+,你可能需要显式允许 `ssh-rsa` 算法。请在 OpenSSH 配置文件(`/etc/ssh/sshd_config``/etc/ssh/sshd_config.d/` 下的 drop-in 文件)中添加:
```bash
CASignatureAlgorithms +ssh-rsa
```
或者,`Ed25519` 密钥在 OpenSSH 中默认被接受。如果需要,您可以使用它来替代 RSA。
或者,直接使用默认支持的 ED25519 密钥:
```bash
ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
### Example
---
#### 使用密码执行远程 SSH 命令
## 🛠️ 用法场景与进阶示例
本节涵盖常见与进阶用法,包括多主机、代理、环境变量传递等。
### 使用密码认证
```yaml
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
- name: 执行远程 SSH 命令(密码认证)
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -171,11 +250,11 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
script: whoami
```
#### 使用私钥
### 使用私钥认证
```yaml
- name: executing remote ssh commands using ssh key
uses: appleboy/ssh-action@v1.2.1
- name: 执行远程 SSH 命令(密钥认证)
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -184,11 +263,11 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
script: whoami
```
#### 多个命令
### 多条命令
```yaml
- name: multiple command
uses: appleboy/ssh-action@v1.2.1
- name: 多条命令
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -201,27 +280,11 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
![result](./images/output-result.png)
#### 多台主机
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
with:
- host: ”foo.com“
+ host: ”foo.com,bar.com“
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
whoami
ls -al
```
#### Commands from a file
### 从文件执行命令
```yaml
- name: file commands
uses: appleboy/ssh-action@v1.2.1
- name: 文件命令
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -230,14 +293,32 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
script_path: scripts/script.sh
```
####个不同端口的主机
### 多主机
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: 多主机
uses: appleboy/ssh-action@v1
with:
- host: ”foo.com“
+ host: ”foo.com:1234,bar.com:5678“
- host: "foo.com"
+ host: "foo.com,bar.com"
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
whoami
ls -al
```
默认 `port``22`
### 多主机不同端口
```diff
- name: 多主机
uses: appleboy/ssh-action@v1
with:
- host: "foo.com"
+ host: "foo.com:1234,bar.com:5678"
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
@ -245,13 +326,13 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
ls -al
```
#### 主机同步执行
### 多主机同步执行
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: 多主机
uses: appleboy/ssh-action@v1
with:
host: ”foo.com,bar.com“
host: "foo.com,bar.com"
+ sync: true
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
@ -261,14 +342,14 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
ls -al
```
#### 将环境变量传递到 Shell 脚本
### 传递环境变量到 shell 脚本
```diff
- name: pass environment
uses: appleboy/ssh-action@v1.2.1
- name: 传递环境变量
uses: appleboy/ssh-action@v1
+ env:
+ FOO: ”BAR“
+ BAR: ”FOO“
+ FOO: "BAR"
+ BAR: "FOO"
+ SHA: ${{ github.sha }}
with:
host: ${{ secrets.HOST }}
@ -277,22 +358,26 @@ ssh-keygen -t ed25519 -a 200 -C ”your_email@example.com“
port: ${{ secrets.PORT }}
+ envs: FOO,BAR,SHA
script: |
echo ”I am $FOO“
echo ”I am $BAR“
echo ”sha: $SHA“
echo "I am $FOO"
echo "I am $BAR"
echo "sha: $SHA"
```
_在 `env` 对象中,您需要将每个环境变量作为字符串传递,传递 `Integer` 数据类型或任何其他类型可能会产生意外结果。_
> _`env` 对象中的所有环境变量必须为字符串。传递整数或其他类型可能导致意外结果。_
#### 如何使用 `ProxyCommand` 连接远程服务器?
---
## 🌐 代理与跳板机用法
你可以通过代理(跳板机)连接到远程主机,适用于进阶网络拓扑。
```bash
+———+ +-———+ +————+
| Laptop | <—> | Jumphost | <—> | FooServer |
+———+ +-———+ +————+
+--------+ +----------+ +-----------+
| Laptop | <--> | Jumphost | <--> | FooServer |
+--------+ +----------+ +-----------+
```
在您的 `~/.ssh/config` 文件中,您会看到以下内容。
示例 `~/.ssh/config`
```bash
Host Jumphost
@ -308,11 +393,11 @@ Host FooServer
ProxyCommand ssh -q -W %h:%p Jumphost
```
#### 如何将其转换为 GitHubActions 的 YAML 格式?
**GitHub Actions YAML:**
```diff
- name: ssh proxy command
uses: appleboy/ssh-action@v1.2.1
- name: SSH 代理命令
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -327,13 +412,17 @@ Host FooServer
ls -al
```
#### 如何保护私钥?
---
密码短语通常用于加密私钥。这使得攻击者无法单独使用密钥文件。文件泄露可能来自备份或停用的硬件,黑客通常可以从受攻击系统中泄露文件。因此,保护私钥非常重要。
## 🛡️ 安全最佳实践
### 保护你的私钥
密码短语会加密你的私钥,即使泄露也无法被攻击者直接利用。请务必妥善保管私钥。
```diff
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
- name: SSH 密钥密码短语
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -345,21 +434,19 @@ Host FooServer
ls -al
```
#### 使用主机指纹验证
### 主机指纹验证
设置 SSH 主机指纹验证可以帮助防止中间人攻击。在设置之前,运行以下命令以获取 SSH 主机指纹。请记得将 `ed25519` 替换为您适当的密钥类型(`rsa``dsa`等),而 `example.com` 则替换为您的主机。
现代 OpenSSH 版本中,需要提取的**默认密钥**类型是 `rsa`(从版本 5.1 开始)、`ecdsa`(从版本 6.0 开始)和 `ed25519`(从版本 6.7 开始)。
验证 SSH 主机指纹有助于防止中间人攻击。获取主机指纹(将 `ed25519` 替换为你的密钥类型,`example.com` 替换为你的主机):
```sh
ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d -f2
ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2
```
现在您可以调整您的配置:
更新配置:
```diff
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
- name: SSH 密钥密码短语
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -371,10 +458,33 @@ ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d
ls -al
```
## 贡献
---
我们非常希望您为 `appleboy/ssh-action` 做出贡献,欢迎提交请求!
## 🚨 错误处理与疑难解答
## 授权方式
### 常见问题
本项目中的脚本和文档采用 [MIT](LICENSE) 许可证 发布。
#### 命令未找到npm 或其他命令)
如果遇到 "command not found" 错误,请参考 [此评论](https://github.com/appleboy/ssh-action/issues/31#issuecomment-1006565847) 了解交互式与非交互式 shell 的区别。
许多 Linux 发行版的 `/etc/bash.bashrc` 包含如下内容:
```sh
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
```
注释掉该行或使用命令的绝对路径。
---
## 🤝 贡献
欢迎贡献!请提交 Pull Request 改进 `appleboy/ssh-action`
---
## 📝 许可证
本项目采用 [MIT License](LICENSE) 授权。

View File

@ -1,168 +1,247 @@
# 🚀 GitHub Actions 的 SSH
[English](./README.md) | [简体中文](./README.zh-cn.md)
[English](./README.md) | 繁體中文 | [简体中文](./README.zh-cn.md)
[GitHub Action](https://github.com/features/actions) 用於執行遠端 SSH 命令。
## 目錄
- [🚀 GitHub Actions 的 SSH](#-github-actions-的-ssh)
- [目錄](#目錄)
- [📖 簡介](#-簡介)
- [🧩 核心概念與輸入參數](#-核心概念與輸入參數)
- [🔌 連線設定](#-連線設定)
- [🛠️ 指令設定](#-指令設定)
- [🌐 代理設定](#-代理設定)
- [⚡ 快速開始](#-快速開始)
- [🔑 SSH 金鑰設定與 OpenSSH 相容性](#-ssh-金鑰設定與-openssh-相容性)
- [設定 SSH 金鑰](#設定-ssh-金鑰)
- [產生 RSA 金鑰](#產生-rsa-金鑰)
- [產生 ED25519 金鑰](#產生-ed25519-金鑰)
- [OpenSSH 相容性](#openssh-相容性)
- [🛠️ 用法場景與進階範例](#-用法場景與進階範例)
- [使用密碼認證](#使用密碼認證)
- [使用私鑰認證](#使用私鑰認證)
- [多條指令](#多條指令)
- [從檔案執行指令](#從檔案執行指令)
- [多主機](#多主機)
- [多主機不同埠號](#多主機不同埠號)
- [多主機同步執行](#多主機同步執行)
- [傳遞環境變數到 shell 腳本](#傳遞環境變數到-shell-腳本)
- [🌐 代理與跳板機用法](#-代理與跳板機用法)
- [🛡️ 安全最佳實踐](#-安全最佳實踐)
- [保護你的私鑰](#保護你的私鑰)
- [主機指紋驗證](#主機指紋驗證)
- [🚨 錯誤處理與疑難排解](#-錯誤處理與疑難排解)
- [常見問題](#常見問題)
- [指令找不到npm 或其他指令)](#指令找不到npm-或其他指令)
- [🤝 貢獻](#-貢獻)
- [📝 授權](#-授權)
---
## 📖 簡介
**SSH for GitHub Actions** 是一個強大的 [GitHub Action](https://github.com/features/actions),可讓你在 CI/CD 工作流程中輕鬆且安全地執行遠端 SSH 指令。
本專案以 [Golang](https://go.dev) 和 [drone-ssh](https://github.com/appleboy/drone-ssh) 建立,支援多主機、代理、進階認證等多種 SSH 場景。
![ssh workflow](./images/ssh-workflow.png)
[![testing main branch](https://github.com/appleboy/ssh-action/actions/workflows/main.yml/badge.svg)](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
此專案使用 [Golang](https://go.dev) 和 [drone-ssh](https://github.com/appleboy/drone-ssh) 建立。🚀
---
## 輸入變數
## 🧩 核心概念與輸入參
請參閱 [action.yml](./action.yml) 以獲取更詳細的信息。
本 Action 提供彈性的 SSH 指令執行能力,並具備豐富的設定選項
| 輸入參數 | 描述 | 預設值 |
| ------------------------- | ----------------------------------------------------- | ------ |
| host | SSH 主機地址 | |
| port | SSH 埠號 | 22 |
| passphrase | SSH 金鑰密碼 | |
| username | SSH 使用者名稱 | |
| password | SSH 密碼 | |
| protocol | SSH 協議版本 (tcp, tcp4, tcp6) | tcp |
| sync | 如果有多個主機,啟用同步執行 | false |
| use_insecure_cipher | 包含更多不安全的加密算法 | false |
| cipher | 允許的加密算法。如果未指定,則使用合理的預設值 | |
| timeout | SSH 連接主機的超時時間 | 30s |
| command_timeout | SSH 命令的超時時間 | 10m |
| key | SSH 私鑰的內容。例如,~/.ssh/id_rsa 的原始內容 | |
| key_path | SSH 私鑰的路徑 | |
| fingerprint | 主機公鑰的 SHA256 指紋 | |
| proxy_host | SSH 代理主機 | |
| proxy_port | SSH 代理埠號 | 22 |
| proxy_protocol | SSH 代理協議版本 (tcp, tcp4, tcp6) | tcp |
| proxy_username | SSH 代理使用者名稱 | |
| proxy_password | SSH 代理密碼 | |
| proxy_passphrase | SSH 代理金鑰密碼 | |
| proxy_timeout | SSH 連接代理主機的超時時間 | 30s |
| proxy_key | SSH 代理私鑰的內容 | |
| proxy_key_path | SSH 代理私鑰的路徑 | |
| proxy_fingerprint | 代理主機公鑰的 SHA256 指紋 | |
| proxy_cipher | 代理允許的加密算法 | |
| proxy_use_insecure_cipher | 包含更多不安全的加密算法 | false |
| script | 執行命令 | |
| script_path | 從文件中執行命令 | |
| envs | 將環境變數傳遞給 shell 腳本 | |
| envs_format | 環境值傳遞的靈活配置 | |
| debug | 啟用調試模式 | false |
| allenvs | 將帶有 `GITHUB_``INPUT_` 前綴的環境變數傳遞給腳本 | false |
| request_pty | 從伺服器請求偽終端 | false |
完整參數請參閱 [action.yml](./action.yml)。
## 用法
### 🔌 連線設定
執行遠端 SSH 命令
這些參數用於控制如何連線到遠端主機。
| 參數 | 說明 | 預設值 |
| ------------------- | --------------------------------------------- | ------ |
| host | SSH 主機位址 | |
| port | SSH 埠號 | 22 |
| username | SSH 使用者名稱 | |
| password | SSH 密碼 | |
| protocol | SSH 協議版本(`tcp``tcp4``tcp6` | tcp |
| sync | 指定多個主機時同步執行 | false |
| timeout | SSH 連線主機的逾時時間 | 30s |
| key | SSH 私鑰內容(如 `~/.ssh/id_rsa` 的原始內容) | |
| key_path | SSH 私鑰路徑 | |
| passphrase | SSH 私鑰密碼 | |
| fingerprint | 主機公鑰的 SHA256 指紋 | |
| use_insecure_cipher | 允許額外(不安全)的加密演算法 | false |
| cipher | 允許的加密演算法,未指定時使用預設值 | |
---
### 🛠️ 指令設定
這些參數用於控制在遠端主機上執行的指令及相關行為。
| 參數 | 說明 | 預設值 |
| --------------- | ----------------------------------------------------- | ------ |
| script | 遠端執行的指令 | |
| script_path | 包含要執行指令的檔案路徑 | |
| envs | 傳遞給 shell 腳本的環境變數 | |
| envs_format | 環境變數傳遞的彈性設定 | |
| allenvs | 傳遞所有帶 `GITHUB_``INPUT_` 前綴的環境變數到腳本 | false |
| command_timeout | SSH 指令執行逾時時間 | 10m |
| debug | 啟用除錯模式 | false |
| request_pty | 向伺服器請求偽終端 | false |
| curl_insecure | 允許 curl 連線無憑證的 SSL 網站 | false |
| version | drone-ssh 執行檔版本,未指定時使用最新版本 | |
---
### 🌐 代理設定
這些參數用於透過代理(跳板機)連線到目標主機。
| 參數 | 說明 | 預設值 |
| ------------------------- | ----------------------------------------- | ------ |
| proxy_host | SSH 代理主機 | |
| proxy_port | SSH 代理埠號 | 22 |
| proxy_username | SSH 代理使用者名稱 | |
| proxy_password | SSH 代理密碼 | |
| proxy_passphrase | SSH 代理私鑰密碼 | |
| proxy_protocol | SSH 代理協議版本(`tcp``tcp4``tcp6` | tcp |
| proxy_timeout | SSH 連線代理主機的逾時時間 | 30s |
| proxy_key | SSH 代理私鑰內容 | |
| proxy_key_path | SSH 代理私鑰路徑 | |
| proxy_fingerprint | 代理主機公鑰的 SHA256 指紋 | |
| proxy_cipher | 代理允許的加密演算法 | |
| proxy_use_insecure_cipher | 代理允許額外(不安全)的加密演算法 | false |
> **注意:** 如需實現已移除的 `script_stop` 功能,請在 shell 腳本最上方加上 `set -e`
---
## ⚡ 快速開始
只需簡單設定,即可在工作流程中執行遠端 SSH 指令:
```yaml
name: remote ssh command
name: Remote SSH Command
on: [push]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
- name: 執行遠端 SSH 指令(密碼認證)
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
username: linuxserver.io
password: ${{ secrets.PASSWORD }}
port: ${{ secrets.PORT }}
script: whoami
```
畫面輸出
**輸出:**
```sh
======CMD======
whoami
======END======
out: ***
linuxserver.io
===============================================
✅ Successfully executed commands to all hosts.
===============================================
```
### 設置 SSH 金鑰
---
請在創建 SSH 金鑰並使用 SSH 金鑰時遵循以下步驟。最佳做法是在本地機器上創建 SSH 金鑰而不是遠端機器上。請使用 Github Secrets 中指定的用戶名登錄。生成 RSA 金鑰:
## 🔑 SSH 金鑰設定與 OpenSSH 相容性
### 生成 RSA 金鑰
### 設定 SSH 金鑰
建議於本地端(非遠端伺服器)產生 SSH 金鑰。請以 GitHub Secrets 指定的使用者名稱登入並產生金鑰對:
#### 產生 RSA 金鑰
```bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
### 生成 ed25519 金鑰
#### 產生 ED25519 金鑰
```bash
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
將新生成的金鑰添加到已授權的金鑰中。詳細了解已授權的金鑰請點擊[此處](https://www.ssh.com/ssh/authorized_keys/).
### 將 RSA 金鑰添加到已授權金鑰中
將新產生的公鑰加入伺服器的 authorized_keys。 [了解更多 authorized_keys](https://www.ssh.com/ssh/authorized_keys/)
```bash
cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
# 加入 RSA 公鑰
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'
```
### 將 ed25519 金鑰添加到已授權金鑰中
複製私鑰內容並貼到 GitHub Secrets。
```bash
cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys'
# macOS
pbcopy < ~/.ssh/id_rsa
# Ubuntu
xclip < ~/.ssh/id_rsa
```
複製私鑰內容,然後將其粘貼到 Github Secrets 中。
> **提示:** 複製內容需包含 `-----BEGIN OPENSSH PRIVATE KEY-----``-----END OPENSSH PRIVATE KEY-----`(含)
### 複製 rsa 私鑰內容
ED25519 同理:
```bash
clip < ~/.ssh/id_rsa
# macOS
pbcopy < ~/.ssh/id_ed25519
# Ubuntu
xclip < ~/.ssh/id_ed25519
```
### 複製 ed25519 私鑰內容
更多資訊:[SSH 免密碼登入](http://www.linuxproblem.org/art_9.html)。
```bash
clip < ~/.ssh/id_ed25519
```
> **注意:** 根據 SSH 版本,可能還需:
>
> - 將公鑰放入 `.ssh/authorized_keys2`
> - 設定 `.ssh` 權限為 700
> - 設定 `.ssh/authorized_keys2` 權限為 640
有關無需密碼登錄 SSH 的詳細信息,請[參見該網站](http://www.linuxproblem.org/art_9.html)。
### OpenSSH 相容性
**來自讀者的注意事項** 根據您的 SSH 版本,您可能還需要進行以下更改:
- 將公鑰放在 `.ssh/authorized_keys2`
- 將 `.ssh` 的權限更改為 700
- 將 `.ssh/authorized_keys2` 的權限更改為 640
### 如果你使用的是 OpenSSH
如果您正在使用 OpenSSH並出現以下錯誤
若出現以下錯誤:
```bash
ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]
```
請確保您所選擇的密鑰演算法得到支援。在 Ubuntu 20.04 或更高版本上,您必須明確允許使用 SSH-RSA 演算法。請在 OpenSSH 守護進程文件中添加以下行(它可以是 `/etc/ssh/sshd_config``/etc/ssh/sshd_config.d/` 中的一個附著文件)
在 Ubuntu 20.04+,你可能需明確允許 `ssh-rsa` 演算法。請於 OpenSSH 設定檔(`/etc/ssh/sshd_config``/etc/ssh/sshd_config.d/` 下的 drop-in 檔案)加入:
```bash
CASignatureAlgorithms +ssh-rsa
```
者,`Ed25519` 密鑰在 OpenSSH 中默認被接受。如果需要,您可以使用它來替代 RSA。
直接使用預設支援的 ED25519 金鑰:
```bash
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
### Example
---
#### 使用密碼執行遠端 SSH 命令
## 🛠️ 用法場景與進階範例
本節涵蓋常見與進階用法,包括多主機、代理、環境變數傳遞等。
### 使用密碼認證
```yaml
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@v1.2.1
- name: 執行遠端 SSH 指令(密碼認證)
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -171,11 +250,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
script: whoami
```
#### 使用私鑰
### 使用私鑰認證
```yaml
- name: executing remote ssh commands using ssh key
uses: appleboy/ssh-action@v1.2.1
- name: 執行遠端 SSH 指令(私鑰認證)
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -184,11 +263,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
script: whoami
```
#### 多個命
### 多條指
```yaml
- name: multiple command
uses: appleboy/ssh-action@v1.2.1
- name: 多條指令
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -201,11 +280,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
![result](./images/output-result.png)
#### Commands from a file
### 從檔案執行指令
```yaml
- name: file commands
uses: appleboy/ssh-action@v1.2.1
- name: 檔案指令
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -214,11 +293,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
script_path: scripts/script.sh
```
####主機
### 多主機
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: 多主機
uses: appleboy/ssh-action@v1
with:
- host: "foo.com"
+ host: "foo.com,bar.com"
@ -230,11 +309,13 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
ls -al
```
#### 多個不同端口的主機
預設 `port``22`
### 多主機不同埠號
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: 多主機
uses: appleboy/ssh-action@v1
with:
- host: "foo.com"
+ host: "foo.com:1234,bar.com:5678"
@ -245,11 +326,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
ls -al
```
#### 主機同步執行
### 多主機同步執行
```diff
- name: multiple host
uses: appleboy/ssh-action@v1.2.1
- name: 多主機
uses: appleboy/ssh-action@v1
with:
host: "foo.com,bar.com"
+ sync: true
@ -261,11 +342,11 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
ls -al
```
#### 將環境變量傳遞到 Shell 腳本
### 傳遞環境變數到 shell 腳本
```diff
- name: pass environment
uses: appleboy/ssh-action@v1.2.1
- name: 傳遞環境變數
uses: appleboy/ssh-action@v1
+ env:
+ FOO: "BAR"
+ BAR: "FOO"
@ -282,9 +363,13 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
echo "sha: $SHA"
```
_在 `env` 對象中,您需要將每個環境變量作為字符串傳遞,傳遞 `Integer` 數據類型或任何其他類型可能會產生意外結果。_
> _`env` 物件中的所有環境變數必須為字串。傳遞整數或其他型別可能導致非預期結果。_
#### 如何使用 `ProxyCommand` 連接遠程服務器?
---
## 🌐 代理與跳板機用法
你可以透過代理(跳板機)連線到遠端主機,適用於進階網路拓撲。
```bash
+--------+ +----------+ +-----------+
@ -292,7 +377,7 @@ _在 `env` 對象中,您需要將每個環境變量作為字符串傳遞,傳
+--------+ +----------+ +-----------+
```
在您的 `~/.ssh/config` 文件中,您會看到以下內容。
範例 `~/.ssh/config`
```bash
Host Jumphost
@ -308,11 +393,11 @@ Host FooServer
ProxyCommand ssh -q -W %h:%p Jumphost
```
#### 如何將其轉換為 GitHubActions 的 YAML 格式?
**GitHub Actions YAML:**
```diff
- name: ssh proxy command
uses: appleboy/ssh-action@v1.2.1
- name: SSH 代理指令
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -327,13 +412,17 @@ Host FooServer
ls -al
```
#### 如何保護私鑰?
---
密碼短語通常用於加密私鑰。這使得攻擊者無法單獨使用密鑰文件。文件泄露可能來自備份或停用的硬件,黑客通常可以從受攻擊系統中洩露文件。因此,保護私鑰非常重要。
## 🛡️ 安全最佳實踐
### 保護你的私鑰
密碼短語會加密你的私鑰,即使外洩也無法被攻擊者直接利用。請務必妥善保管私鑰。
```diff
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
- name: SSH 私鑰密碼
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -345,21 +434,19 @@ Host FooServer
ls -al
```
#### 使用主機指紋驗證
### 主機指紋驗證
設置 SSH 主機指紋驗證可以幫助防止中間人攻擊。在設置之前,運行以下命令以獲取 SSH 主機指紋。請記得將 `ed25519` 替換為您的適當金鑰類型(`rsa``dsa`等),而 `example.com` 則替換為您的主機。
現代 OpenSSH 版本中,需要提取的**默認金鑰**類型是 `rsa`(從版本 5.1 開始)、`ecdsa`(從版本 6.0 開始)和 `ed25519`(從版本 6.7 開始)。
驗證 SSH 主機指紋有助於防止中間人攻擊。取得主機指紋(將 `ed25519` 換成你的金鑰型別,`example.com` 換成你的主機):
```sh
ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2
```
現在您可以調整您的配置
更新設定
```diff
- name: ssh key passphrase
uses: appleboy/ssh-action@v1.2.1
- name: SSH 私鑰密碼
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
@ -371,10 +458,33 @@ ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' '
ls -al
```
## 貢獻
---
我們非常希望您為 `appleboy/ssh-action` 做出貢獻,歡迎提交請求!
## 🚨 錯誤處理與疑難排解
## 授權方式
### 常見問題
本項目中的腳本和文檔采用 [MIT](LICENSE) 許可證 發布。
#### 指令找不到npm 或其他指令)
若遇到 "command not found" 錯誤,請參考 [此討論](https://github.com/appleboy/ssh-action/issues/31#issuecomment-1006565847) 了解互動式與非互動式 shell 差異。
許多 Linux 發行版的 `/etc/bash.bashrc` 包含如下內容:
```sh
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
```
請將該行註解掉或使用指令的絕對路徑。
---
## 🤝 貢獻
歡迎貢獻!請提交 Pull Request 改善 `appleboy/ssh-action`
---
## 📝 授權
本專案採用 [MIT License](LICENSE) 授權。

View File

@ -3,85 +3,91 @@ description: "Executing remote ssh commands"
author: "Bo-Yi Wu"
inputs:
host:
description: "SSH host address."
description: "SSH host address or IP to connect to."
port:
description: "SSH port number."
description: "SSH port number for the connection."
default: "22"
passphrase:
description: "Passphrase for the SSH key."
description: "Passphrase to decrypt the SSH private key if protected."
username:
description: "SSH username."
description: "SSH username for authentication on the remote server."
password:
description: "SSH password."
description: "SSH password for authentication (use secrets for sensitive data)."
protocol:
description: 'The IP protocol to use. Valid values are "tcp". "tcp4" or "tcp6". Default to tcp.'
description: 'IP protocol version to use. Options: "tcp" (default), "tcp4" (IPv4 only), or "tcp6" (IPv6 only).'
default: "tcp"
sync:
description: "Enable synchronous execution if multiple hosts are involved."
description: "When true, executes commands synchronously across multiple hosts (one after another)."
use_insecure_cipher:
description: "Include more ciphers by using insecure ciphers."
description: "Enable additional legacy ciphers that might be less secure but more compatible with older systems."
cipher:
description: "Allowed cipher algorithms. If unspecified, a sensible default is used."
description: "Specify custom cipher algorithms for encryption. Leave empty to use secure defaults."
timeout:
description: "Timeout duration for establishing SSH connection to the host."
description: "Maximum time to wait when establishing the SSH connection, e.g., '30s', '1m'."
default: "30s"
command_timeout:
description: "Timeout duration for SSH commands execution."
description: "Maximum execution time for the remote commands before terminating, e.g., '10m', '1h'."
default: "10m"
key:
description: "Content of the SSH private key. For example, the raw content of ~/.ssh/id_rsa."
description: "Raw content of the SSH private key for authentication (use secrets for sensitive data)."
key_path:
description: "Path to the SSH private key file."
description: "Path to the SSH private key file on the runner."
fingerprint:
description: "SHA256 fingerprint of the host public key."
description: "SHA256 fingerprint of the host public key for verification to prevent MITM attacks."
proxy_host:
description: "SSH proxy host address."
description: "Proxy server hostname or IP if connecting through an SSH jump host."
proxy_port:
description: "SSH proxy port number."
description: "SSH port number for the proxy connection."
default: "22"
proxy_username:
description: "SSH proxy username."
description: "Username for authentication on the proxy server."
proxy_password:
description: "SSH proxy password."
description: "Password for authentication on the proxy server (use secrets for sensitive data)."
proxy_protocol:
description: 'The IP protocol to use. Valid values are "tcp". "tcp4" or "tcp6". Default to tcp.'
description: 'IP protocol version for proxy. Options: "tcp" (default), "tcp4" (IPv4 only), or "tcp6" (IPv6 only).'
default: "tcp"
proxy_passphrase:
description: "SSH proxy key passphrase."
description: "Passphrase to decrypt the proxy SSH private key if protected."
proxy_timeout:
description: "Timeout duration for establishing SSH connection to the proxy host."
description: "Maximum time to wait when establishing the proxy SSH connection, e.g., '30s', '1m'."
default: "30s"
proxy_key:
description: "Content of the SSH proxy private key. For example, the raw content of ~/.ssh/id_rsa."
description: "Raw content of the SSH proxy private key for authentication (use secrets for sensitive data)."
proxy_key_path:
description: "Path to the SSH proxy private key file."
description: "Path to the SSH proxy private key file on the runner."
proxy_fingerprint:
description: "SHA256 fingerprint of the proxy host public key."
description: "SHA256 fingerprint of the proxy host public key for verification."
proxy_cipher:
description: "Allowed cipher algorithms for the proxy. If unspecified, a sensible default is used."
description: "Specify custom cipher algorithms for proxy connection encryption."
proxy_use_insecure_cipher:
description: "Include more ciphers for the proxy by using insecure ciphers."
description: "Enable additional legacy ciphers for proxy connections (less secure but more compatible)."
script:
description: "Commands to be executed."
description: "Commands to execute on the remote server (inline script string)."
script_path:
description: "Path to the file containing commands to be executed."
description: "Path to a local file containing commands to execute on the remote server."
envs:
description: "Environment variables to be passed to the shell script."
description: "Environment variables to expose to the remote script, format: key=value,key2=value2."
envs_format:
description: "Flexible configuration for environment value transfer."
description: "Format specification for environment variable transfer (for advanced usage)."
debug:
description: "Enable debug mode."
description: "Set to true to enable verbose logging for troubleshooting connection issues."
allenvs:
description: "pass all environment variable to shell script."
description: "When true, passes all GitHub Actions environment variables to the remote script."
request_pty:
description: "Request a pseudo-terminal from the server."
capture_stdout:
description: "Capture the stdout of the commands."
description: "Request a pseudo-terminal from the server (required for interactive commands or sudo)."
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-ssh to use.
outputs:
stdout:
description: 'Standard output of the executed commands.'
description: "Standard output of the executed commands when capture_stdout is enabled."
value: ${{ steps.entrypoint.outputs.stdout }}
runs:
@ -131,6 +137,8 @@ runs:
INPUT_PROXY_CIPHER: ${{ inputs.proxy_cipher }}
INPUT_SYNC: ${{ inputs.sync }}
INPUT_CAPTURE_STDOUT: ${{ inputs.capture_stdout }}
INPUT_CURL_INSECURE: ${{ inputs.curl_insecure }}
DRONE_SSH_VERSION: ${{ inputs.version }}
branding:
icon: "terminal"

View File

@ -1,77 +1,56 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
set -euo pipefail
export GITHUB="true"
GITHUB_ACTION_PATH="${GITHUB_ACTION_PATH%/}"
DRONE_SSH_RELEASE_URL="${DRONE_SSH_RELEASE_URL:-https://github.com/appleboy/drone-ssh/releases/download}"
DRONE_SSH_VERSION="${DRONE_SSH_VERSION:-1.8.0}"
DRONE_SSH_VERSION="${DRONE_SSH_VERSION:-1.8.1}"
function log_error() {
echo "$1" >&2
exit "$2"
}
function detect_client_info() {
if [ -n "${SSH_CLIENT_OS-}" ]; then
CLIENT_PLATFORM="${SSH_CLIENT_OS}"
else
local kernel
kernel="$(uname -s)"
case "${kernel}" in
Darwin)
CLIENT_PLATFORM="darwin"
;;
Linux)
CLIENT_PLATFORM="linux"
;;
Windows)
CLIENT_PLATFORM="windows"
;;
*)
echo "Unknown, unsupported platform: ${kernel}." >&2
echo "Supported platforms: Linux, Darwin and Windows." >&2
echo "Bailing out." >&2
exit 2
;;
esac
fi
CLIENT_PLATFORM="${SSH_CLIENT_OS:-$(uname -s | tr '[:upper:]' '[:lower:]')}"
CLIENT_ARCH="${SSH_CLIENT_ARCH:-$(uname -m)}"
if [ -n "${SSH_CLIENT_ARCH-}" ]; then
CLIENT_ARCH="${SSH_CLIENT_ARCH}"
else
local machine
machine="$(uname -m)"
case "${machine}" in
x86_64* | i?86_64* | amd64*)
CLIENT_ARCH="amd64"
;;
aarch64* | arm64*)
CLIENT_ARCH="arm64"
;;
*)
echo "Unknown, unsupported architecture (${machine})." >&2
echo "Supported architectures x86_64, i686, arm64." >&2
echo "Bailing out." >&2
exit 3
;;
esac
fi
case "${CLIENT_PLATFORM}" in
darwin | linux | windows) ;;
*) log_error "Unknown or unsupported platform: ${CLIENT_PLATFORM}. Supported platforms are Linux, Darwin, and Windows." 2 ;;
esac
case "${CLIENT_ARCH}" in
x86_64* | i?86_64* | amd64*) CLIENT_ARCH="amd64" ;;
aarch64* | arm64*) CLIENT_ARCH="arm64" ;;
*) log_error "Unknown or unsupported architecture: ${CLIENT_ARCH}. Supported architectures are x86_64, i686, and arm64." 3 ;;
esac
}
detect_client_info
DOWNLOAD_URL_PREFIX="${DRONE_SSH_RELEASE_URL}/v${DRONE_SSH_VERSION}"
CLIENT_BINARY="drone-ssh-${DRONE_SSH_VERSION}-${CLIENT_PLATFORM}-${CLIENT_ARCH}"
TARGET="${GITHUB_ACTION_PATH}/${CLIENT_BINARY}"
echo "Will download ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}"
curl -fsSL --retry 5 --keepalive-time 2 "${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o ${TARGET}
chmod +x ${TARGET}
echo "======= CLI Version ======="
sh -c "${TARGET} --version" # print version
echo "==========================="
if [[ "$INPUT_CAPTURE_STDOUT" == 'true' ]]; then
echo 'stdout<<EOF' >> $GITHUB_OUTPUT # use heredoc for multiline output
sh -c "${TARGET} $*" | tee -a $GITHUB_OUTPUT # run the command
echo 'EOF' >> $GITHUB_OUTPUT
else
sh -c "${TARGET} $*" # run the command
echo "Downloading ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}"
INSECURE_OPTION=""
if [[ "${INPUT_CURL_INSECURE}" == 'true' ]]; then
INSECURE_OPTION="--insecure"
fi
curl -fsSL --retry 5 --keepalive-time 2 ${INSECURE_OPTION} "${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o "${TARGET}"
chmod +x "${TARGET}"
echo "======= CLI Version Information ======="
"${TARGET}" --version
echo "======================================="
if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then
{
echo 'stdout<<EOF'
"${TARGET}" "$@" | tee -a "${GITHUB_OUTPUT}"
echo 'EOF'
} >>"${GITHUB_OUTPUT}"
else
"${TARGET}" "$@"
fi