GitLab Pages is a feature that allows you to automate the process of building a static website and publishing it on a server, directly from a repository in GitLab. This is accomplished through a tool called GitLab CI/CD. When the procecss is completed, the website can be accessed through a domain offered by GitLab; optionally, you can add a custom domain and enable the HTTPS protocol.
I have just switched to GitLab Pages to host my blog, which is built with the
blogdown package. In this post, I am going to share with you the details of how it is done.
Update: Automated Let’s Encrypt certificates for Gitlab Pages is now available. Some HTTPS settings introduced in this post may no longer be necessary. I’ll update this post later.
Before proceeding, you should know how to: create a git repository to track the source files of your website; create a corresponding project in GitLab and push commits to it. Instructions on how to accomplish these steps are out of the scope of this post. I refer readers in need to some useful documentations (e.g., this and this).
Setting up GitLab CI/CD
To set up GitLab CI/CD, we need a yaml file called
.gitlab-ci.yml, which should be placed in the root directory of the project that holds your website’s source files. This file specifies the commands to be executed in a Docker container on GitLab to build your website. Here is what is inside the
.gitlab-ci.yml file that I use to build my blog:
image: rocker/tidyverse:3.5.2 before_script: - apt-get update && apt-get -y install pandoc pandoc-citeproc - R -e "install.packages('blogdown')" - R -e "blogdown::install_hugo(version = '0.44')" pages: script: - R -e "blogdown::build_site()" artifacts: paths: - public only: - master
Now, let me explain this file in more details.
The first line of this file specifies a Docker image for the container to use. Here the image is
rocker/tidyverse:latest, which is built on debian and includes the latest version of
tidyverse packages1. There are other images (see here) like
rocker/r-base that only includes base packages of R; however, using
rocker/tidyverse has an advantage of accelerating the build process. This is because it eliminates the need to compile many packages required by the
Then, under the
before_script section, I tell the container to install the packages which will be used to generate the website, including
Finally, the build process will be completed by a
pages. In this section, the command
R -e "blogdown::build_site()" is executed and by default the generated website files will be stored in a directory named
artifacts subsection indicates where to find the files, which will be uploaded to the GitLab Pages server. Additionally, in the
only subsection, I tell the container only to build the website in the
The official documentation of GitLab offers more details on how to tweak the
After the above configuration, when I push commits to GitLab, my website will be automatically built. If the build is successful, then I can access my blog via
https://<username>.gitlab.io/ if it is a user page; or
https://<username>.gitlab.io/<projectname>/ if it is a project page (what is the difference?).
Note that by default, a static site generator (e.g.,
Hugo) expects to find your website under a domain (e.g.,
https://<username>.gitlab.io/), not in a subdirectory of that domain (e.g.,
https://<username>.gitlab.io/<projectname>). Therefore, whenever you want to publish a project page, you’ll first have to configure the baseurl to reflect this pattern. To do this for
Hugo (which is the static site generator that powers
blogdown), you can set the parameter
baseurl in the
config.toml file to
That is it. If you don’t need a custom domain for your website, then the above configuration is all you need to get the site published on GitLab Pages server. However, if you do want to use a custom domain for your website, then please continue reading.
Adding a custom domain and enabling HTTPS protocol
Note that the following content requires some knowledge on domain name, DNS web service and the HTTPS protocol. If you are confused, you may find this documentation to be useful.
Cloudflare is a network platform that provides free DNS service and SSL/TLS Certificates. The following instructions on how to add a custom domain to a GitLab Pages and enable HTTPS are based on cloudflare.
First, login to cloudflare, go to the control panel of your domain, and:
- Navigate to the DNS tab and create a new
CNAMErecord pointing a custom domain (e.g.,
blog.zenggyu.com) to the GitLab Pages domain (e.g.,
zenggyu.gitlab.io) (Fig. 1).
- Navigate to the Crypto tab; then, in the Origin Certificates section, click the Create Certificate button and generate an RSA private key and a CSR (Fig. 2); copy the generated certificate and private key for use in GitLab.
- In the same section, make sure that SSL mode is Full (strict), and that Always Use HTTPS is On (Fig. 3-4).
Then, login to GitLab, and:
- Go to Settings > Pages from your project’s dashboard and click the New Domain button (Fig. 5); add the custom domain, the certificate2 and private key and click Create New Domain.
- Check the verification status of the custom domain and copy the verification code for use in the following step.
Go back to cloudflare, and:
- Navigate to the DNS tab and create a new
TXTrecord for the custom domain, with the verification code (Fig. 1).
Finally, go back to GitLab, and:
- Verify the ownership of the custom domain.
- Make sure that Force domains with SSL certificates to use HTTPS is checked (Fig. 5).
Note that DNS propagation needs some time to take effect. So don’t worry if you can’t access your website via your custom domain instantaneously. Just wait for some time and check it again.
- Hugo has not reached a very stable release yet. Therefore, it is recommended to install a specific version of Hugo (e.g.,
R -e "blogdown::install_hugo(version = '0.44')") to build a website in order to avoid breaking changes.
- When using GitLab CI/CD to build the website, you need to make sure all the content generated by code can be reproduced on the server; otherwise, the build process won’t succeed. To reduce complexity in maintenance, keep executable code in
.Rmdfiles as few as possible.
- Remember to configure the settings so that requests always uses the HTTPS protocol to avoid redirect loop.
- To publish a plain website without a static site generator (e.g.,
blogdown), just move the content to a directory named
public/and specify the path to the
.gitlab-ci.yml. Here is an example:
pages: stage: deploy script: - mkdir .public - cp -r * .public - mv .public public artifacts: paths: - public only: - master