github twitter linkedin 500px email
Deploy static sites with Github Actions
Jun 17, 2020

I used Hugo to generate a static site and copy it to my web server using rsync over SSH. Recently, I started using Github Actions, which is a free continuous integration (CI) platform from Github.

On my web server, I created a user with restricted permissions so that Github is not granted access to my full server. Setting up Github Actions is as simple as creating the YAML file .github/workflows/deploy.yml inside the repository. The documentation is a good starting point. My workflow file contains instructions to run a job on every push event on this repository.

name: Autodeploy
on: [push]

    runs-on: ubuntu-latest
    - name: Git checkout
      uses: actions/checkout@v2
        token: ${{ secrets.MY_GITHUB_PUBLIC_PAT }}
        submodules: recursive

    - name: rsync git repository to vultr
      uses: AEnterprise/rsync-deploy@v1.0
        DEPLOY_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        SERVER_PORT: ${{ secrets.SSH_PORT }}
        SERVER_IP: ${{ secrets.HOST }}
        USERNAME: ${{ secrets.USERNAME }}
        ARGS: "-e -c -r --delete"
        FOLDER: "./"

    - name: run Hugo
      uses: appleboy/ssh-action@master
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.SSH_PRIVATE_KEY }}
        port: ${{ secrets.SSH_PORT }}
        script: source deploy_saik_at

The job contains three steps using existing GitHub Actions:

  1. checkout the repository and submodules on the “mysterious” server, where the GitHub Actions are running.
  2. rsync the content to my web server.
  3. SSH to my web server and run the deploy_saik_at script.

These actions use several vulnerable personal information, which I trusted Github to keep secure by keeping them as Secrets in the Settings of the repository. The HOST, USERNAME and SSH_PORT are respectively the IP address of my web server, username of the restricted account, and the port that listens to incoming SSH requests. The SSH_PRIVATE_KEY is the RSA private key generated on my web server. The corresponding public key was added to .ssh/authorized_keys on the web server.

ssh-keygen -t rsa -b 4028 -C "[email protected]" -f ~/.ssh/id_rsa
cat ~/.ssh/ >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

I had to use my Github registered email for generating the key. The MY_GITHUB_PUBLIC_PAT is my personal access token for Github and is required for recursive submodule checkout. It can be generated here. The deploy_saik_at is a bash script on the web server which generates the static site and, if successful, makes it public. Here is a trimmed down version:

TEMP=$( mktemp -d )
${HUGO} --destination="${TEMP}" --logFile="${LOGFILE}"
if [ $? -eq 0 ]; then
    rsync -aq --delete "${TEMP}/" "${DEPLOY_DIR}"


  1. If restricted user cannot be created in the webserver, then restrict SSH to rsync.
  2. Some other relevant blogs: [1] [2] [3].

Back to posts

comments powered by Disqus