How to deploy a static website generated with Hugo to a webserver? In this post, I will share the steps that I followed in order to be able to deploy this very blog using Github Actions to the shared hosting that I have.
Use case: I have a Hugo website, code hosted on GitHub, how do I deploy it to a location of my choice?
The assumed starting point is:
Let’s start!
The first thing is to generate a first pair of private/public ssh keys. In a terminal (local, distant, your taste):
ssh-keygen -t rsa -b 4096
Or better, if your server supports it, adjusting filenames accordingly:
ssh-keygen -a 100 -t ed25519
You will be prompted for a location - specify a location that you consider secure and a name. Do not type in any password. I will here assume that it is saved under the name id_rsa
for the private key with the corresponding id_rsa.pub
that should be automatically generated.
Go to next to, adapting to your situation:
https://github.com/[GITHUB_USERNAME]/[GITHUB_REPOSITORY]/settings/secrets/actions
On this page, copy the private key - id_rsa
- into a secret variable called DEPLOY_KEY
. In plain english, this means, open the private key file in a text editor of you choice, copy everything in it:
-----BEGIN RSA PRIVATE KEY-----
MANYLINESWITHALOTOFNUMBERSANDCHARACTERS
-----END RSA PRIVATE KEY-----
and paste it in the Value
text field. You should not have any blank lines above, below or in the middle of the text, depending on how the key was generated you might have blank lines at the end or in between the keys and the header/footer. Save the key.
Now, connect to THE_SERVER through an ssh connexion with something like ssh THE_SERVER_USERNAME@THE_SERVER
and type your password. Copy the public key content to the ~/.ssh/authorized_keys
file on THE_SERVER. If it is not empty, just add a new line or create the file if it did not exist. Just in case, make sure the file rights are Ok with chmod 600 ~/.ssh/authorized_keys
.
Next, still in the ssh session, you will need to generate a new pair of keys with the following:
ssh-keygen -t rsa -b 4096
Or better, if your server supports it, adjusting filenames accordingly:
ssh-keygen -a 100 -t ed25519
Use a different name, here I will assume that the two files are in/called: ~/.ssh/id_rsa_gh
/ ~/.ssh/id_rsa_gh.pub
. Do not type in any password.
Make sure that the proper rights are applied:
chmod 400 ~/.ssh/id_rsa_gh
chmod 600 ~/.ssh/id_rsa_gh.pub
This is important as Github expect certain permissions on these files.
We still have a little something to do, create a new file, I use vim, with: vim ~/.ssh/config
. Type in the following:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_gh
IdentitiesOnly yes
And again:
chmod 600 ~/.ssh/config
Now copy the public key present in the ~/.ssh/id_rsa_gh.pub
file present on THE_SERVER and copy/paste into a deploy key here:
https://github.com/[GITHUB_USERNAME]/[GITHUB_REPOSITORY]/settings/keys
Finally, go back to the terminal where you have an open connection to THE_SERVER and type in: ssh -T git@github.com
. It should ask for your confirmation, type yes and you can close the ssh session if you see the following:
Hi [GITHUB_USERNAME]/[GITHUB_REPOSITORY]! You\ve successfully authenticated, but GitHub does not provide shell access.
This handles the configuration of the secured connection.
The big advantage of static generators is that you can focus on the content, writing in markdown and let the pipeline automatically handle the deployment.
The general logic of the pipeline is that it will use GitHub Actions to get the source code (theme included), build the static pages and transfer them using rsync
. In the following configuration, we will build and deploy every time a commit or a pull request is pushed on the master branch. For this, you will need to add a pipeline file in your repository under .github/worflows/main.yml
and configure some variables:
name: hugo rsync
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.74.3'
- name: Build
run: hugo --minify
- name: Deployment rsync
uses: burnett01/rsync-deployments@4.1
with:
switches: -avzr --delete
path: public/
remote_path: WWW/PATH/ON/THE/DISTANT/SERVER
remote_host: ${{ secrets.DEPLOY_HOSTNAME }}
remote_port: ${{ secrets.DEPLOY_PORT }}
remote_user: ${{ secrets.DEPLOY_USERNAME }}
remote_key: ${{ secrets.DEPLOY_KEY}}
All that is left to do, is to add a few keys in the repository’s secrets page to assign the DEPLOY_HOSTNAME
, DEPLOY_PORT
(often 22) and DEPLOY_USERNAME
variables that matches THE_SERVER configuration.
That’s all! I never used Github Actions before this and I lost a couple of half-hours on some pain points without finding this use case described fully somewhere. This is corrected now. Please, contact me if something is missing or suggestions.
This is a very basic pipeline but it is a working starting point.
[UPDATE]
Suggestion by Jan Reilink, for better security:
Please use ed25519 keys instead of rsa (https://t.co/LdcwNhBClZ random link explaining)
— Jan Reilink (@HertogJanR) November 21, 2020
So if your server supports it, replace the key generation with the more recent ed25519 encryption!
ssh-keygen -a 100 -t ed25519
Copyright 2023 - Mikael Koutero. All rights reserved.