Skip to content

Commit

Permalink
Merge pull request #1 from rainstormy/spdiswal/define-action-steps
Browse files Browse the repository at this point in the history
  • Loading branch information
spdiswal authored Apr 10, 2023
2 parents e30e351 + 6272b44 commit 9e89542
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 4 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Validate

on:
pull_request:
branches: [ main ]

jobs:
validate-commit-messages:
name: Validate commit messages
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Run the validation
uses: rainstormy/github-action-validate-commit-messages@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
rules: 'acknowledged-author-email-addresses, acknowledged-author-names, acknowledged-committer-email-addresses, acknowledged-committer-names, capitalised-subject-lines, empty-line-after-subject-lines, imperative-subject-lines, limit-length-of-body-lines, limit-length-of-subject-lines, multi-word-subject-lines, no-co-authors, no-merge-commits, no-revert-revert-commits, no-squash-commits, no-trailing-punctuation-in-subject-lines, no-unexpected-whitespace'
acknowledged-author-email-addresses--patterns: '\d+\+.+@users\.noreply\.github\.com'
acknowledged-author-names--patterns: '\p{Lu}.*\s.+'
acknowledged-committer-email-addresses--patterns: '\d+\+.+@users\.noreply\.github\.com'
acknowledged-committer-names--patterns: '\p{Lu}.*\s.+'
5 changes: 4 additions & 1 deletion .idea/github-action-deploy-with-rsync-over-ssh.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion CONTRIBUTING.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ $ ssh-add ~/.ssh/<my-ssh-key>
$ git config --global core.sshCommand "C:/Windows/System32/OpenSSH/ssh.exe"
----

. Grab the **_public_** key.
. Grab the *_public_* key.
It appears like `ssh-ed25519 AAAAC3(...)`.
+
[source,shell,subs="+quotes,+replacements"]
Expand Down
82 changes: 80 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,84 @@
= Deploy with Rsync over SSH
:experimental:
:source-highlighter: highlight.js
:toc: preamble

This repository implements an Ubuntu-based composite GitHub Action that copies files from the GitHub Actions runner to a remote host using the https://manpages.ubuntu.com/manpages/bionic/man1/rsync.1.html[Rsync] tool over SSH.
This repository implements an Ubuntu-based https://docs.github.com/en/actions/creating-actions/about-custom-actions#composite-actions[composite GitHub Action] that copies files from the GitHub Actions runner to a remote host using the https://manpages.ubuntu.com/manpages/jammy/en/man1/rsync.1.html[Rsync] tool over an SSH connection.
This provides a way to deploy static files to a web server.

Please read the `action.yml` file to review the specific steps performed by this action:
In broad terms, it saves the private SSH key and the list of known hosts on the GitHub Actions runner for the duration of the action and executes the `rsync` command with the given input parameters.

== Usage
. Define a GitHub Actions workflow.
For example:
+
[source,yaml]
----
# .github/workflows/deploy.yml
name: Deploy
on: [ workflow_dispatch ]
jobs:
copy-static-files-to-web-server:
name: Copy static files to the web server
runs-on: ubuntu-latest
steps:
- name: Check out the repository
uses: actions/checkout@v3
- name: Copy the files with Rsync over SSH
uses: rainstormy/github-action-deploy-with-rsync-over-ssh@v1
with:
rsync-options: --archive --compress --verbose --rsh="ssh -l ${{ secrets.SSH_USERNAME }}"
rsync-host: ${{ secrets.RSYNC_HOST }}
rsync-source-path: www/
rsync-destination-path: ${{ secrets.RSYNC_DESTINATION_PATH }}
ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }}
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh-private-key-filename: ${{ secrets.SSH_PRIVATE_KEY_FILENAME }}
----
+
Here is another example that uses https://manpages.ubuntu.com/manpages/jammy/en/man1/sshpass.1.html[sshpass] to perform password-based authentication in addition to key-based authentication:
+
[source,yaml]
----
with:
rsync-options: --archive --compress --verbose --rsh="sshpass -e ssh -l ${{ secrets.SSH_USERNAME }}"
rsync-host: ${{ secrets.RSYNC_HOST }}
rsync-source-path: www/
rsync-destination-path: ${{ secrets.RSYNC_DESTINATION_PATH }}
ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }}
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
ssh-private-key-filename: ${{ secrets.SSH_PRIVATE_KEY_FILENAME }}
env:
SSHPASS: ${{ secrets.SSH_PASSWORD }}
----

. Create https://docs.github.com/en/actions/security-guides/encrypted-secrets[GitHub Actions secrets] for the SSH username, the remote host (e.g. `server123.company.com`), and the destination pathname on the remote (e.g. `~/www`).
They are to be accessed through input parameters `rsync-options` (in the `--rsh` option), `rsync-host`, and `rsync-destination-path`, respectively.

. Optionally, for password-based authentication, create a GitHub Actions secret for the SSH password to be accessed through the `SSHPASS` environment variable.

. From your own computer, gather the remote host keys and verify that they are authentic to establish a https://developer.mozilla.org/en-US/docs/Glossary/TOFU[trust-on-first-use] relationship:
+
[source,shell,subs="+quotes,+replacements"]
----
$ ssh-keyscan -H *_<remote-host>_* > "$HOME/.ssh/known_hosts"
----

. Save the remote host keys in a GitHub Actions secret to be accessed through the `ssh-known-hosts` input parameter.

. From your own computer, generate an SSH key with the *Ed25519* algorithm, for example using https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent[ssh-keygen] or https://developer.1password.com/docs/ssh/manage-keys[1Password], and optionally choose a name for the key or use the default name of `id_ed25519` as `*_<my-ssh-key>_*`:
+
[source,shell,subs="+quotes,+replacements"]
----
$ ssh-keygen -t ed25519 -f "$HOME/.ssh/**_<my-ssh-key>_**"
----

. Grab the *_public_* key and add it to the list of authorised SSH keys on the remote host.
It appears like `ssh-ed25519 AAAAC3(...)`.

. Save the private key in a GitHub Actions secret to be accessed through the `ssh-private-key` input parameter.
It appears like `-----BEGIN OPENSSH PRIVATE KEY-----(...)-----END OPENSSH PRIVATE KEY-----`.

. Save the name that you have chosen as `*_<my-ssh-key>_*` in a GitHub Actions secret to be accessed through the `ssh-private-key-filename` input parameter.
It defines the name of the file in which the private key is stored on the GitHub Actions runner for the duration of the action.
You may skip this step if you have chosen the default name of `id_ed25519`.
48 changes: 48 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Deploy with Rsync over SSH
description: Copies files from the GitHub Actions runner to a remote host using the Rsync tool over an SSH connection.
author: Steffen Diswal
inputs:
rsync-destination-path:
description: The pathname on the remote host to which the files are to be copied.
required: true
rsync-host:
description: The hostname of the remote server onto which the files are to be copied.
required: true
rsync-options:
description: The options to pass to the Rsync tool. Include the `--rsh` option to set the SSH credentials for Rsync.
required: true
rsync-source-path:
description: The pathname on the GitHub Actions runner from which the files are to be copied.
required: true
ssh-known-hosts:
description: A list of trusted remote host keys gathered by the ssh-keyscan utility to be stored temporarily on the GitHub Actions runner.
required: true
ssh-private-key:
description: The private SSH key to be stored temporarily on the GitHub Actions runner in the file designated by the `ssh-private-key-filename` input parameter. It is used by the Rsync tool to establish an SSH connection to the remote host which should know the public SSH key in advance.
required: true
ssh-private-key-filename:
description: The name of the file in the `.ssh` directory on the GitHub Actions runner in which the value of the `ssh-private-key` input parameter is temporarily stored.
required: false
default: 'id_ed25519'
runs:
using: composite
steps:
- name: Prepare the SSH configuration
run: |
mkdir ~/.ssh
echo "${{ inputs.ssh-known-hosts }}" > ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
echo "${{ inputs.ssh-private-key }}" > ~/.ssh/${{ inputs.ssh-private-key-filename }}
chmod 600 ~/.ssh/${{ inputs.ssh-private-key-filename }}
shell: bash

- name: Deploy with Rsync
run: |
rsync ${{ inputs.rsync-options }} ${{ inputs.rsync-source-path }} ${{ inputs.rsync-host }}:${{ inputs.rsync-destination-path }}
shell: bash

- if: always()
name: Erase the SSH configuration
run: |
rm --recursive --force ~/.ssh
shell: bash

0 comments on commit 9e89542

Please sign in to comment.