This cross-platform GitHub Action deploys files in path (relative to GITHUB_WORKSPACE) to a remote folder via rsync over ssh.
Use this action in a CD workflow which leaves deployable code in GITHUB_WORKSPACE, such actions/checkout.
The base-image of this action is very small and based on Alpine 3.23.2 (no cache) which results in fast deployments.
Alpine version: 3.23.2 Rsync version: 3.4.1-r1
| Version | Purpose | Immutable |
|---|---|---|
v8 (recommended) |
latest MAJOR (pointer to 8.MINOR.PATCH) | no |
| 8.0.3 | latest MINOR+PATCH | yes |
| 7.1.0 | previous MAJOR+MINOR (deprecation notice) | yes |
| 7.0.2 | previous MAJOR+PATCH (deprecation notice) | no |
Check SECURITY.md for support cycles.
name: DEPLOY
on:
push:
branches:
- master
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: $ # ex: /var/www/html/
remote_host: $ # ex: example.com
remote_port: $ # ex: 22
remote_user: $ # ex: ubuntu
remote_key: $
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
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
remote_host* - The remote host
remote_port - The remote port. Defaults to 22
remote_user* - The remote user
remote_key* - The remote ssh private key
remote_key_pass - The remote ssh private key passphrase (if any)
* = Required
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.
For better security always use secrets for remote_host, remote_port, remote_user and remote_path inputs.
Simple:
name: DEPLOY
on:
push:
branches:
- master
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: $ # ex: /var/www/html/
remote_host: $ # ex: example.com
remote_port: $ # ex: 22
remote_user: $ # ex: ubuntu
remote_key: $
Advanced (with filters etc):
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: rsync deployments
uses: burnett01/rsync-deployments@v8
with:
switches: -avzr --delete --exclude="" --include="" --filter=""
path: src/
remote_path: $ # ex: /var/www/html/
remote_host: $ # ex: example.com
remote_port: $ # ex: 22
remote_user: $ # ex: ubuntu
remote_key: $
If your private key is passphrase protected you should use:
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: $ # ex: /var/www/html/
remote_host: $ # ex: example.com
remote_port: $ # ex: 22
remote_user: $ # ex: ubuntu
remote_key: $
remote_key_pass: $
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".
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: $ # ex: /var/www/html/
remote_host: $ # ex: example.com
remote_port: $ # ex: 22
remote_user: $ # ex: ubuntu
remote_key: $
See #49 and #24 for more information.
Note: Only use this if necessary. It’s recommended to upgrade your remote OpenSSH server instead.
–
For advanced rsync configuration options and switches, refer to the rsync manual.
If you encounter “Permission denied (publickey,password)” errors, here are the most common solutions:
Ensure your SSH key pair is correctly generated and configured:
# 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:
.pub file) to your server’s ~/.ssh/authorized_keys.pub extension) to GitHub Secrets as REMOTE_PRIVATE_KEYchmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
For detailed information on creating and managing SSH keys, see GitHub’s SSH Key Guide.
remote_path permissionsMake sure the remote_user has write access to remote_path.
See: https://github.com/Burnett01/rsync-deployments/issues/81#issuecomment-3308152891
If your remote server has firewall restrictions:
By default, rsync copies dot files and folder if present at path:. To exclude them, you can use the --exclude switch:
switches: -avzr --delete --exclude='.git/'
Other common exclusions:
switches: -avzr --delete --exclude='.git/' --exclude='node_modules/' --exclude='.env'
More advanced examples:
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:
sudo apt-get update && sudo apt-get install rsync
CentOS/RHEL/Rocky/AlmaLinux:
sudo yum install rsync
# OR on newer versions:
sudo dnf install rsync
Alpine Linux:
sudo apk add rsync
Check here:
Check here:
Check here:
Check here:
Check here:
Check here:
Check here:
Version 4.0 & 4.1 use the drinternet/rsync:1.0.1 base-image.
Check here: https://github.com/Burnett01/rsync-deployments/tree/3.0
Version 3.0 uses the alpine:latest base-image directly.
Consider upgrading to 4.0 that uses a docker-image drinternet/rsync:1.0.1 that is
based on alpine:latestand heavily optimized for rsync.
Check here: https://github.com/Burnett01/rsync-deployments/tree/2.0
Version 2.0 uses a larger base-image (ubuntu:latest).
Consider upgrading to 3.0 for even faster deployments.
Check here: https://github.com/Burnett01/rsync-deployments/tree/1.0
Please note that version 1.0 has reached end of life state.
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