Serving personal page with HTTPS on GitLab Pages

As my current hosting plan on OVH ends next month, I’ve looked for a way to move my Gluwer website to another location. As it gets very popular now to serve simple static personal websites like this one on GitHub using custom domain. But if you want to do HTTPS and custom domain on GitHub, you have to use solutions like CloudFlare to get it working. Because I use GitLab for personal non-public projects, I’ve checked their GitLab Pages solution.

I was pleased to see that they support both custom domains and HTTPS (of course you can use CloudFlare there too as CDN). They also have prepared many ready to use examples of websites for all popular static website generators. What is interesting that you just push to GitLab the source code and generation happens on their CI service. This is very convenient, because you can edit/add new articles using GitLab and their Markdown editor easily without using your own computer at all.

Generator setup

Because I already have static website generator in place (it uses Gulp tasks), the only thing I had to do was adding .gitlab-ci.yml file to the repository. I have used example version for nuxt that after small changes looks like this:

image: node:7

before_script:
  - npm install

cache:
  paths:
    - node_modules/

pages:
  script:
    - npm run generate
    - mv build public
  artifacts:
    paths:
      - public
  only:
    - master

Because only the public folder is exported to GitLab Pages, I had to rename my build folder. This is more or less everything you have to do for Node based generators. After commit and push GitLab CI will start, generate the static version using Docker image and make it available on https://.gitlab.io/ (it may be you have to wait 10-15 minutes after push to build and upload to proper location).

What is especially important that the main repository for this website is still private, only generated website is made available to the outside world! For private projects GitLab offers 2000 minutes of CI for free. It is more than suffice for private website or blog.

If the site is available, we now have to add a custom domain to it.

Custom domain and HTTPS

Because I previously used OVH as service provider, they give HTTPS certificates for free automatically using Let’s Encrypt initiative. I can use it to get the certificate for free too. The only downside is that certs are valid only for 90 days as Let’s Encrypt is made to work on servers with automatic renew. On GitLab it is not possible (if you do not want to renew, you may usie CloudFlare as they provide SSL).

The other problem is that I use Windows and official certbot client is for Linux/Mac OS. This is also not a big issue, you can use online tools or clients that work on Windows. I have chosen the Google client named (ACME)[https://github.com/google/acme] written in Go language.

Getting the cert

Download the binary version and put it in any folder. Go to that folder and use command below:

acme reg -gen mailto:<your email>

If the command returns an error (it was in my case on Windows 10), create .config/acme folder in user’s folder (eg. C:/Users/rafa/.config/acme). The folder should be created automatically, but is not.

After agreeing to the Terms, tool will create account for you. ACME tool can create a new private key for domain, but we cannot really use it. The tool creates EV KEY, but GitLab requires RSA KEY, so we have to create the key manually.

Use Putty to generate key using these instructions or just use ssh keygen, if you have it installed on Windows as I do:

ssh-keygen -t rsa -b 2048

Copy the private key to acme folder mentioned ealier as <domain.name>.key. The tool will use it automatically.

Now, log in to your DNS provider and run below command:

acme cert -dns <domain.name>

You will get domain entry to add to DNS starting with _acme-challenge. In most DNS editing tools you may have to only enter _acme-challenge without domain. Add it as TXT type with value shown. Save it on DNS provider website and wait a minute or two to allow propagation. Hit Enter and you receive the URL for the cert, but don’t use it. The cert was also saved in the acme folder in PEM format.

Set up everything on GitLab

Now go to GitLab’s repository page and then to Settings/Pages. Click New Domain. In the form enter the domain name, a copy-paste the content of certificate (.crt) and the private key .key. Click Create new domain. If all goes well, you should see the domain in the Domains part of the Pages page.

The last thing to do is to change DNS to use GitLab. If it is naked domain like mine, use A type with IP address 52.167.214.135. For subdomains you can use CNAME type which is more safe (you don’t have to do anything if GitLab changes main IP).

Redirect to HTTPS

Because GitLab does not offer any rewriting rules (like for example Firebase Hosting), you have to use dirty trick in JS to check if HTTPS is in use. Of course for static sites it is not really a requirement, but if you want to use service workers etc. user must use secure connection.

I’ve ended up with below fragment, which is not nice, but works for most users:

var host = 'gluwer.com';
  if ('www.'+ host === window.location.host) {
    window.location = window.location.toString().replace(/^https?:\/\/www\./, "https://");
  } else if (host === window.location.host && window.location.protocol !== 'https:') {
    window.location = window.location.toString().replace(/^http:/, "https:");
  }

Yuo can see that I’ve also added support for www.gluwer.com (without HTTPS certificate) if someone just writes this in the browser to redirect to HTTPS without www.

End notes

Well, everything works properly, but I see several downsides of this solution if you have a higher traffic static website:

  • no compression
  • no expiry headers
  • no rewrites

I think the GitLab Pages are a bit nicer solution than GitHub Pages (for free for privates projects, support of HTTPS with custom domains), but it is better to use Firebase Hosting (free version is pretty generous) or use CDN like CloudFlare for more control, allow all there elements above etc. For less hassle CloudFlare (if free version should suffice) may be a better option, as for Firebase you lose GitLab CI capabilities.

Comments