SSL certificate

Nowadays ssl certificate is a must because it prevents:

  • faking your website
  • reading information that transferred in between users and your website
  • improves rank of the website in the search systems

Even moreover in a few years browsers will forbid not secured connection, so it is better to learn how to set up ssl certificate for your website.

SSL certificate is just a file which links information about organization with a cryptographic key. When it is installed on the webservers, it enables https protocol which means that secure connection between your users and website can be established.

Ways to get ssl certificate

According to this gitlab’s tutorial they suggested two ways to get ssl certificate for free:

These organizations offer ssl certification according to initiative to make internet a safer place.

CloudFlare is a webtool which makes it much easier to start with ssl certification. But for some reason I did not manage to make this certificate work, might be because I did not wait for proper period. So in this article we will see how to use LetsEncrypt scripts.

If you want to use CloudFlare you can find this tutorial really useful.

Step 1. Ways to create ssl certificate

In order to create ssl certificate using letsencrypt scripts we have several ways:

  • clone letsencrypt repo and inside it run command
./letsencrypt-auto certonly -a manual -d domain_name 
  • download and install certbot on your machine using this link.

  • In my case I saw this comment on the certbot website: certbot_docker_comment

    So we can also use docker image.

Eventually I renewed certbot with

brew install certbot

Step 2. SSL certificate creation

When you chose your way it is time to create certificate. Using certbot installed in the machine we need to run next command:

sudo certbot certonly -a manual -d domain_name -d other_domain_name

It will ask several questions:

  • your email address
  • are you agree or disagree with the Terms of Service
  • do you want to share your email with the Electronic Frontier Foundation
  • are you OK with your IP being logged?

After this question you will see something like:

Create a file containing just this data:


And make it available on your web server at this URL:


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

NOTE if you want to create certificate for several domains and you pointed them in the console like:

 -d your_domain_name -d other_domain_name

You will see output like above for each domain name.

Step 3. Adding file to our website

Previous console output means that we have to go to our website project and create html files in our _pages folder. This file can have any name, it does not matter, but what does matter is it’s content

layout: null
permalink: /.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f


When it is created start jekyll with command:

bundle exec jekyll serve

Check _site/.well-known/acme-challenge/ folder it has to contain file with name kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f.html Check the content of this file - the only thing that has to be there is kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f.na2lKMSd1soU73Ls0o2NSLna2lKMSd1soU73Ls0o2NSL with no html tags or something, just plain text.

NOTE if you are creating certificate for several domains you will need to add such file for each domain name.

Step 4. Modifying .gitlab-ci.yml file

Then go to .gitlab-ci.yml file and add this line beneath building the website line:

-cp ./public/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f.html ./public/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f

So it should something like this:

  stage: deploy
    - bundle install
    - bundle exec jekyll build -d public
    - cp ./public/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f.html ./public/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f
  when: manual
    - release
    - public

Why do we need to copy that file? Take a look at this line more carefully:

cp ./public/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f.html ./public/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f

It copies html file and paste file without extension. We need this because certbot script will look for exactly this url available: http://your_domain_name/.well-known/acme-challenge/kSdf45wfHW3hs4Sg-j34HsdDek2_aS21gn1cNSl4f and there is no html extension. That’s why we have to do this hack (maybe you have better solution for this).

Step 5. Finishing certificate creation

We almost did it. The last thing is to finish certification process in the console. So let’s go back to our console and type Enter.

After a while you will see something like this:

Waiting for verification...
Cleaning up challenges

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2019-02-05. 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"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:
   Donating to EFF:          

Which means that our certificate was created.

Step 6. Pasting our certificate in gitlab

Now all we have to do is to use our certificate in gitlab. So we need to go to our gitlab repository settings then to Pages. On this page we need to:

  • enable HTTPS only checkbox
  • click Edit button to edit our http domain
  • paste your certificate. To read it just use something like:
sudo cat /etc/letsencrypt/live/your_domain_name/fullchain.pem
  • paste your private key. To read it just use something like:
sudo cat /etc/letsencrypt/live/another_your_domain_name/privkey.pem
  • save changes

After a while you will see that your site is reachable using url with https.

How to renew certificate

Usually certificate work for three months after which we have to renew them again. In my case I did it with such steps:

Step 1. Check what kind of certificates do we have

To do this we can use next cli command:

  certbot certificates

Then We should see something like:

Found the following certs:
  Certificate Name:
    Expiry Date: 2019-04-16 10:24:50+00:00 (INVALID: EXPIRED)
    Certificate Path: /etc/letsencrypt/live/
    Private Key Path: /etc/letsencrypt/live/

So today is 2019-04-21 and the tool says that certificate is expired and it is right time to renew it again. Well not exactly right time because ideally it has to be done beforehand and automatically. For now I don’t want to create script that works with repo (it has to commit pages with proper challenge values). We will discuss the ways to automate this process in the future anyway.

Step 2. Initiate certificates renewal

Using console we need to do:

sudo certbot certonly -a manual -d domain-name -d other-domain-name

Console will reply with something like:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for
http-01 challenge for

This is exactly the same as we have in the step 2 of the creation flow and from this point we can follow certificate creation flow.


The first problem I faced is that certbot in docker did not work for me: I was able to work through the script steps, but certificate was not created in my local machine despite I opened volumes. So my advice if you use docker do not run in with -rm flag - which means that later on you can ssh to your container and check letsencrypt folder.

The second and the biggest problem was related to html extension of the file. So be aware that certbot script is searching for file with url without html extension. That’s why I had to copy file to have another one without this extension.

The third problem is having html tags inside created file. Again certbot was searching for plain text not for html element. For the first time I created md files which jekyll converted to html and added <p></p> tags around my key. Then the solution is to create html file instead of md` file.