Automate Hugo deployment with GitLab CI/CD
To make it easier to write new posts I wanted to automate the deployment of updates to my Hugo website.
The goal is whenever a new commit is added to the master branch, the site is rebuilt using Hugo and deployed to my server using rsync.
Quick note: If your site is entirely static, Netlify (I’m in no way affiliated with them) will do this for you along with lots of extra features like generating previews for pull requests. I use it to generate the sceditor.com website where it works well.
You will need to set up a user and/or key for rsync to connect to your server with.
The Hugo website has instructions for setting up an SSH key if you don’t already have one set up.
The private key needs to be added as a variable to the repository so that GitLab CI can access it. From the repository go to:
Settings -> CI/CD -> Variables
Click the add variable and then add the key giving it the name
Every time SSH connects, it checks the key from the server against ones it has seen before and warns if it hasn’t seen the key before.
Each time GitLab CI/CD is run it creates a new VM instance, so any previously
seen host keys are not saved. It’s possible to just always accept new keys but
that could open up MITM attacks. To avoid that, it’s best to add the keys from
the server to the
To set up the
known_hosts file, add a new variable called
with the contents of the following command:
ssh-keyscan -H your.hostname.com
Finally, add a file called
.gitlab-ci.yml with the following contents:
# Use GitLabs built-in Hugo image # Might be wise to change from latest to a specific version of Hugo # to ensure nothing breaks when new versions of Hugo are released. # # For example: # image: registry.gitlab.com/pages/hugo:0.81.0 image: registry.gitlab.com/pages/hugo:latest variables: GIT_SUBMODULE_STRATEGY: recursive deploy: # Set sane timeout, for me it takes ~25 seconds to run so # 5 minutes is reasonable timeout: 5 minutes script: # Need SSH client for rsync to use - apk add rsync openssh-client # Add the key and known hosts - mkdir -p ~/.ssh - echo "$RSYNC_KNOWN_HOSTS" >> ~/.ssh/known_hosts - echo "$RSYNC_PRIVATE_KEY" > ~/.ssh/key - chmod -R 700 ~/.ssh - eval "$(ssh-agent -s)" - ssh-add ~/.ssh/key # Build the website - hugo # Sync the built site # IMPORTANT: Make sure to modify the rsync command below # for your sever. Remove --dry-run when ready to deploy - rsync -crtvz --dry-run --delete ./public/ user@host:/path/to/public_html/ only: # Only run on main branch variables: - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Change the rsync command parameters to match your server.
I’ve added the
--dry-run option set so should be safe to run but it would be
wise to backup your server before committing it to the repository.
Check the output and once happy, remove the
That’s it, now whenever a new commit is made to the master branch it will be automatically built and deployed.
GitLab offers free users 400 minutes per month to use which should be plenty for most people (takes around ~25 seconds to run for me). If you’re going to be doing a lot of deploys per day, or if you have a lot of websites, GitHub offers 2000 minutes per month for free users which might be a better choice.