Compare commits

..

101 Commits

Author SHA1 Message Date
Steven 0c902521b8 Release/8.0.2 (#93)
* fix: only attempt to create dir if not yet exists

On self-hosted runners it can happen that an action (docker container) is cached. This leads to the script trying to create the .ssh dir despite it already existing. The action then fails.

* fix: only attempt to create file if it doesn't exist yet

On self-hosted runners it can happen that an action (docker container) is cached, resulting in aborting this script because the know_hosts file already exists. 
This if clause fixes it.
Setting permissions is intentionally outside the if clause because in all cases we want to reset perms.

* fix: reverting printf in favor of echo

Like in commit 2c22263 we are using echo again instead of printf because some runners can't function properly with it.

* chore: 8.0.2

* chore: readme changes
2025-12-07 12:59:02 +01:00
Steven 68d1fd5150 chore: 8.0.1 2025-12-06 21:44:40 +00:00
Steven 2c22263f9c fix: regression - using echo instead of printf again #90
It was found via #90 and #89 that using printf causes problems.
In the previous version 7.1.0 we used echo instead of printf - hence we are bringing this back for version 8.0.x
2025-12-06 22:33:01 +01:00
Steven 8a39558686 feat: add README for SSH agent and known_hosts management scripts 2025-12-06 19:19:48 +00:00
Steven 0f1cb7924d fix: permissions of docker-rsync scripts 2025-12-06 19:19:26 +00:00
Steven 05a269aeea v8 - 8.0.0 (#88)
* feat: latest Alpine 3.23.0
* feat: latest Rsync 3.4.1-r1
* feat: integrate [rsync-docker](https://github.com/JoshPiper/rsync-docker/) 3rd party into this action as 1st party code (no more dependency, better audit, single source of truth)
   - backported:
       - agent-start
       - agent-stop
       - agent-askpass
       - agent-add
       - hosts-add
       - hosts-clear
   - new added: 
       - ssh-init
       - hosts-init
   - improved: 
     - stricter permissions on .ssh/ folder (700) and known_hosts (600)
     - use set -eu in all scipts
* feat: new ``strict_host_keys`` option to enable support for strict host key verification. Default: false (to keep backward compatibility)
* feat: new ``debug`` option to see the commands executed (-x) by this action
* feat: this action is now scanned for vulnerabilities by Snyk
* feat; this action is now scanned by CodeQL for Q/A
* feat: this action now performs CI tasks such as Validation, Linting and Unit Tests
* fix: various shell syntax for robustness
* fix: use printf and redirect output to non-stdout instead of echo in sensitive code locations
* refactor: use $HOME instead of tilde ~ for robustness
* feat: cross-platform support
* chore: Deprecate 7.0.2
* chore: EOL 7.0.0 & 7.0.1
2025-12-06 16:57:20 +01:00
Steven 92961b5880 feat: always force-upgrade alpine openssl
Force upgrade the alpines openssl to  3.5.4-r0 in order to tackle CVE-2025-9230 (low)
CVE-2025-9231 (low)
CVE-2025-9232 (low)

See: 
https://github.com/Burnett01/rsync-deployments/security/code-scanning/7

https://github.com/Burnett01/rsync-deployments/security/code-scanning/8

https://github.com/Burnett01/rsync-deployments/security/code-scanning/9
2025-10-07 19:04:58 +02:00
Steven 96abc27e05 fix: snyk-docker-vulnerability-scan sarif
See https://github.com/github/codeql-action/issues/2187#issuecomment-2043220400
2025-10-07 18:55:29 +02:00
Steven 7e729bf4dd fix: snyk-docker-vulnerability-scan sarif
See https://github.com/github/codeql-action/issues/2187#issuecomment-2043220400
2025-10-07 18:53:39 +02:00
Steven c23b68a9ef chore: snyk output sarif file content 2025-10-07 18:45:23 +02:00
Steven 3e83373c59 fix: snyk-docker-vulnerability-scan sarif
caused by github/codeql-action#3156
2025-10-07 18:33:54 +02:00
Steven da6a0e1f57 fix: snyk-docker-vulnerability-scan sarif
caused by github/codeql-action#3156
2025-10-07 18:30:41 +02:00
Steven 0b92d76269 fix: snyk-docker-vulnerability-scan sarif
caused by https://github.com/github/codeql-action/issues/3156
2025-10-07 18:10:15 +02:00
Copilot 78cbabbd5c chore: adjust troubleshooting section for missing rsync on remote host (#86)
* Adjust troubleshooting section for missing rsync on remote host

Co-authored-by: Burnett01 <1208707+Burnett01@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Burnett01 <1208707+Burnett01@users.noreply.github.com>
2025-09-23 21:08:48 +02:00
Copilot f1607ccbba Add comprehensive SSH troubleshooting section with documentation links and improved secret naming to README (#83)
* chore: Add comprehensive SSH troubleshooting section to README

* chore: Enhance README with rsync documentation link, SSH key guide

* chore: further enrich readme with more troubleshooting + change secrets name from DEPLOY_* to REMOTE_*

* chore: Added a new section for versions and updated heading formatting.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Burnett01 <1208707+Burnett01@users.noreply.github.com>
Co-authored-by: sovetski
2025-09-19 15:40:13 +02:00
Steven 3de7ffff44 Revise Media section and add new pingback links
Updated section title and added media links.
2025-09-01 12:52:06 +02:00
Steven 9ffbf95175 chore: Add CI badges to README 2025-09-01 12:37:49 +02:00
Steven 02794c2f5a Rename CI workflow file to ci-validating-linting-testing.yml 2025-09-01 12:34:44 +02:00
Steven 7cbc96a81e Rename snyk-container.yml to snyk-docker-vulnerability-scan.yml 2025-09-01 12:34:18 +02:00
Steven 1eeed00fb4 chore: Update CI workflow name for clarity 2025-09-01 12:32:53 +02:00
Steven 581feb8967 Rename workflow to 'Snyk Docker Vulnerability Scan' 2025-09-01 12:31:06 +02:00
Steven fbd408424a feat: Snyk container workflow configuration (#79)
* Update Snyk container workflow configuration

* Update Docker image name in Snyk workflow

* Update Snyk action to use latest master version
2025-09-01 12:25:11 +02:00
Steven 51bdd07760 chore: issue templates 2025-09-01 11:41:30 +02:00
Steven eb1d171493 feat: restrict workflow permissions to PoLP (principle of least privilege)
Discovered by Code scanning alert no. 6: Workflow does not contain permissions (#78)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-09-01 11:37:07 +02:00
Steven 53581dff6d Add bats tests (#76)
* Add Bats tests and workflow for entrypoint.sh

* Add Bats tests and workflow

* Add comprehensive GitHub Actions CI workflow (#77)

* Initial plan

* Add comprehensive GitHub Actions CI workflow

Co-authored-by: Burnett01 <1208707+Burnett01@users.noreply.github.com>

* Enhance CI workflow with job dependencies and documentation

Co-authored-by: Burnett01 <1208707+Burnett01@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Burnett01 <1208707+Burnett01@users.noreply.github.com>

* Update CI workflow to only include master branch

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2025-08-29 22:50:40 +02:00
Steven 33214bd98b Release/7.1.0 (#72)
* upgrade to alpine from 3.19 to 3.22.1

Use drinternet/rsync 1.5.1 with alpine 3.22.1

https://hub.docker.com/layers/drinternet/rsync/v1.5.1/images/sha256-e61f4047577b566872764fa39299092adeab691efb3884248dbd6495dc926527

* upgrade to alpine from 3.19 to 3.22.1

Use drinternet/rsync 1.5.1 with alpine 3.22.1

https://hub.docker.com/layers/drinternet/rsync/v1.5.1/images/sha256-e61f4047577b566872764fa39299092adeab691efb3884248dbd6495dc926527

* Alpine 3.22.1

* Update SECURITY.md

* Alpine 3.22.1

* Update LICENSE
2025-08-29 20:57:37 +02:00
Steven Agyekum 22a7777152 Merge pull request #69 from Burnett01/release/7.0.2
Release/7.0.2
2025-01-19 15:36:00 +01:00
Steven Agyekum 3cccb68511 Update SECURITY.md 2025-01-19 15:32:42 +01:00
Steven Agyekum e642759b84 new version 7.0.2 (with rsync 3.4.0), deprecate old versions, remove dead links
The latest rsync version 3.4.0 fixes a wide variety of CVE's:

CVE-2024-12084 -⁠ Heap Buffer Overflow in Checksum Parsing.

CVE-2024-12085 -⁠ Info Leak via uninitialized Stack contents defeats ASLR.

CVE-2024-12086 -⁠ Server leaks arbitrary client files.

CVE-2024-12087 -⁠ Server can make client write files outside of destination directory using symbolic links.

CVE-2024-12088 -⁠ -⁠-⁠safe-⁠links Bypass.

CVE-2024-12747 -⁠ symlink race condition.

See their press release: https://download.samba.org/pub/rsync/NEWS#3.4.0

The latest action version 7.0.2 is using rsync 3.4.0, so please use that.
2025-01-19 15:29:07 +01:00
Steven Agyekum 76404482ea always force-upgrade rsync to get the latest security upgrades 2025-01-19 15:19:29 +01:00
Steven Agyekum d19dd4a0be Merge pull request #68 from ilyabrin/patch-1
Update README.md
2024-09-22 11:35:23 +02:00
Ilya Brin f825a1ed74 Update README.md
added syntax highlighting
2024-09-14 14:32:58 +03:00
Steven Agyekum 796cf0d5e4 Merge pull request #61 from Burnett01/release/7.0.1
- Pin @JoshPiper [drinternet/rsync](https://github.com/JoshPiper/rsync-docker) image by SHA-256 hash rather than version.  (Immutability)
Added via #60 

The docker image of this action is now pinned to the specific SHA-256 hash of the version rather than just the version.
This means for the latest `drinternet/rsync:v1.4.4` the corresponding hash is `drinternet/rsync@sha256:15b2949838074bd93c49421c22380396a0cd53a322439e799ac87afcadcfe234`

Check for validation: https://hub.docker.com/layers/drinternet/rsync/v1.4.4/images/sha256-15b2949838074bd93c49421c22380396a0cd53a322439e799ac87afcadcfe234

With that, usage of this action is even more secure due to a consistent dependency chain of trust,
since changes accompanied by a docker image hash are immutable.

Thanks to @XComp
2024-03-31 18:11:10 +02:00
Steven Agyekum b2bc75ad2c Merge pull request #60 from XComp/use-hash-instead-of-version-tag
Use SHA instead of Docker version tag for base image to allow for consistent code execution.
2024-03-31 17:50:56 +02:00
Steven Agyekum 93c0d7acae upd: mention version 7.0.1 2024-03-30 10:49:50 +01:00
Steven Agyekum 13aa4f9f57 update year to 2024 2024-03-30 10:46:13 +01:00
Matthias Pohl b16614048b Use SHA instead of Docker version tag for base image to allow for consistent code execution. 2024-03-28 17:53:03 +01:00
Steven Agyekum e1c5b900e9 Merge pull request #59 from Burnett01/release/7.0.0
Release/7.0.0
2024-03-06 15:06:24 +01:00
Steven Agyekum 93f02b856f chore: adjust readme for release 7.0.0 2024-03-06 15:04:26 +01:00
Steven Agyekum 21c0e5a9d9 chore: mention latest Alpine 3.19.1 2024-03-06 14:33:58 +01:00
Steven Agyekum c88a1dbded chore: adjust for EOL, DEPRECATION and MAINTENANCE 2024-03-06 14:33:02 +01:00
Steven Agyekum b9a68ac619 chore!: Versions 4.x EOL, 5.x DEPRECATED, 6.x MAINTENANCE
- All versions 4.x are now EOL and no longer maintained
- All versions 5.x are now DEPRECATED and will become EOL within Q2 2024
- All versions  6.x are now MAINTENANCE and will become DEPRECATED within Q4 2024
2024-03-06 12:35:07 +01:00
Steven Agyekum f479c97783 chore: mention new legacy_allow_rsa_hostkeys option 2024-03-06 12:29:40 +01:00
Steven Agyekum 008719532f feat: configuarable legacy RSA hostkeys support
Ability to configure legacy rsa hostkeys support for
OpenSSH servers < 8.8.
Related to #24 and  9603fc8
2024-03-06 12:20:39 +01:00
Steven Agyekum 9603fc8186 feat: Make usage of legacy rsa hostkeys conditional
The usage of RSA host keys introduced with c7baefdc23 
was adjusted to make it conditional/configurable and to keep
backward compatibility
2024-03-06 12:16:35 +01:00
Steven Agyekum 580c98fc2e Merge pull request #58 from Burnett01/release/5.3
Backmerge unofficial release/5.3 into new upcoming rlease/7.0.0
2024-03-06 12:04:45 +01:00
Steven Agyekum ee287eb1f0 feat: Update base image to latest 1.4.4 (apline 3.19.1) 2024-03-06 11:58:08 +01:00
Steven Agyekum c04732dab2 added v6 as new major 2023-06-08 18:05:17 +02:00
Steven Agyekum fb06973f0e Merge pull request #45 from Burnett01/release/6.0.0
Release/6.0.0
2023-06-08 17:54:57 +02:00
Steven Agyekum 45d84ad5f6 New version 6.0.0
- It is no longer possible to use an empty string as remote_path (Fixes #44) (Thanks to @maximilliangeorge)
- Updated checkout action in examples from v2 to v3
- Added disclaimer to media site-links
- Overall readme improvements
2023-06-08 17:54:10 +02:00
Steven Agyekum d732b39732 improved string empty check for remote_path 2023-06-08 17:35:29 +02:00
Steven Agyekum 570fd6bb52 fix empty string check 2023-06-08 17:27:31 +02:00
Steven Agyekum bef106d127 validate remote_path is not empty 2023-06-08 17:23:41 +02:00
Steven Agyekum b247bfd3af versions correction 2023-06-01 11:49:29 +02:00
Steven Agyekum f17a58e4ba adjust readme with correct versions 2023-06-01 11:48:45 +02:00
Steven Agyekum 8bb79ee6b5 Merge pull request #42 from Burnett01/dependabot/docker/drinternet/rsync-v1.4.3 2023-04-01 17:59:03 +02:00
dependabot[bot] b2007e683f Bump drinternet/rsync from v1.4.2 to v1.4.3
Bumps drinternet/rsync from v1.4.2 to v1.4.3.

---
updated-dependencies:
- dependency-name: drinternet/rsync
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-01 02:56:43 +00:00
Steven Agyekum 48dde0d741 Merge pull request #35 from Burnett01/dependabot/docker/drinternet/rsync-v1.4.2
Bump drinternet/rsync from v1.4.1 to v1.4.2
2022-12-11 20:22:59 +01:00
dependabot[bot] 4b36c0937b Bump drinternet/rsync from v1.4.1 to v1.4.2
Bumps drinternet/rsync from v1.4.1 to v1.4.2.

---
updated-dependencies:
- dependency-name: drinternet/rsync
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-01 02:03:49 +00:00
Steven Agyekum 2651e3eecb Merge pull request #34 from Burnett01/release/5.2.1
Release/5.2.1
2022-08-01 18:02:21 +02:00
Steven Agyekum a9c15493e0 mention version 5.2.1 2022-08-01 17:59:24 +02:00
Steven Agyekum b107255845 Merge pull request #33 from Burnett01/dependabot/docker/drinternet/rsync-v1.4.1
Bump drinternet/rsync from v1.4.0 to v1.4.1
2022-08-01 17:50:38 +02:00
Steven Agyekum d987a9a536 Merge pull request #32 from Burnett01/dependabot/docker/drinternet/rsync-v1.4.1
Bump drinternet/rsync from v1.4.0 to v1.4.1
2022-08-01 17:31:49 +02:00
dependabot[bot] de20664c6e Bump drinternet/rsync from v1.4.0 to v1.4.1
Bumps drinternet/rsync from v1.4.0 to v1.4.1.

---
updated-dependencies:
- dependency-name: drinternet/rsync
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 02:08:20 +00:00
Steven Agyekum d2a4efa87c Update with suggestions from #31
#31
2022-07-30 10:19:44 +02:00
Steven Agyekum a078b62820 Merge pull request #24 from jasongill/patch-1
Re-allow RSA host keys with SSH
2022-03-24 19:06:39 +01:00
Jason Gill c7baefdc23 Allow RSA host keys
RSA host keys are disabled by default on OpenSSH 8.8+ which is used by the base Alpine image, but many servers still use RSA host keys
2022-03-02 12:29:53 -05:00
Steven Agyekum 9f40ee1996 version 3.0 is EOL (see #23) 2022-01-01 19:29:16 +01:00
Steven Agyekum 0dc935cdec Merge pull request #23 from Burnett01/feature/maintenance-2022
Version 5.2
2022-01-01 19:16:33 +01:00
dependabot[bot] 4afbe87441 Bump drinternet/rsync from v1.3.0 to v1.4.0 (#22)
Bumps drinternet/rsync from v1.3.0 to v1.4.0.

---
updated-dependencies:
- dependency-name: drinternet/rsync
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-01 19:07:48 +01:00
Steven Agyekum 6ae12186da bump version to 5.2 in Readme 2022-01-01 19:07:03 +01:00
Steven Agyekum 4a950331e5 dropped support for 3.0 2022-01-01 19:02:50 +01:00
Steven Agyekum 057a69d147 Update LICENSE 2022-01-01 19:00:50 +01:00
Steven Agyekum 164dafd7fc Create dependabot.yml 2021-09-01 12:47:46 +02:00
Steven Agyekum b943ffe476 Release/v5.1 (#15)
* update base image drinternet/rsync:v1.3.0

* Base Image updates:  alpine 3.14.1 latest

* use v5.1 in examples

* support for v5.x

* mention Alpine version
2021-08-12 18:45:01 +02:00
Steven Agyekum 342e70b07e Release/v5 (#13)
* Reference JoshPiper/rsync-docker @ 1.1.0

* See: https://github.com/JoshPiper/rsync-docker/tree/1.1.0
* New features: Support passphrase protected keys

* supply SSH_PASS (key passphrase) to agent-add

Read more about the behavior: https://github.com/JoshPiper/rsync-docker#agent-askpass

* add new remote_key_pass config option

* Update README.md

* Update README.md

* 2.0 is EOL

* support 5.0, drop 2.0

* default to empty string

* reference JoshPiper/rsync-docker @ v1.2.0
2021-08-02 21:57:01 +02:00
Steven Agyekum a93a577f3f add more blogs/media 2021-04-03 15:02:42 +02:00
Steven Agyekum 22f8d1ffe8 2021 2021-01-01 17:46:52 +01:00
Steven Agyekum 695f58ca67 mention blogs 2020-10-05 18:46:16 +02:00
Steven Agyekum b1aa5210b1 Create CONTRIBUTING.md 2020-06-27 15:55:57 +02:00
Steven Agyekum 5aaa93368b Create CODE_OF_CONDUCT.md 2020-06-27 15:55:31 +02:00
Steven Agyekum 248befb7da Create SECURITY.md 2020-06-27 15:53:22 +02:00
Steven Agyekum 23a557dceb Update README.md 2020-06-23 00:08:44 +02:00
Steven Agyekum ea3f2b7314 improve code-formatting 2020-06-22 21:40:12 +02:00
Steven Agyekum 469a77e7aa use actions/checkout@v2 for even faster deployments
The actions/checkout@v2 action uses a checkout depth of 1 by default.
There is no more need to set it manually.
2020-03-27 14:55:02 +01:00
Steven Agyekum 819cb701d2 Update README.md 2020-01-08 20:10:18 +01:00
Steven Agyekum c269e19dd0 Changes in 4.0 2020-01-05 14:47:18 +01:00
Steven Agyekum c39ab06b30 Merge pull request #4 from JoshPiper/feat/rsync-image
Feat/rsync image
2020-01-05 14:40:05 +01:00
JoshPiper 9f59b515f6 Update entrypoint.sh 2020-01-05 11:19:21 +00:00
JoshPiper c5464e03ed Use sh not bash. 2020-01-05 11:11:59 +00:00
JoshPiper 0010c2adf6 Update entrypoint.sh 2020-01-05 11:06:14 +00:00
JoshPiper c6d9be15a7 Update Dockerfile 2020-01-05 11:03:17 +00:00
Steven Agyekum d75a44a646 2020 2019-12-31 16:54:40 +01:00
Steven Agyekum c47cfee594 Version 3.0 - faster deployments
* Feat/new base image
2019-12-27 16:39:11 +01:00
Steven Agyekum 7e62b51e32 Update README.md 2019-12-27 16:37:44 +01:00
Steven Agyekum f8c929a1f4 Update README.md 2019-12-27 16:33:45 +01:00
Steven Agyekum 6a989b68a1 Update README.md 2019-12-27 16:29:01 +01:00
Steven Agyekum 6fa9b56771 Update Dockerfile 2019-12-27 16:14:47 +01:00
Steven Agyekum f5c5431bf6 Update entrypoint.sh 2019-12-27 16:12:10 +01:00
Steven Agyekum 20b1f5b4b8 Update Dockerfile 2019-12-27 16:11:54 +01:00
Steven Agyekum 1bbe8382e5 Update Dockerfile 2019-12-27 16:08:00 +01:00
24 changed files with 1026 additions and 58 deletions
+5
View File
@@ -0,0 +1,5 @@
Dockerfile
LICENSE
*.md
.git*
.github*
+15
View File
@@ -0,0 +1,15 @@
root = true
[*]
charset = utf-8
end_of_line = lf
tab_width = 4
indent_size = 4
indent_style = space
max_line_length = 9999
insert_final_newline = true
trim_trailing_whitespace = true
[*.{yml,yaml}]
tab_width = 2
indent_size = 2
+33
View File
@@ -0,0 +1,33 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Action version**
eg. 7.0.1
**Runner OS+Version**
eg. ubuntu-latest
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: docker
directory: /
schedule:
interval: monthly
@@ -0,0 +1,165 @@
# GitHub Actions CI workflow for rsync-deployments
# This workflow validates the action on every push and pull request by:
# - Running BATS tests for the entrypoint script
# - Validating the action.yml definition
# - Building and testing the Docker image
# - Checking file structure and permissions
# - Linting shell scripts
# - Running a final integration check
name: CI - Validating, Linting, Testing
permissions:
contents: read
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
runs-on: ubuntu-latest
name: Test BATS Suite
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install BATS
run: |
sudo apt-get update
sudo apt-get install -y bats
- name: Run BATS tests
run: bats test/entrypoint.bats
validate-action:
runs-on: ubuntu-latest
name: Validate Action Definition
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate action.yml
run: |
# Check if action.yml exists and has required fields
if [ ! -f "action.yml" ]; then
echo "Error: action.yml not found"
exit 1
fi
# Basic validation that action.yml contains required fields
python3 -c "
import yaml
import sys
with open('action.yml', 'r') as f:
action = yaml.safe_load(f)
required_fields = ['name', 'description', 'inputs', 'runs']
for field in required_fields:
if field not in action:
print(f'Missing required field: {field}')
sys.exit(1)
# Check required inputs exist
required_inputs = ['switches', 'remote_path', 'remote_host', 'remote_user', 'remote_key']
for input_name in required_inputs:
if input_name not in action['inputs']:
print(f'Missing required input: {input_name}')
sys.exit(1)
if not action['inputs'][input_name].get('required', False):
print(f'Input {input_name} should be marked as required')
sys.exit(1)
print('Action definition is valid')
"
docker-build:
runs-on: ubuntu-latest
name: Build Docker Image
needs: [validate-action, action-structure]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: |
echo "Building Docker image..."
docker build -t rsync-deployments . --no-cache
echo "Docker image built successfully"
action-structure:
runs-on: ubuntu-latest
name: Validate Action Structure
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check required files
run: |
echo "Checking required files exist..."
# Check all required files exist
required_files=("action.yml" "Dockerfile" "entrypoint.sh")
for file in "${required_files[@]}"; do
if [ ! -f "$file" ]; then
echo "Error: Required file $file not found"
exit 1
fi
echo "✓ $file exists"
done
# Check entrypoint is executable
if [ ! -x "entrypoint.sh" ]; then
echo "Error: entrypoint.sh is not executable"
exit 1
fi
echo "✓ entrypoint.sh is executable"
# Check basic script syntax
bash -n entrypoint.sh
echo "✓ entrypoint.sh has valid syntax"
echo "All structure checks passed!"
lint-shell:
runs-on: ubuntu-latest
name: Lint Shell Scripts
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install ShellCheck
run: |
sudo apt-get update
sudo apt-get install -y shellcheck
- name: Lint entrypoint.sh
run: |
echo "Linting shell scripts..."
# Run shellcheck with exclusions for Docker-specific dependencies
shellcheck -e SC1091 -e SC3046 entrypoint.sh || {
echo "ShellCheck found issues, but running with Docker-specific exclusions..."
shellcheck -e SC1091 -e SC3046 entrypoint.sh
}
echo "Shell script linting completed"
integration-check:
runs-on: ubuntu-latest
name: Integration Check
needs: [test, validate-action, docker-build, action-structure, lint-shell]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Final integration check
run: |
echo "All CI jobs completed successfully!"
echo "✅ BATS tests passed"
echo "✅ Action definition validated"
echo "✅ Docker image built and tested"
echo "✅ File structure validated"
echo "✅ Shell scripts linted"
echo ""
echo "🎉 rsync-deployments action is ready for use!"
@@ -0,0 +1,41 @@
name: Snyk Docker Vulnerability Scan
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '39 13 * * 4'
permissions:
contents: read
jobs:
snyk:
permissions:
contents: read
security-events: write
actions: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build a Docker image
run: docker build -t burnett01/rsync-deployments .
- name: Run Snyk to check Docker image for vulnerabilities
continue-on-error: true
uses: snyk/actions/docker@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
image: burnett01/rsync-deployments
args: --file=Dockerfile
- name: Output sarif file
run: cat snyk.sarif
- name: fix security-severity "null" to "0" for valid sarif format
run: |
sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif
- name: Upload result to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: snyk.sarif
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team via issues. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+1
View File
@@ -0,0 +1 @@
Feel free to contribute to this project.
+10 -7
View File
@@ -1,12 +1,15 @@
FROM ubuntu:latest
FROM alpine:3.23.0@sha256:51183f2cfa6320055da30872f211093f9ff1d3cf06f39a0bdb212314c5dc7375 AS base
# Update
RUN apt-get update
RUN apk update && apk add --no-cache --upgrade rsync openssh openssl busybox
# Install packages
RUN apt-get -yq install rsync openssh-client
RUN rm -rf /var/cache/apk/*
# Copy entrypoint
ADD entrypoint.sh /entrypoint.sh
COPY docker-rsync/* /bin/
RUN chmod +x /bin/agent-* /bin/ssh-* /bin/hosts-*
FROM base AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
+3 -2
View File
@@ -1,7 +1,8 @@
MIT License
Copyright (c) 2019 Contention
Copyright (c) 2019 Burnett01
Copyright (c) 2019-2022 Contention
Copyright (c) 2019-2025 Joshua Piper (Dr Internet)
Copyright (c) 2019-2025 Burnett01
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+311 -38
View File
@@ -1,21 +1,35 @@
# rsync deployments
Forked from [Contention/rsync-deployments](https://github.com/Contention/rsync-deployments)
[![CI - Validating, Linting, Testing](https://github.com/Burnett01/rsync-deployments/actions/workflows/ci-validating-linting-testing.yml/badge.svg)](https://github.com/Burnett01/rsync-deployments/actions/workflows/ci-validating-linting-testing.yml)
[![Snyk Docker Vulnerability Scan](https://github.com/Burnett01/rsync-deployments/actions/workflows/snyk-docker-vulnerability-scan.yml/badge.svg)](https://github.com/Burnett01/rsync-deployments/actions/workflows/snyk-docker-vulnerability-scan.yml)
[![CodeQL](https://github.com/Burnett01/rsync-deployments/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/Burnett01/rsync-deployments/actions/workflows/github-code-scanning/codeql)
[![Dependabot Updates](https://github.com/Burnett01/rsync-deployments/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/Burnett01/rsync-deployments/actions/workflows/dependabot/dependabot-updates)
This GitHub Action deploys files in `GITHUB_WORKSPACE` to a folder on a server via rsync over ssh.
This cross-platform GitHub Action deploys files in [`path`](#inputs) (relative to `GITHUB_WORKSPACE`) to a remote folder via rsync over ssh.
Use this action in a build/test workflow which leaves deployable code in `GITHUB_WORKSPACE`.
Use this action in a CD workflow which leaves deployable code in `GITHUB_WORKSPACE`, such [actions/checkout](https://github.com/actions/checkout).
The base-image of this action is very small and based on **Alpine 3.23.0** (no cache) which results in fast deployments.
Alpine version: [3.23.0](https://www.alpinelinux.org/posts/Alpine-3.23.0-released.html)
Rsync version: [3.4.1-r1](https://download.samba.org/pub/rsync/NEWS#3.4.1)
---
## Inputs
- `debug`* - Whether to enable debug output. ("true" / "false") - Default: "false"
- `switches`* - The first is for any initial/required rsync flags, eg: `-avzr --delete`
- `rsh` - Remote shell commands
- `path` - The source path. Defaults to GITHUB_WORKSPACE
- `strict_hostkeys_checking` - Enables support for strict hostkeys (fingerprint) checking. ("true" / "false") - Default: "false"
- `legacy_allow_rsa_hostkeys` - Enables support for legacy RSA host keys on OpenSSH 8.8+. ("true" / "false") - Default: "false"
- `path` - The source path. Defaults to GITHUB_WORKSPACE and is relative to it
- `remote_path`* - The deployment target path
@@ -25,19 +39,37 @@ Use this action in a build/test workflow which leaves deployable code in `GITHUB
- `remote_user`* - The remote user
- `remote_key`* - The remote ssh key
- `remote_key`* - The remote ssh private key
- `remote_key_pass` - The remote ssh private key passphrase (if any)
``* = Required``
## Required secret
## Required secret(s)
This action needs a `DEPLOY_KEY` secret variable. This should be the private key part of a ssh key pair. The public key part should be added to the authorized_keys file on the server that receives the deployment. This should be set in the Github secrets section and then referenced as the `remote_key` input.
This action needs secret variables for the ssh private key of your key pair. The public key part should be added to the authorized_keys file on the server that receives the deployment. The secret variable should be set in the Github secrets section of your org/repo and then referenced as the `remote_key` input.
> Always use secrets when dealing with sensitive inputs!
For simplicity, we are using `REMOTE_*` as the secret variables throughout the examples.
## Current Version: v8 (8.0.2)
### Release channels:
| Version | Purpose | Immutable |
| ------- | ------------------ | ------------------ |
| ``v8`` | latest release (pointer to 8.x.x) | no, points to latest MINOR,PATCH |
| 8.0.2 | latest major release | yes |
| 7.1.0 | previous release | yes |
Check [SECURITY.md](SECURITY.md) for support cycles.
## Example usage
Simple:
```
```yml
name: DEPLOY
on:
push:
@@ -48,34 +80,28 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v6
- name: rsync deployments
uses: burnett01/rsync-deployments@2.0
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete
path: src/
remote_path: /var/www/html/
remote_host: example.com
remote_user: debian
remote_key: ${{ secrets.DEPLOY_KEY }}
remote_key: ${{ secrets.REMOTE_PRIVATE_KEY }}
```
Advanced:
```
name: DEPLOY
on:
push:
branches:
- master
```yml
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v6
- name: rsync deployments
uses: burnett01/rsync-deployments@2.0
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete --exclude="" --include="" --filter=""
path: src/
@@ -83,41 +109,288 @@ jobs:
remote_host: example.com
remote_port: 5555
remote_user: debian
remote_key: ${{ secrets.DEPLOY_KEY }}
remote_key: ${{ secrets.REMOTE_PRIVATE_KEY }}
```
For better security, I suggest you create additional secrets for remote_host, remote_port and remote_user inputs.
```
name: DEPLOY
on:
push:
branches:
- master
For better **security**, I suggest you create additional secrets for remote_host, remote_port, remote_user and remote_path inputs.
```yml
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v6
- name: rsync deployments
uses: burnett01/rsync-deployments@2.0
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete
path: src/
remote_path: /var/www/html/
remote_host: ${{ secrets.DEPLOY_HOST }}
remote_port: ${{ secrets.DEPLOY_PORT }}
remote_user: ${{ secrets.DEPLOY_USER }}
remote_key: ${{ secrets.DEPLOY_KEY }}
remote_path: ${{ secrets.REMOTE_PATH }}
remote_host: ${{ secrets.REMOTE_HOST }}
remote_port: ${{ secrets.REMOTE_PORT }}
remote_user: ${{ secrets.REMOTE_USER }}
remote_key: ${{ secrets.REMOTE_PRIVATE_KEY }}
```
If your private key is passphrase protected you should use:
```yml
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: rsync deployments
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete
path: src/
remote_path: ${{ secrets.REMOTE_PATH }}
remote_host: ${{ secrets.REMOTE_HOST }}
remote_port: ${{ secrets.REMOTE_PORT }}
remote_user: ${{ secrets.REMOTE_USER }}
remote_key: ${{ secrets.REMOTE_PRIVATE_KEY }}
remote_key_pass: ${{ secrets.REMOTE_PRIVATE_KEY_PASS }}
```
---
## Version 1.0 (EOL)
#### Legacy RSA Hostkeys support for OpenSSH Servers >= 8.8+
Looking for version 1.0?
If your remote OpenSSH Server still uses RSA hostkeys, then you have to
manually enable legacy support for this by using ``legacy_allow_rsa_hostkeys: "true"``.
```yml
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: rsync deployments
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete
legacy_allow_rsa_hostkeys: "true"
path: src/
remote_path: ${{ secrets.REMOTE_PATH }}
remote_host: ${{ secrets.REMOTE_HOST }}
remote_port: ${{ secrets.REMOTE_PORT }}
remote_user: ${{ secrets.REMOTE_USER }}
remote_key: ${{ secrets.REMOTE_PRIVATE_KEY }}
```
See [#49](https://github.com/Burnett01/rsync-deployments/issues/49) and [#24](https://github.com/Burnett01/rsync-deployments/issues/24) for more information.
**Note:** Only use this if necessary. It's recommended to upgrade your remote OpenSSH server instead.
--
## Advanced Rsync switches/flags/options
For advanced rsync configuration options and switches, refer to the [rsync manual](https://linux.die.net/man/1/rsync).
---
## Troubleshooting
### SSH Permission Denied Errors
If you encounter "Permission denied (publickey,password)" errors, here are the most common solutions:
#### 1. SSH Key Setup
Ensure your SSH key pair is correctly generated and configured:
```bash
# Generate a new SSH key pair (recommended: Ed25519 or RSA 4096-bit)
ssh-keygen -t ed25519 -C "deploy@yourproject" -f ~/.ssh/deploy_yourproject -N ""
# OR for RSA:
ssh-keygen -t rsa -b 4096 -C "deploy@yourproject" -f ~/.ssh/deploy_yourproject -N ""
```
**Important Steps:**
- Add the **public key** (`.pub` file) to your server's `~/.ssh/authorized_keys`
- Add the **private key** (without `.pub` extension) to GitHub Secrets as `REMOTE_PRIVATE_KEY`
- Ensure correct file permissions on your server:
```bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
```
For detailed information on creating and managing SSH keys, see [GitHub's SSH Key Guide](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
#### 2. ``remote_path`` permissions
Make sure the ``remote_user`` has write access to ``remote_path``.
See: https://github.com/Burnett01/rsync-deployments/issues/81#issuecomment-3308152891
#### 3. Firewall / GitHub Actions IP Restrictions
If your remote server has firewall restrictions:
- **Option A:** Whitelist [GitHub Actions IP ranges](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#ip-addresses) (Azure-based)
- **Option B:** Use self-hosted runners on your server (recommended for strict firewall environments)
### Excluding files/folders (eg .git)
By default, rsync copies dot files and folder if present at ``path:``. To exclude them, you can use the ``--exclude`` switch:
```yml
switches: -avzr --delete --exclude='.git/'
```
Other common exclusions:
```yml
switches: -avzr --delete --exclude='.git/' --exclude='node_modules/' --exclude='.env'
```
More advanced examples:
- https://github.com/Burnett01/rsync-deployments/issues/5#issuecomment-667589874
- https://github.com/Burnett01/rsync-deployments/issues/16
- https://github.com/Burnett01/rsync-deployments/issues/71
- https://github.com/Burnett01/rsync-deployments/issues/52
### Missing rsync on Remote Host
If the action fails with "rsync: command not found" or similar errors, rsync is not installed on your remote server. Install it using your system's package manager:
**Ubuntu/Debian:**
```bash
sudo apt-get update && sudo apt-get install rsync
```
**CentOS/RHEL/Rocky/AlmaLinux:**
```bash
sudo yum install rsync
# OR on newer versions:
sudo dnf install rsync
```
**Alpine Linux:**
```bash
sudo apk add rsync
```
---
## Versions
## Version 8.0.0 (EOL due to regression -> fixed via 8.0.1 & 8.0.2)
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/8.0.0 (alpine 3.23.0)
## Version 7.1.0
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/7.1.0 (alpine 3.22.1)
## Version 7.0.2 (DEPRECATED)
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/7.0.2 (alpine 3.22.1)
---
## Version 7.0.0 & 7.0.1 (EOL)
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/7.0.0 (alpine 3.19.1)
- https://github.com/Burnett01/rsync-deployments/tree/7.0.1 (alpine 3.22.1)
---
## Version 6.0 (EOL)
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/6.0 (alpine 3.17.2)
---
## Version 5.0, 5.1 & 5.2 & 5.x (EOL)
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/5.0 (alpine 3.11.x)
- https://github.com/Burnett01/rsync-deployments/tree/5.1 (alpine 3.14.1)
- https://github.com/Burnett01/rsync-deployments/tree/5.2 (alpine 3.15.0)
- https://github.com/Burnett01/rsync-deployments/tree/5.2.1 (alpine 3.16.1)
- https://github.com/Burnett01/rsync-deployments/tree/5.2.2 (alpine 3.17.2)
---
## Version 4.0 & 4.1 (EOL)
Check here:
- https://github.com/Burnett01/rsync-deployments/tree/4.0
- https://github.com/Burnett01/rsync-deployments/tree/4.1
Version 4.0 & 4.1 use the ``drinternet/rsync:1.0.1`` base-image.
---
## Version 3.0 (EOL)
Check here: https://github.com/Burnett01/rsync-deployments/tree/3.0
Version 3.0 uses the ``alpine:latest`` base-image directly.<br>
Consider upgrading to 4.0 that uses a docker-image ``drinternet/rsync:1.0.1`` that is<br>
based on ``alpine:latest``and heavily optimized for rsync.
## Version 2.0 (EOL)
Check here: https://github.com/Burnett01/rsync-deployments/tree/2.0
Version 2.0 uses a larger base-image (``ubuntu:latest``).<br>
Consider upgrading to 3.0 for even faster deployments.
## Version 1.0 (EOL)
Check here: https://github.com/Burnett01/rsync-deployments/tree/1.0
Please note that version 1.0 has reached end of life state.
---
## Acknowledgements
+ This project is a fork of [Contention/rsync-deployments](https://github.com/Contention/rsync-deployments)
+ Base image [JoshPiper/rsync-docker](https://github.com/JoshPiper/rsync-docker)
---
## Media & Pingback
This action was featured in multiple blogs across the globe:
> Disclaimer: The author & co-authors are not responsible for the content of the site-links below.
- https://hosting.xyz/wiki/hosting/other/github-actions/
- https://www.alexander-palm.de/2025/07/22/sichere-rsync-deployments-mit-github-actions-und-rrsync/
- https://lab.uberspace.de/howto_automatic-deployment/
- https://blog.devops.dev/setting-up-an-ubuntu-instance-for-nodejs-apps-in-ovh-cloud-using-nginx-pm2-github-actions-7618c768d081
- https://elijahverdoorn.com/2020/04/14/automating-deployment-with-github-actions/
- https://www.vektor-inc.co.jp/post/github-actions-deploy/
- https://webpick.info/automatiser-avec-github-actions/
- https://matthias-andrasch.eu/blog/2021/tutorial-webseite-mittels-github-actions-deployment-zu-uberspace-uebertragen-rsync/
- https://jishuin.proginn.com/p/763bfbd38928
- https://cloud.tencent.com/developer/article/1786522
+33
View File
@@ -0,0 +1,33 @@
# Security Policy
The Docker image and code quality are regularly checked for vulnerabilities and CVEs by Snyk and CodeQL.
## Supported Versions
The following versions are currently being supported with security updates:
| Version | Supported | Rsync version | Alpine version |
| ------- | ------------------ | ------------------ | ------------------ |
| 8.0.2 | :white_check_mark: | >= 3.4.1-r1 | 3.23.0 |
| 8.0.1 | :white_check_mark: | >= 3.4.1-r1 | 3.23.0 |
| 8.0.0 | :x: EOL (due to regression #90) | >= 3.4.1-r1 | 3.23.0 |
| 7.1.0 | :white_check_mark: | >= 3.4.1-r0 | 3.22.1 |
| 7.0.2 | :warning: DEPRECATED | >= 3.4.0-r0 | 3.22.1 |
| 7.0.1 | :x: EOL | < 3.4.0 | 3.22.1 |
| 7.0.0 | :x: EOL | < 3.4.0| 3.19.1 |
| 6.x | :x: EOL |< 3.4.0| 3.17.2 |
| 5.x | :x: EOL |< 3.4.0| 3.11 - 3.14.1 - 3.15 - 3.16 - 3.17.2 |
| 4.x | :x: EOL |< 3.4.0| 3.11 |
| 3.0 | :x: EOL |< 3.4.0| N/A |
| 2.0 | :x: EOL |< 3.4.0| Ubuntu |
| 1.0 | :x: EOL |< 3.4.0| Ubuntu |
### Terminology
EOL = End of life (no support/no updates)
DEPRECATED = Close to EOL (support/no updates)
## Reporting a Vulnerability
You can report a vulnerability by creating an issue.
+16
View File
@@ -9,6 +9,14 @@ inputs:
description: 'The remote shell argument'
required: false
default: ''
legacy_allow_rsa_hostkeys:
description: 'Enables support for legacy RSA host keys on OpenSSH 8.8+'
required: false
default: 'false'
strict_hostkeys_checking:
description: 'Controls strict host keys checking'
required: false
default: 'false'
path:
description: 'The local path'
required: false
@@ -29,6 +37,14 @@ inputs:
remote_key:
description: 'The remote key'
required: true
remote_key_pass:
description: 'The remote key passphrase'
required: false
default: ''
debug:
description: 'Debug the action'
required: false
default: 'false'
runs:
using: 'docker'
image: 'Dockerfile'
+40
View File
@@ -0,0 +1,40 @@
# Scripts
Shell-scripts to help with managing SSH agents and known hosts files.
### SSH Management
#### ssh-init
This command create the ``$HOME/.ssh`` folder with default permissions ``700``.
### SSH-Agent Management
#### agent-start
This command starts the SSH agent, if it isn't already started (SSH_AGENT_PID set or ssh agent ID file found).
It takes one optional argument, for the name of the agent to be started. Defaults to "default".
This program needs to be source'd to work correctly.
`source agent-start "default"`
#### agent-stop
This command stops the SSH agent, if it is started (SSH_AGENT_PID set or ssh agent ID file found).
It takes one optional argument, for the name of the agent to be stopped. Defaults to "default".
`agent-stop "my-agent-name"`
#### agent-add
This command adds a key to the currently running SSH agent. The key is taken from stdin, and the agent used is that in SSH_AGENT_PID.
#### agent-askpass
This command is called by ssh-add when the [SSH_ASKPASS](https://man.openbsd.org/ssh-add.1#ENVIRONMENT) variable is set active. The command returns the SSH_PASS to [ssh-askpass(1)](https://man.openbsd.org/ssh-askpass.1).
This command is ignored by ssh-add if the key does not require a passphrase.
### known_hosts management
#### hosts-init
This command creates the known_hosts file (``$HOME/.ssh/known_hosts``) with default permission ``600``.
#### hosts-add
This command adds an entry to the known hosts file, and ensures its permissions are correct. It takes one argument, which is the new key to add.
#### hosts-clear
This command truncates the known_hosts file.
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
set -eu
source agent-start "${1:-default}"
cat - | tr -d '\r' | DISPLAY=1 SSH_ASKPASS=agent-askpass ssh-add - >/dev/null
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
set -eu
echo "$SSH_PASS"
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
set -eu
FOLDER=${1:-default}
STORE_PATH="/tmp/ssh-agent/$FOLDER"
mkdir -p "$STORE_PATH"
if [ -z "${SSH_AGENT_PID:-}" ]; then
if [ -f "$STORE_PATH/id" ]; then
SSH_AGENT_PID=$(cat "$STORE_PATH/id")
export SSH_AGENT_PID
SSH_AUTH_SOCK=$(cat "$STORE_PATH/sock")
export SSH_AUTH_SOCK
else
eval "$(ssh-agent)" > /dev/null
echo "$SSH_AGENT_PID" > "$STORE_PATH"/id
echo "$SSH_AUTH_SOCK" > "$STORE_PATH"/sock
fi
fi
+37
View File
@@ -0,0 +1,37 @@
#!/bin/sh
set -eu
if [ ! -z "$SSH_AGENT_PID" ]; then
# Here, the environment is set already, just kill the script.
eval $(ssh-agent -k) >/dev/null
exit $?
else
# The env isn't set, construct the file path.
FOLDER=${1:-default}
STORE_PATH="/tmp/ssh-agent/$FOLDER"
if [ ! -d "$STORE_PATH" ]; then
echo "Store Path $STORE_PATH doesn't exist!" >&2
exit 1
fi
# And check our files exist.
if [ -f "$STORE_PATH/id" ]; then
# Grab our PID and socket.
SSH_AGENT_PID=$(cat "$STORE_PATH/id")
export SSH_AGENT_PID
rm "$STORE_PATH/id"
SSH_AUTH_SOCK=$(cat "$STORE_PATH/sock")
export SSH_AUTH_SOCK
rm "$STORE_PATH/sock"
rmdir "$STORE_PATH"
eval $(ssh-agent -k) >/dev/null
exit $?
else
echo "SSH_AGENT_PID not set, $STORE_PATH/id doesn't exist!" >&2
exit 1
fi
fi
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
set -eu
echo "$@" >> $HOME/.ssh/known_hosts
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
set -eu
truncate -s 0 $HOME/.ssh/known_hosts
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
set -eu
if [ ! -f "$HOME/.ssh/known_hosts" ]; then
touch $HOME/.ssh/known_hosts
fi
chmod 600 $HOME/.ssh/known_hosts
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
set -eu
if [ ! -d "$HOME/.ssh" ]; then
mkdir -m 700 $HOME/.ssh
fi
+48 -11
View File
@@ -1,18 +1,55 @@
#!/bin/bash
#!/bin/sh
set -eu
# Set deploy key
SSH_PATH="$HOME/.ssh"
if [ "${INPUT_DEBUG:-false}" = "true" ]; then
set -x
fi
# Create .ssh dir if it doesn't exist
[ -d "$SSH_PATH" ] || mkdir "$SSH_PATH"
if [ -z "$(echo "$INPUT_REMOTE_PATH" | awk '{$1=$1};1')" ]; then
echo "The remote_path can not be empty. see: github.com/Burnett01/rsync-deployments/issues/44"
exit 1
fi
# Place deploy_key into .ssh dir
echo "$INPUT_REMOTE_KEY" > "$SSH_PATH/key"
# Initialize SSH and known hosts.
source ssh-init
source hosts-init
# Set r+w to user only
chmod 600 "$SSH_PATH/key"
# Start the SSH agent and load key.
source agent-start "$GITHUB_ACTION"
echo "$INPUT_REMOTE_KEY" | SSH_PASS="$INPUT_REMOTE_KEY_PASS" agent-add
# Do deployment
sh -c "rsync $INPUT_SWITCHES -e 'ssh -i $SSH_PATH/key -o StrictHostKeyChecking=no -p $INPUT_REMOTE_PORT $INPUT_RSH' $GITHUB_WORKSPACE/$INPUT_PATH $INPUT_REMOTE_USER@$INPUT_REMOTE_HOST:$INPUT_REMOTE_PATH"
# Variables.
LEGACY_RSA_HOSTKEYS=""
if [ "${INPUT_LEGACY_ALLOW_RSA_HOSTKEYS:-false}" = "true" ]; then
LEGACY_RSA_HOSTKEYS="-o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa"
fi
STRICT_HOSTKEYS_CHECKING="-o StrictHostKeyChecking=no"
if [ "${INPUT_STRICT_HOSTKEYS_CHECKING:-false}" = "true" ]; then
STRICT_HOSTKEYS_CHECKING="-o UserKnownHostsFile=$HOME/.ssh/known_hosts -o StrictHostKeyChecking=yes"
key="$(ssh-keyscan -p "$INPUT_REMOTE_PORT" "$INPUT_REMOTE_HOST" 2>/dev/null | sed '/^#/d')" || key=""
if [ -n "$key" ]; then
# fingerprint verification
echo "$key" | ssh-keygen -lf -
# add to known hosts
echo "$key" | while IFS= read -r line; do hosts-add "$line"; done
else
echo "Warning: failed to fetch host key for $INPUT_REMOTE_HOST" >&2
exit 1
fi
fi
RSH="ssh $STRICT_HOSTKEYS_CHECKING $LEGACY_RSA_HOSTKEYS -p $INPUT_REMOTE_PORT $INPUT_RSH"
LOCAL_PATH="$GITHUB_WORKSPACE/$INPUT_PATH"
DSN="$INPUT_REMOTE_USER@$INPUT_REMOTE_HOST"
# Deploy.
sh -c "rsync $INPUT_SWITCHES -e '$RSH' $LOCAL_PATH $DSN:$INPUT_REMOTE_PATH"
# Clean up.
source agent-stop "$GITHUB_ACTION"
source hosts-clear
exit 0
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env bats
setup() {
# Create dummy binaries for sourcing
echo 'echo "source"' > source
echo 'echo "agent started"' > agent-start
echo 'echo "key added"' > agent-add
chmod +x source agent-start agent-add
# Create dummy rsync binary to capture its arguments
echo 'echo "rsync $@"' > rsync
chmod +x rsync
PATH="$PWD:$PATH"
}
teardown() {
rm -f source agent-start agent-add rsync ssh-keyscan hosts-add
}
@test "fails if INPUT_REMOTE_PATH is empty" {
export INPUT_REMOTE_PATH=" "
run ./entrypoint.sh
[ "$status" -eq 1 ]
[[ "${output}" == *"can not be empty"* ]]
}
@test "includes legacy RSA switches when allowed" {
export INPUT_LEGACY_ALLOW_RSA_HOSTKEYS="true"
export INPUT_REMOTE_PATH="remote/"
export INPUT_REMOTE_KEY="dummy"
export INPUT_REMOTE_KEY_PASS="dummy"
export GITHUB_ACTION="dummy"
export INPUT_SWITCHES="-avz"
export INPUT_REMOTE_PORT="22"
export INPUT_RSH=""
export INPUT_PATH=""
export INPUT_REMOTE_USER="user"
export INPUT_REMOTE_HOST="localhost.local"
export GITHUB_WORKSPACE="/tmp"
export DSN="user@localhost.local"
export LOCAL_PATH="/tmp/"
run ./entrypoint.sh
[[ "${output}" == *"rsync -avz -e ssh -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa -p 22 /tmp/ user@localhost.local:remote/"* ]]
}
@test "does not include legacy RSA switches when not allowed" {
export INPUT_LEGACY_ALLOW_RSA_HOSTKEYS="false"
export INPUT_REMOTE_PATH="remote/"
export INPUT_REMOTE_KEY="dummy"
export INPUT_REMOTE_KEY_PASS="dummy"
export GITHUB_ACTION="dummy"
export INPUT_SWITCHES="-avz"
export INPUT_REMOTE_PORT="22"
export INPUT_RSH=""
export INPUT_PATH=""
export INPUT_REMOTE_USER="user"
export INPUT_REMOTE_HOST="localhost.local"
export GITHUB_WORKSPACE="/tmp"
export DSN="user@localhost.local"
export LOCAL_PATH="/tmp/"
run ./entrypoint.sh
[[ "${output}" == *"rsync -avz -e ssh -o StrictHostKeyChecking=no -p 22 /tmp/ user@localhost.local:remote/"* ]]
}
@test "includes STRICT_HOSTKEYS_CHECKING switches when allowed" {
# Set a fake HOME dir
local -r HOME="/tmp"
export INPUT_LEGACY_ALLOW_RSA_HOSTKEYS="false"
export INPUT_STRICT_HOSTKEYS_CHECKING="true"
export INPUT_REMOTE_PATH="remote/"
export INPUT_REMOTE_KEY="dummy"
export INPUT_REMOTE_KEY_PASS="dummy"
export GITHUB_ACTION="dummy"
export INPUT_SWITCHES="-avz"
export INPUT_REMOTE_PORT="22"
export INPUT_RSH=""
export INPUT_PATH=""
export INPUT_REMOTE_USER="user"
export INPUT_REMOTE_HOST="localhost.local"
export GITHUB_WORKSPACE="/tmp"
export DSN="user@localhost.local"
export LOCAL_PATH="/tmp/"
# Generate a mock key pair to test ssh-keyscan (entrypoint.sh:32)
rm -f "$HOME/mockKeyPair" "$HOME/mockKeyPair.pub" \
&& ssh-keygen -t ed25519 -f "$HOME/mockKeyPair" -N '' -q -C '' \
&& mockPublicKey=$(< "$HOME/mockKeyPair.pub")
# Create dummy ssh-keyscan binary to return $mockPublicKey
echo "echo 'localhost.local $mockPublicKey #Mock 1'" > ssh-keyscan
chmod +x ssh-keyscan
# Create dummy hosts-add binary to capture its arguments
echo 'echo "hosts-add $@"' > hosts-add
chmod +x hosts-add
run ./entrypoint.sh
[[ "${output}" == *"hosts-add localhost.local ssh-ed25519"* ]]
[[ "${output}" == *"rsync -avz -e ssh -o UserKnownHostsFile=/tmp/.ssh/known_hosts -o StrictHostKeyChecking=yes -p 22 /tmp/ user@localhost.local:remote/"* ]]
}
@test "does not includes STRICT_HOSTKEYS_CHECKING switches when not allowed" {
export INPUT_LEGACY_ALLOW_RSA_HOSTKEYS="false"
export INPUT_STRICT_HOSTKEYS_CHECKING="false"
export INPUT_REMOTE_PATH="remote/"
export INPUT_REMOTE_KEY="dummy"
export INPUT_REMOTE_KEY_PASS="dummy"
export GITHUB_ACTION="dummy"
export INPUT_SWITCHES="-avz"
export INPUT_REMOTE_PORT="22"
export INPUT_RSH=""
export INPUT_PATH=""
export INPUT_REMOTE_USER="user"
export INPUT_REMOTE_HOST="localhost.local"
export GITHUB_WORKSPACE="/tmp"
export DSN="user@localhost.local"
export LOCAL_PATH="/tmp/"
run ./entrypoint.sh
[[ "${output}" == *"rsync -avz -e ssh -o StrictHostKeyChecking=no -p 22 /tmp/ user@localhost.local:remote/"* ]]
}