I setup a GitHub Actions workflow which connects to my Linux production machine via SSH using RSA keypair (the setting looks a bit like this tutorial, except I'm trying to create a dedicated Linux user for that, looks to me like it would be the good practice here).
On my Linux machine, I did:
github
with its RSA keypairgithub
user part of the group www-data
www-data
group can read, write and execute)On the GitHub repo side I set up the secrets SSH_PRIVATE_KEY
, SSH_HOST
and SSH_USER
(which is github
).
The GitHub Actions workflow file (the interesting steps of the workflow) look like this:
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
name: id_rsa
known_hosts: ${{ secrets.SSH_HOST }}
- name: Adding known hosts
run: ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
- name: Copy repository to server with rsync
run: rsync -avz ./ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/home/www/my_project/ --usermap=github:www-data
When I rsync the project folder with the github
user and its keypair from my local machine project folder to /home/www/my_project/
on my production server just for a test, everything works fine.
However, when I push on the repo and the GitHub Actions workflow is executed, the rsync steps fails on many files with the following errors on many files of my project:
rsync: [generator] failed to set times on "/home/www/my_project/app/templates/en": Operation not permitted (1)
Why?
After a few tries comparing the permissions of the overwritten files of the server before and after rsync, I found out that the files copied from the repo by GitHub Actions didn't have the group write permission anymore, so it couldn't be written over anymore.
So we just need to set up the owner, group, files permissions and directory permissions for the copied files when copying, so that they keep the exact same rights that they had before rsync. We set directory (D
) and files (F
) permissions for group www-data
to rwx
so that the same users from the www-data
group can overwrite later. All in all the rsync step becomes:
- name: Copy repository to server with rsync
run: rsync -avz --chown=github:www-data --chmod=Dg=rwx,Fg=rwx ./ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/home/www/my_project/
Hope that can be of some help to someone else!
EDIT 2023/03/01:
We might also need to ignore the .git
directory to avoid overwriting it, since it would still exist on GitHub's machine even though if it's gitignored. So rsync step becomes:
- name: Copy repository to server with rsync
run: rsync -avz --exclude '.git' --chown=github:www-data --chmod=Dg=rwx,Fg=rwx ./ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/home/www/my_project/