Setting up https on a hugo site on Gitlab pages with your custom domain requires some manual work, but if i can do it, so can you.
The process includes the following components
- A Hugo site on your computer
- Gitlab pages with above site
- Let’s Encrypt certbot
- In my case, a Mac with homebrew (you can do this with Linux as well)
- A public DNS server or service
- Your favourite terminal
- No much fear
I should have taken some screenshots, but i’ll try to explain things well enough so that you can do without. Please ask using the comments (if they work) or Twitter, or the MacAdmins Slack, if i left something out.
I’ll assume that you, like me, already are running your Hugo site on Gitlab Pages. You may or may not have set up a custom domain name for your pages. I did, because i’m curious, and i like to take things in iterative steps.
The whole thing is a bit of a circular chase, where every chicken needs to eggsist before its egg, which in practice means that you’ll have to do a few things in parallel. Have faith. Think of parallel universes. It’s not that complicated.
These instructions are probably valid for other platforms than Hugo. The only really Hugo-specific bit is that i’ll post a validation file into Hugo’s
static directory which means it will be presented to the users as-is.
The first parallel bit is to create a custom domin for your site on Gitlab pages and on your DNS server/service. To make things silly, you’ll first need to set your Gitlab pages domain without a certificate. Later, you’ll delete this domain. Yeah, i know, it’s a bit convoluted, but as i said, some things are a bit chicken-and-egg here.
From the Gitlab user interface, within your Hugo pages project, go
Settings > Pages > + New Domain. Type the domain name of your site in the Domain box. Leave the Certificate and Key boxes blank. Click the inviting green
Create New Domain button.
Gitlab will warn you that
This domain is not verified so let’s do that now.
Head over to your friendly DNS server/service and create two records:
CNAME record (sometimes called an “alias” record) for your site
TXT record to prove to Gitlab that it’s you
Copy and paste the relevant bits from the page into your DNS config. Exactly how you do this depends on your DNS provider, which is a terribly lazy way of saying that i can’t really help you here. I use ZoneEdit, which allows me to host one domain for free, and Amazon Route 53, which costs a penny a day per domain name. Since i’m scared, i haven’t moved my free entry on ZoneEdit to Amazon.
Be careful with the
TXT record. On the “left” side, paste in all of
_gitlab-pages-verification-code.your.site.tld and on the “right” side,
Also, note the dot at the end of the CNAME. It’s there for a reason. When you’re done with the DNS stuff, click the green
Verify ownership button. If all goes well, your domain name is now verified. To verify, you may want to
curl http://your.site.tld and celebrate.
DNS records may take a little while to propagate around the Internet, so don’t panic. You may want to
dig your.site.tld from your command line.
The crypto bits
Now, let’s install Let’s Encrypt Certbot. On a Mac with homebrew, that’s as easy as
brew install certbot
See the Certbot site for info on other platforms. In the
Software dropdown, choose
none of the above and whatever your OS is in the
Now change into the directory of your computer which contains your hugo site – let’s call this
$yoursite, – and create a few magic directories
% cd $yoursite
% cd static
% mkdir -p .well-known/acme-challenge
% cd .well-known/acme-challenge
OK. Now let’s create all the certificate stuff, ie the private key and the keychain. I’ll probably write something about certificates one day, because they can be a bit confusing. You’ll need to
sudo this, as the process involves touching some files which are out of bounds for the regular user. If you’re like me, you’ll first need to
su into your admin user, and if you’re like old-me, you just use
sudo as if nothing’s happened.
your.site.tld with your custom domain.
Open up a new terminal tab for the Certbot stuff, since you’ll need to do two things in parallel again. I’ll call this new tab the Certbot tab and the previous one the User tab.
you % su admin-you
admin-you % sudo certbot certonly --manual -d your.site.tld
And this is where it starts to get tricky.
The verification file
Certbot will now ask you to
Create a file containing just this data:, which is a long and seemingly random string of characters into a file containing those same characters and more seemingly random characters. As hugo will serve files from the
static hierarchy as-is, this is the place to create a file containing just this data.
Keep certbot running in the Certbot tab and switch to your User tab. There,
% cd $yoursite/.well-known/acme-challenge # unless you're there already
% echo ThoseRandomCharactersCertbotGenerated.AndThenSome > ThoseRandomCharactersCertbotGenerated
Push these to Gitlab:
% git add .
% git commit -am "Add Certbot validation file"
% git push
Then wait some more. Stand up, walk around the chair. Breathe. Sit down.
Still in your User tab,
curl http://your.site.tld/.well-known/acme-challenge/ThoseRandomCharactersCertbotGenerated. Repeat until you get a response containing only
ThoseRandomCharactersCertbotGenerated.AndThenSome. The first few times, you’ll probably get the 404 error page. That’s because Gitlab is still processing your site.
If you get errors, there are two reasons i can think of. First test whether the file was actually pushed into production. Substituting your username for
curl https://yourusername.gitlab.io/.well-known/acme-challenge/ThoseRandomCharactersCertbotGenerated (or http). If you got the validation file, good. If not,
The second reason is probably DNS, because “everything’s a DNS problem”. Your DNS records may still point to your old site (you got a 404) or your site was not found (DNS records haven’t propagated yet). Go back to the bit about DNS.
Switch to your Certbot tab, which is just waiting to verify the file you sent above. Press Enter to let it, and fill yourself with joy as you read the
Congratulations! text. The
certbot has now created two files which you’ll need soon.
Switch to Secure
We’re nearly there, and trust me, it’s taken a lot longer time to write this than what it took me to get my site running in glorious https.
You’re now going to remove your previously created custom domain on Gitlab. Sick, yeh? This is because (currently?), you can’t add a certificate to an already existing custom domain on Gitlab. Maybe that’ll change one day and that means i’ll have to change this write-up, but until then, that’s life.
From your Gitlab pages'
Settings > Pages, see your previously created domain name and press the slightly intimidating (it’s designed that way)
Remove button. There’ll be a dialogue box. Click
OK, because you are sure. Now press the green
+ New Domain button again.
In the Domain field, enter
your.domain.tld again. Paste the contents of the cerbot-generated certificate file (in my case,
/etc/letsencrypt/live/robin.lauren.fi/fullchain.pem) into the Certificate field and the key file (me,
/etc/letsencrypt/live/robin.lauren.fi/fullchain.pem) into the Key text field. As a note to all you aspiring devops-style sysadmins, you usually want to keep your private key very private and be very, very careful with where you put it. A healthy dose of paranoia is probably good for you.
Press the green
Create New Domain button and rejoice!
OK, nearly there. You’ll still need to edit your Hugo site’s main configuration file,
$yoursite/config.toml. Change the
baseurl to reflect
baseurl = "https://your.domain.tld/"
Commit all your changes. Push to Gitlab. Give it a while to generate. And surf to your newly https’isised site! Yay!
In three months, your certificate will expire. Before that, you should
sudo certbot renew, or even better, set up an automation to do that.