Blogging with Hugo and GitLab (4): HTTPS with Let's Encrypt
Tags: webdev, tutorial, https, letsencrypt
Published: 2019-05-10 03:59:27

---
title: Blogging with Hugo and GitLab (4): HTTPS with Let's Encrypt
published: true
tags: ["webdev", "tutorial", "https", "letsencrypt"]
canonical_url: https://loadbalancing.xyz/post/blogging-with-hugo-and-gitlab-https-with-letsencrypt/
---

The default HTTPS support by GitLab will be unavailable with custom domains. Fortunately, there is the solution to add HTTPS back for free.

## Why HTTPS?

HTTPS (HTTP over TLS or HTTP over SSL) is more secure than HTTP. Today many browsers will mark a website as insecure if it's visited via HTTP instead of HTTPS. I think that's important for personal bloggers as you don't want people to think they are exposed to security risk by visiting your blog website.

## Why Let's Encrypt?

In order to equip your website with HTTPS, you need to acquire a SSL/TLS certificate from a certificate authority (CA) that is trusted by browsers. The good thing is that free certificates are available. For example:

* <a href="http://www.cacert.org" target="_blank">CAcert</a> is more in the Linux world while certificates issued by it are still not trusted by most browsers.
* <a href="https://www.cloudflare.com" target="_blank">Cloudflare</a> (btw, they own an interesting domain *https:<span></span>//one.one.one.one*) offers free certificates, but <a href="https://nickjanetakis.com/blog/lets-encrypt-vs-cloudflare-for-https" target="_blank"> it might not be really free</a> if you go with full features.
* <a href="https://letsencrypt.org" target="_blank">Let's Encrypt</a> provides full-feature free certificates which are valid for 90 days and renewable.

Overall, Let's Encrypt is the best.

## Environment

* macOS Sierra 10.12.6.

## Obtain a Let's Encrypt certificate

1. Install Homebrew in macOS.
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2. Install CertBot.
brew install certbot

3. Request a certificate. Though optional, it's recommended to provide an email to receive notifications (e.g., certificate expiration). Here we request the certificate for both root domain and sub-domain.
sudo certbot certonly -a manual -d loadbalancing.xyz -d www.loadbalancing.xyz --email example@email.com
It's then followed by several steps:
  * Type `A` to agree with their terms of service.
  * Type either `Y` or `N` depending on if you want to receive news from Let's Encrypt.
  * Type `Y` to agree with logging your IP.  

4. Then pause here (don't press Enter). Follow the instruction to create a file containing the data specified and commit it to your repository.
cd your_repository/static
mkdir -p .well-known/acme-challenge/
vi the_specified_file_name
The file need to be available at:
*http://<span/>loadbalancing.xyz/.well-known/acme-challenge/the_specified_file_name*

5. Now press Enter. It will generate and save the certificate and key to local. Record their content which will be used in the next step.
sudo cat /etc/letsencrypt/live/loadbalancing.xyz/fullchain.pem
sudo cat /etc/letsencrypt/live/loadbalancing.xyz/privkey.pem 


## Add the certificate to GitLab

1. Add the certificate and key to your website.  
"Setting" > "Pages".  
For each domain (root and sub-domain), click "Details" > "Edit".

2. Copy and paste the certificate into the first field `Certificate (PEM)`.

3. Copy and paste the private key into the second field `Key (PEM)`.

4. Let traffics be automatically directed to HTTPS.  
Select "Force HTTPS (requires valid certificates)".  
Click "Save".  

After a few minutes, you will be able to visit your website via HTTPS. You may also want to update the base URL in `config.toml`.

## Renewal

As mentioned earlier, Let's Encrypt certificates expire every 90 days and you will have to renew them periodically. To renew certificates:
```
sudo certbot renew
```
Alright, after two months I realized the above renewal just doesn't work. The following error is given:

*"Attempting to renew cert (loadbalancing.xyz) from /etc/letsencrypt/renewal/loadbalancing.xyz.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.*

*The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.'). Skipping."*

Looks like the only way of renewal is to manually redo the whole procedure, which I don't think is gonna be sustainable. Fortunately, someone figured out a way of auto renewal with GitLab and I will update my experience of trying that in the next post.