2019-05-15 06:32:43 +08:00
# 🚀 SSH for GitHub Actions
2019-05-15 00:31:53 +08:00
2019-09-30 11:35:28 +08:00
[GitHub Action ](https://github.com/features/actions ) for executing remote ssh commands.
2019-05-15 06:32:43 +08:00
2019-09-29 11:09:26 +08:00

[](https://github.com/appleboy/ssh-action/actions)
2019-05-15 06:36:27 +08:00
2020-06-05 09:05:02 +08:00
**Important** : Only support **Linux** [docker ](https://www.docker.com/ ) container.
2020-05-08 19:05:47 +08:00
2021-04-03 23:59:44 +02:00
## Input variables
See [action.yml ](./action.yml ) for more detailed information.
* `host` - ssh host
* `port` - ssh port, default is `22`
* `username` - ssh username
* `password` - ssh password
* `passphrase` - the passphrase is usually to encrypt the private key
* `sync` - synchronous execution if multiple hosts, default is false
* `timeout` - timeout for ssh to remote host, default is `30s`
* `command_timeout` - timeout for ssh command, default is `10m`
2023-03-03 10:22:51 +08:00
* `key` - content of ssh private key. ex raw content of ~/.ssh/id_rsa, remember include the BEGIN and END lines
2021-04-03 23:59:44 +02:00
* `key_path` - path of ssh private key
* `fingerprint` - fingerprint SHA256 of the host public key, default is to skip verification
* `script` - execute commands
* `script_stop` - stop script after first failure
* `envs` - pass environment variable to shell script
* `debug` - enable debug mode
* `use_insecure_cipher` - include more ciphers with use_insecure_cipher (see [#56 ](https://github.com/appleboy/ssh-action/issues/56 ))
* `cipher` - the allowed cipher algorithms. If unspecified then a sensible
SSH Proxy Setting:
* `proxy_host` - proxy host
* `proxy_port` - proxy port, default is `22`
* `proxy_username` - proxy username
* `proxy_password` - proxy password
* `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 proxy host public key, default is to skip verification
* `proxy_use_insecure_cipher` - include more ciphers with use_insecure_cipher (see [#56 ](https://github.com/appleboy/ssh-action/issues/56 ))
* `proxy_cipher` - the allowed cipher algorithms. If unspecified then a sensible
2019-05-15 06:32:43 +08:00
## Usage
2019-05-15 06:36:27 +08:00
Executing remote ssh commands.
2019-05-15 06:32:43 +08:00
2019-09-29 11:09:26 +08:00
```yaml
2019-09-29 14:16:47 +08:00
name : remote ssh command
on : [ push]
jobs :
build :
name : Build
runs-on : ubuntu-latest
steps :
- name : executing remote ssh commands using password
2023-02-28 17:18:27 +08:00
uses : appleboy/ssh-action@v0.1.8
2019-09-29 14:16:47 +08:00
with :
host : ${{ secrets.HOST }}
username : ${{ secrets.USERNAME }}
password : ${{ secrets.PASSWORD }}
port : ${{ secrets.PORT }}
script : whoami
2019-05-15 06:32:43 +08:00
```
2019-09-29 11:09:26 +08:00
output:
2019-05-15 06:32:43 +08:00
2019-09-29 11:09:26 +08:00
```sh
====== CMD ======
whoami
====== END ======
out: ***
2019-11-20 23:49:31 +08:00
==============================================
✅ Successfully executed commands to all host.
==============================================
2019-09-29 11:09:26 +08:00
```
2021-04-03 23:59:44 +02:00
### Setting up a SSH Key
2020-08-13 01:06:27 +08:00
Make sure to follow the below steps while creating SSH Keys and using them.
2020-10-31 07:03:29 +08:00
The best practice is create the SSH Keys on local machine not remote machine.
2020-08-13 01:06:27 +08:00
Login with username specified in Github Secrets. Generate a RSA Key-Pair:
2023-03-03 10:26:23 +08:00
### Generate rsa key
2021-04-03 23:59:44 +02:00
```bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
2023-03-03 10:26:23 +08:00
### Generate ed25519 key
2021-04-03 23:59:44 +02:00
```bash
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
2020-08-13 01:06:27 +08:00
Add newly generated key into Authorized keys. Read more about authorized keys [here ](https://www.ssh.com/ssh/authorized_keys/ ).
2023-03-03 10:26:23 +08:00
### Add rsa key into Authorized keys
2021-04-03 23:59:44 +02:00
2020-08-13 01:06:27 +08:00
```bash
2020-10-31 07:03:29 +08:00
cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
2020-08-13 01:06:27 +08:00
```
2023-03-03 10:26:23 +08:00
### Add ed25519 key into Authorized keys
2021-04-03 23:59:44 +02:00
```bash
cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys'
```
2020-08-13 01:06:27 +08:00
Copy Private Key content and paste in Github Secrets.
2023-03-03 10:26:23 +08:00
### Copy rsa Private key
2021-04-03 23:59:44 +02:00
2020-08-13 01:06:27 +08:00
```bash
clip < ~/.ssh/id_rsa
```
2023-03-03 10:26:23 +08:00
### Copy ed25519 Private key
2021-04-03 23:59:44 +02:00
```bash
clip < ~/.ssh/id_ed25519
```
2021-05-09 21:11:10 +08:00
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:
* Put the public key in `.ssh/authorized_keys2`
* Change the permissions of `.ssh` to 700
* Change the permissions of `.ssh/authorized_keys2` to 640
2020-08-13 01:06:27 +08:00
2022-07-29 08:58:30 -04:00
### If you are using OpenSSH
2022-07-29 21:24:53 +08:00
2022-07-29 08:58:30 -04:00
If you are currently using OpenSSH and are getting the following error:
```bash
ssh: handshake failed: ssh: unable to authenticate, attempted methods [ none publickey]
```
2023-03-03 10:22:51 +08:00
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/` ):
2022-07-29 08:58:30 -04:00
2022-07-29 21:24:53 +08:00
```bash
2022-07-29 08:58:30 -04:00
CASignatureAlgorithms +ssh-rsa
```
Alternatively, `ed25519` keys are accepted by default in OpenSSH. You could use this instead of rsa if needed:
2022-07-29 21:24:53 +08:00
2022-07-29 08:58:30 -04:00
```bash
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
```
2019-05-15 06:47:53 +08:00
### Example
2021-04-03 23:59:44 +02:00
#### Executing remote ssh commands using password
2019-05-15 06:47:53 +08:00
2019-09-29 11:09:26 +08:00
```yaml
- name : executing remote ssh commands using password
2023-02-28 17:18:27 +08:00
uses : appleboy/ssh-action@v0.1.8
2019-09-29 11:09:26 +08:00
with :
host : ${{ secrets.HOST }}
username : ${{ secrets.USERNAME }}
password : ${{ secrets.PASSWORD }}
port : ${{ secrets.PORT }}
2019-09-29 11:45:42 +08:00
script : whoami
2019-05-15 06:47:53 +08:00
```
2021-04-03 23:59:44 +02:00
#### Using private key
2019-05-15 06:47:53 +08:00
2019-09-29 11:09:26 +08:00
```yaml
- name : executing remote ssh commands using ssh key
2023-02-28 17:18:27 +08:00
uses : appleboy/ssh-action@v0.1.8
2019-09-29 11:09:26 +08:00
with :
host : ${{ secrets.HOST }}
username : ${{ secrets.USERNAME }}
key : ${{ secrets.KEY }}
port : ${{ secrets.PORT }}
script : whoami
2019-05-15 06:47:53 +08:00
```
2021-04-03 23:59:44 +02:00
#### Multiple Commands
2019-05-15 06:52:59 +08:00
2019-09-29 11:09:26 +08:00
```yaml
- name : multiple command
2023-02-28 17:18:27 +08:00
uses : appleboy/ssh-action@v0.1.8
2019-09-29 11:09:26 +08:00
with :
host : ${{ secrets.HOST }}
username : ${{ secrets.USERNAME }}
key : ${{ secrets.KEY }}
port : ${{ secrets.PORT }}
script : |
whoami
ls -al
2019-05-15 06:52:59 +08:00
```
2019-09-29 11:09:26 +08:00

2019-05-15 06:59:18 +08:00
2021-04-03 23:59:44 +02:00
#### Multiple Hosts
2019-05-15 07:13:49 +08:00
2019-09-29 11:09:26 +08:00
```diff
2019-11-20 23:49:31 +08:00
- name: multiple host
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2019-11-20 23:49:31 +08:00
with:
- host: "foo.com"
+ host: "foo.com,bar.com"
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
whoami
ls -al
2019-05-15 07:13:49 +08:00
```
2019-09-29 11:23:40 +08:00
2021-04-03 23:59:44 +02:00
#### Multiple hosts with different port
2020-11-17 10:51:06 +08:00
```diff
- name: multiple host
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2020-11-17 10:51:06 +08:00
with:
- host: "foo.com"
+ host: "foo.com:1234,bar.com:5678"
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
whoami
ls -al
```
2021-04-03 23:59:44 +02:00
#### Synchronous execution on multiple hosts
2020-01-30 17:40:33 +03:00
```diff
- name: multiple host
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2020-01-30 17:40:33 +03:00
with:
host: "foo.com,bar.com"
+ sync: true
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
whoami
ls -al
```
2021-04-03 23:59:44 +02:00
#### Pass environment variable to shell script
2019-09-29 11:23:40 +08:00
```diff
2019-11-20 23:49:31 +08:00
- name: pass environment
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2019-11-20 23:49:31 +08:00
+ env:
+ FOO: "BAR"
2019-12-08 07:16:30 +08:00
+ BAR: "FOO"
2020-02-09 11:37:56 +08:00
+ SHA: ${{ github.sha }}
2019-11-20 23:49:31 +08:00
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
2022-07-29 14:19:55 +01:00
+ envs: FOO,BAR,SHA
2019-11-20 23:49:31 +08:00
script: |
echo "I am $FOO"
echo "I am $BAR"
2020-02-09 11:37:56 +08:00
echo "sha: $SHA"
2019-09-29 11:23:40 +08:00
```
2019-09-29 12:02:21 +08:00
2020-07-08 14:16:24 +05:30
_Inside `env` object, you need to pass every environment variable as a string, passing `Integer` data type or any other may output unexpected results._
2021-04-03 23:59:44 +02:00
#### Stop script after first failure
> ex: missing `abc` folder
2019-09-29 12:02:21 +08:00
2019-11-20 23:49:31 +08:00
```diff
- name: stop script if command error
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2019-11-20 23:49:31 +08:00
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
+ script_stop: true
script: |
mkdir abc/def
ls -al
```
output:
```sh
====== CMD ======
mkdir abc/def
ls -al
====== END ======
2019/11/21 01:16:21 Process exited with status 1
err: mkdir: cannot create directory ‘abc/def’: No such file or directory
##[error]Docker run failed with exit code 1
2019-09-29 12:02:21 +08:00
```
2019-12-07 20:05:02 +08:00
2021-04-03 23:59:44 +02:00
#### How to connect remote server using `ProxyCommand`?
2019-12-07 20:05:02 +08:00
```bash
+--------+ +----------+ +-----------+
| Laptop | <--> | Jumphost | <--> | FooServer |
+--------+ +----------+ +-----------+
```
in your `~/.ssh/config` , you will see the following.
```bash
Host Jumphost
HostName Jumphost
User ubuntu
Port 22
IdentityFile ~/.ssh/keys/jump_host.pem
Host FooServer
HostName FooServer
User ubuntu
Port 22
ProxyCommand ssh -q -W %h:%p Jumphost
```
2021-04-03 23:59:44 +02:00
#### How to convert to YAML format of GitHubActions
2019-12-07 20:05:02 +08:00
```diff
- name: ssh proxy command
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2019-12-07 20:05:02 +08:00
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
+ proxy_host: ${{ secrets.PROXY_HOST }}
+ proxy_username: ${{ secrets.PROXY_USERNAME }}
+ proxy_key: ${{ secrets.PROXY_KEY }}
+ proxy_port: ${{ secrets.PROXY_PORT }}
script: |
mkdir abc/def
ls -al
```
2019-12-30 19:54:28 +08:00
2021-04-03 23:59:44 +02:00
#### Protecting a Private Key
The purpose of the passphrase is usually to encrypt the private key.
2022-07-29 21:24:53 +08:00
This makes the key file by itself useless to an attacker.
2021-04-03 23:59:44 +02:00
It is not uncommon for files to leak from backups or decommissioned hardware, and hackers commonly exfiltrate files from compromised systems.
2019-12-30 19:54:28 +08:00
```diff
- name: ssh key passphrase
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2019-12-30 19:54:28 +08:00
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
+ passphrase: ${{ secrets.PASSPHRASE }}
script: |
whoami
ls -al
```
2021-04-03 23:59:44 +02:00
2021-05-15 17:05:07 +02:00
#### Using 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).
2022-02-06 15:15:00 +08:00
```sh
2021-05-15 17:05:07 +02:00
ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2
```
Now you can adjust you config:
```diff
- name: ssh key passphrase
2023-02-28 17:18:27 +08:00
uses: appleboy/ssh-action@v0.1.8
2021-05-15 17:05:07 +02:00
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
+ fingerprint: ${{ secrets.FINGERPRINT }}
script: |
whoami
ls -al
```
2021-04-03 23:59:44 +02:00
## Contributing
2022-02-06 15:15:00 +08:00
2021-04-03 23:59:44 +02:00
We would love for you to contribute to `appleboy/ssh-action` , pull requests are welcome!
## License
2022-02-06 15:15:00 +08:00
2021-04-03 23:59:44 +02:00
The scripts and documentation in this project are released under the [MIT License ](LICENSE )