How we created a static website with Hugo and hosted it on GitLab Pages with our custom domain secured with a SSL/TLS certificate, for free.
With Hugo + GitLab Pages + Let’s Encrypt you get:
- Static website generator.
- Auto-deploy on checkin.
- Free hosting.
- Custom domain AND secured with SSL/TLS encryption.
- Free Let’s Encrypt certificate.
Previously we had [setup our website on GitHub] (/post/hugo-website-on-githubpages/) but with one major drawback: Github Pages doesn’t currently support SSL/TLS certificates with a custom domain. With GitLab Pages, you can use a custom domain AND add your own certificate.
With GitLab Pages your URL options are:
- Encrypted sub domain of GitLab Pages, for example:
https://mygitname.gitlab.io/mywebsite
. - Unencrypted custom domain, for example:
http://mycustomdomain
. - Encrypted custom domain, for example:
https://mycustomdomain
.
We use Let’s Encrypt to generate a 90 day TLS certificate for free. We mostly followed [autonomic.guru/using-letsencrypt-on-gitlabs] (https://autonomic.guru/using-letsencrypt-on-gitlabs/) with a few modifications.
We are running on Linux, your commands might differ. In the following sustitute ‘mywebsite’ with your project name.
Step 1: Add mywebsite project in GitLab
Step 2: Install Hugo, set up your project & push
You might want to look at Hugo - getting-started. Here is how we installed Hugo:
$ sudo apt install snapd
$ snap install hugo
$ export PATH=$PATH:/snap/hugo/current/bin
Download the starter project from [gitlab.com/pages/hugo] (https://gitlab.com/pages/hugo) and rename as mywebsite. This project comes complete with the GitLab deployment script. Then:
$ cd mywebsite
$ git init
$ git config --global user.name "Joe Blogs"
$ git config --global user.email "Joe.Blogs@gmail.com"
# Note: do not add a theme as a git submodule! Just download the theme files and $ git add .
$ git remote add origin https://gitlab.com/JoeB/mywebsite.git
$ git add .
$ git commit -m "Initial commit"
$ git push -u origin master
Wait for a minute then check your website is deployed at your GitLab Page,
for example: https://JoeB.gitlab.io/mywebsite/
.
The nice thing about GitLab’s deployment script is you only check in the source, not the generated html. No public folder or special deployment branch is required. On push, GitLab’s deployment script runs Hugo on the server to generate and deploy the content for you.
Ensure that you are running the same version of Hugo locally and in the deployment
script. For example if you get a 404 page-not-found
when you check your
deployed website, take a look in GitLab / jobs: even if it might have suceeded,
check that the Hugo build logging exactly matches what you see when running
$ hugo server -D
locally, for example:
$ hugo
Started building sites ...
Built site for language en:
0 draft content
0 future content
0 expired content
36 regular pages created
100 other pages created
0 non-page files copied
56 paginator pages created
0 archives created
42 tags created
2 categories created
total in 494 ms
We fixed the 404 page-not-found
error by updating the deployment script
hugo version to match our local version, for example:
// .gitlab-ci.yml
...
variables:
HUGO_VERSION: '0.25.1'
HUGO_SHA: 'fbf8ca850aaaaad331f5b40bbbe8e797115dab296a8486a53c0561f253ca7b00'
...
Add some content to your project, commit and push to GitLab.
Step 3: Update your DNS server and GitLab project settings
Log into your domain’s admin control panel and add a DNS A record pointing GitLab’s IP address. For projects on GitLab.com, the IP is 52.167.214.135
Also add a CNAME record pointing ‘www’ to the same domain ( or IP address )
DNS settings:
Type | Host | Target | TTL |
---|---|---|---|
A | mywebsite.org | 52.167.214.135 | |
CNAME | www | mywebsite.org |
In gitlab.com under the projects' settings/pages link click the big green button to add a domain. For now just add the mywebsite.org and leave the ssl certificate fields blank.
Update your hugo configuration:
# .config.toml
...
baseURL = "http://mywebsite.org/"
...
Git Commit and push
Step 4: Generate SSL/TLS Certificate & upload to GitLab
We are using Let’s Encrypt’s ‘certbot’ to generate the certificate for free. Or you could buy a certificate.
-
Install and prepare certbot:
Install certbot:
$ sudo apt-get update $ sudo apt-get install software-properties-common $ sudo add-apt-repository ppa:certbot/certbot $ sudo apt-get update $ sudo apt-get install certbot
Create a cli.ini file with contents similar to the following:
# .cli.ini text = True domains = mywebsite.org email = joe.blogs@gmail.com renew-by-default agree-tos rsa-key-size = 4096 logs-dir = /tmp/certbot/logs/ work-dir = /tmp/certbot/work/
Update .gitlab-ci.yml:
# .gitlab-ci.yml ... pages: script: hugo mkdir -p public/.well-known/acme-challenge/ cp -R acme-challenge public/.well-known/ ...
-
Run certbot:
$ certbot certonly -a manual -c cli.ini
Part way through running certbot you will need to commit and push the challenge url file as required by certbot to prove your ownership of the domain, for example:
$ cd acme-challenge $ echo s3PmrAqvcx_Zf_7jX7pklYOT9nM9oUKhV1ij2UZR9w4.xN-zdWKk8ATOGjLsHrWTEAOAfvP_TVx4lCT87YNwgyI > s3PmrAqvcx_Zf_7jX7pklYOT9nM9oUKhV1ij2UZR9w4
Git commit and push
Test that the challenge url works, for example: http://mywebsite.org/.well-known/acme-challenge/s3PmrAqvcx_Zf_7jX7pklYOT9nM9oUKhV1ij2UZR9w4
Continue running certbot, noting the location of the certificates when it completes:
Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/mywebsite.org/fullchain.pem. Your cert will expire on 2017-11-04. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew"
-
Add the certificate to GitLab
Update your hugo configuration:
# config.toml ... baseURL = "https://mywebsite.org/" ...
Git commit and push
Go back to gitlab.com under the projects' settings/pages link. Delete the domain you added earlier. Click the big green button to add a domain. Add ‘mywebsite.org’ and paste in the
fullchain.pem
andprivkey.pem
contents into the certificate fields.Add another domain for ‘www.mywebsite.org’ and add the same certificate details.
-
Enforce SSL
Update your hugo configuration:
# config.toml ... [params] enforceSSL = true ...
Add this to a layout or common partial:
// layouts/partials/nav.html ... {{ if .Site.Params.EnforceSSL }} <script type="text/javascript"> if (window.location.protocol != "https:") window.location.protocol = "https"; </script> {{ end }} ...
Git commit and push
Your custom domain should now be secured at https://mywebsite.org/
and
https://www.mywebsite.org/
Finally, make a note in your diary to renew the certificate 3 months later, by following: https://autonomic.guru/gitlab-autorenew-letsencrypt/
From now on you can add further content to your project, commit and push to GitLab, and see your website updated accordingly.
November 2017 update: Certificate Renewal!
Unfortunately with using the manual verification step, it was not that simple to renew and we had to re run some of the steps above. The challenge page was different so we had to commit and push that again during the certbot execution. Here in summary are the steps we took to renew (for more details see above):
- Set enforceSSL = false, commit & push.
- ( you may or may not need to repeat the cerbot install steps ).
- Run
$ ./certbot-auto certonly -a manual -c cli.ini
- Pause and add the acme-challenge file, commit and push, wait for GitLab to deploy.
- Continue to finish.
- Delete mywebsite.org & www.mywebsite.org in GitLab Pages, add them again with certificates.
- set enforceSSL = true, commit & push.
You are done for another 3 months. Note that it may take a little while for the new certificate to show up in the browser.