How to Create a Blog with Hugo and Gitlab Pages

4 minute read Modified:

Tutorial and documentation of how I built this site.

The day before starting this site, I had just started a blog using Github Pages and Jekyll and I wanted to compare the experience of building a site with Gitlab Pages and Hugo.

Steps

These steps are from the Hugo Quick Start guide and from the Hugo Gitlab Hosting Guide.

  1. Create a new Gitlab repository called ${username}.gitlab.io.

  2. Install Hugo. On Mac, you can run brew install hugo.

  3. Create a new site with hugo.

    hugo new site ${username}.gitlab.io
    cd ${username}.gitlab.io
    
  4. Initialize the repository.

    git init
    git remote add origin git@gitlab.com:${username}/${username}.gitlab.io.git
    echo "/public" >> .gitignore
    git add *
    git commit -am "Create new hugo site"
    git push -u origin master
    
  5. Customize the theme.

    git submodule add https://github.com/halogenica/beautifulhugo.git themes/beautifulhugo
    echo 'theme = "beautifulhugo"' >> config.toml
    git commit -am "Add beautifulhugo theme"
    
  6. Change the title in config.toml to what you want.

    baseURL = "https://${username}.gitlab.io/"
    languageCode = "en-us"
    title = "My Crazy Site"
    theme = "beautifulhugo"
    
  7. Add your first post. Make sure you do this step before the next one (setting up Gitlab CI) or else your build will fail with the error: Error: Error building site: No source directory found, expecting to find it at /builds/${username}/${username}.gitlab.io/content

    hugo new posts/my-first-post.md
    git add content/posts/my-first-post.md
    git add config.toml
    git commit -m "Add first post"
    git push
    
  8. Create a .gitlab-ci.yml file for Gitlab Continuous Integration which will build your site. (Delete the backslashes and replace them with tabs. There is currently a bug in Hugo’s Markdown renderer, blackfriday.)

    image: monachus/hugo
    before_script:
    \- git submodule init
    \- git submodule update --force
    pages:
    script:
    \- hugo
    artifacts:
    paths:
    \- public
    only:
    \- master
    
  9. Commit and push

    git add .gitlab-ci.yml
    git commit -m "Add Gitlab CI yaml file"
    git push
    
  10. If you wait a couple minutes for the Gitlab CI to build your side and then go to http://${username}.gitlab.io/, you should see your site with just your title and theme.

  11. Go ahead and write your first post at the content/posts/my-first-post.md file created earlier. However, currently the site has no link to your posts! Let’s try to fix that now. Open anew terminal window (tab or tmux pane) and run hugo server -D. Now if you navigate to localhost:1313, you will be able to see a local version of your website.

  12. Copy the themes/beautifulhugo/layouts/_default/list.html file to layouts/_default/list.html so you can see your posts.

    cp themes/beautifulhugo/layouts/_default/list.html layouts/_default/list.html
    

    If hugo server -D is still running, you should be able to navigate to localhost:1313 and see your first post!

  13. Change draft: true to draft: false and then commit your changes and push. Then you should see your changes at ${username}.gitlab.io!

Optional Steps to Set Up Domain Name

This is all from the Gitlab Documentation.

  1. Go to your DNS provider (I use DNSimple. Full disclosure: If you use this link, I get a referral bonus.) and add an A record pointing to Gitlab’s IP address 52.167.214.135. I also added a CNAME record www pointing to ${username}.gitlab.io

  2. (Optional) Set up SSL Encryption. (Replace jkleong.com with your domain name and the token with whatever token LetsEncrypt provides.)

    git clone https://github.com/letsencrypt/letsencrypt
    cd letsencrypt
    ./letsencrypt-auto certonly -a manual -d jkleong.com -d www.jkleong.com
    

    Follow the steps that LetsEncrypt gives you before hitting enter:

    Create a file containing just this data:
    
    1CXxEDFBR5Hb48piXZAOw3kEa1WgcK1O5kAFjAM6ruM.6R8edBjjSRsMbsdq9wgWT98dhMtOtkrsFQjOL6QmMeM
    
    And make it available on your web server at this URL:
    
    http://jkleong.com/.well-known/acme-challenge/1CXxEDFBR5Hb48piXZAOw3kEa1WgcK1O5kAFjAM6ruM
    
    mkdir -p static/.well-known/acme-challenge
    echo '1CXxEDFBR5Hb48piXZAOw3kEa1WgcK1O5kAFjAM6ruM.6R8edBjjSRsMbsdq9wgWT98dhMtOtkrsFQjOL6QmMeM' > static/.well-known/acme-challenge/1CXxEDFBR5Hb48piXZAOw3kEa1WgcK1O5kAFjAM6ruM
    git add static/.well-known/acme-challenge/1CXxEDFBR5Hb48piXZAOw3kEa1WgcK1O5kAFjAM6ruM
    git commit -m "Add TLS certificate(s)"
    git push
    

    You might have to do this twice if you entered in two domains. Wait until curl http://jkleong.com/.well-known/acme-challenge/1CXxEDFBR5Hb48piXZAOw3kEa1WgcK1O5kAFjAM6ruM returns the string that you expect.

  3. From your project’s dashboard, go to Settings > Pages > New Domain and add your domain. (e.g. jkleong.com and www.jkleong.com). If you did step 15, also add everything in /etc/letsencrypt/live/jkleong.com/fullchain.pem to Certificate (PEM) and /etc/letsencrypt/live/jkleong.com/privkey.pem to Key (PEM).

  4. Go to your website (e.g. www.jkleong.com). Hopefully, you should have a functional blog!

Takeaways

This process was definitely more complicated than setting up a site with Jekyll and Github Pages but the SSL encryption makes Gitlab Pages a worthy option.

It took me a while to figure out the Hugo layout because it seems more complex and the documentation and examples may not be as comprehensive.

However, it’s worth it because the site builds so fast that it is basically instantaneously. (I noticed 3-6 ms while writing this post.)

Gitlab has been taking around 30 seconds for Continuous Integration to build the site. I think if I were using Jekyll, it would be slower than Github but with Hugo it may be faster.

Thanks to Tracey Chan for reading and editing my post.