Create a blog with Hugo
- 7 minutes read - 1346 wordsUnsurprisingly, the first post of this blog explains how it is built and hosted.
Blog engine choice
This blog is static, meaning it does not need a content management system such as Wordpress, Drupal or others.
On the contrary, all pages are generated upstream in HTML/CSS/JS, and are served statically. The tool that does all that (and more) is Hugo.
Hugo takes in input Markdown files, and generates the corresponding HTML. There are many extensions that can add more functionality.
Set up
We first have to download and install Hugo by following the official instructions.
Then type the following command to create a new site:
hugo new site blog
In order to add a theme, we will use a git submodule. For that, we have to initialize the git workspace and add the theme with these commands:
cd blog
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
Here, we use the default theme, but there are many others.
Once the theme has been added, we must reference it in the configuration file config.toml
.
Note that Hugo also support YAML for this file, and that’s what we’ll use here:
config.yaml
baseURL: http://example.org/
languageCode: fr-fr
title: Blog de Stéphane
theme: ananke
Theme configuration
Each theme has its own configuration and customization.
For exemple, for this theme, we can add the following parameters:
params:
show_reading_time: true
twitter: https://twitter.com/stephane_deraco
github: https://github.com/stephane-deraco
We can customize a lot more things like visual aspect (background color, images, …) and even use a custom CSS.
Create a new blog entry
To create a new blog post, simply type the following command:
hugo new posts/2021-04-11-creation-blog-avec-hugo.md
A new file will be created in the directory content/posts
.
By default, this post is in draft mode (draft: true
in the file header).
That means that this specific post will not been generated by Hugo when we will build the site.
However, it is still possible to view this post locally using this command:
hugo server -D
hugo server
tells Hugo to build pages (locally), to launch a web server and to check modifications made on files in order to rebuild pages on the fly. The brower is then refreshed automatically thanks to a live reload feature.- the
-D
flag is here to tell Hugo to also build draft pages.
Hosting
The site will only contains static files, so any hosting will do the job.
Here, I use the Github Pages functionnality to host this site.
Build the site
The first step is to build the site with this command:
HUGO_ENV=production hugo
All files that will form the final site are generated in the public
directory.
Note:
hugo env
should be sufficient but the theme documentation indicates that we need to set theHUGO_ENV
variable toproduction
.
Note: Do not forget to remove the
draft
flag of pages that you want to publish!
Note: In the
config.yaml
file, the value ofbaseURL
will be used for links, in particular from the landing page to post pages. By default the value isexample.org
. You need to modifiy this value with where the site will be hosted. However, in order to test the site locally, we can use the commandhugo -b http://localhost:8000/
, go in thepublic
directory, and launch a web server withpython3 -m http.server
.
Publish the site
The site will be hosted with Github Pages.
We have to create a new Github repository with the name username.github.io
, username being the Github username.
This repository will contain the site content, that is the HTML/CSS/JS that Hugo will generate.
Hugo documentation explains the procedure.
Note: We can find several articles using a different solution based on git submodules, one for the source, and another for the generated files. With Github Actions, as explained on Hugo web site, we can make it simpler.
We also have to create the repository that will contain source code of web site. Eventually, two repositories are required:
- https://github.com/stephane-deraco/blog.git for blog source code
- https://github.com/stephane-deraco/stephane-deraco.github.io.git for web site static files generated by Hugo
Github Actions will generate and publish the site. As described in the documentation, we need to create this file:
.github/workflows/gh-pages.yml
name: github pages
on:
push:
branches:
- main # Set a branch to deploy
pull_request:
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
# extended: true
- name: Build
run: hugo --minify
env:
HUGO_ENV: production
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/main'
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
external_repository: stephane-deraco/stephane-deraco.github.io
publish_branch: main
publish_dir: ./public
The only difference with the Hugo documentation is that we tell Github Actions to push the generated files on another repository (external_repository
), as explained on the site of Github Action peaceiris/actions-gh-pages
.
As Github needs to interact with another repository, we must create a deploy SSH key:
ssh-keygen -t rsa -b 4096 -C "$(git config user.email)" -f gh-pages -N ""
Then navigate to the Github repository that will contain the generated files (stephane-deraco.github.io
) > Settings > Deploy keys, click on the Add deploy key button and copy the public key (the content of the gh-pages.pub
file generated by the previous command), and check the Allow write access checkbox.
Now navigate to the Github repository that contains the source code in Markdown (blog
) > Secrets and add the private key (the content of the gh-pages
file) by clicking on the New repository secret button.
Use the ACTIONS_DEPLOY_KEY
as the name (it must match with what we put in the Github Action).
We can now do a commit & push on the blog
repository:
git add .
git commit -m "First blog post"
git remote add origin https://github.com/stephane-deraco/blog.git
git branch -M main
git push -u origin main
The Github Action will be triggered, and soon the repository for the generated files will be updated with what Hugo has built.
Use a personal domain
So far, the web site is already available on https://stephane-deraco.github.io/!
We can use a personal domain (like https://blog.deraco.fr), everything is explained in the Hugo documentation.
Hugo configuration
We need to create the static/CNAME
file with the personal domain in content:
static/CNAME
blog.deraco.fr
Github configuration
On the Github side, the documentation states that we have to configure the domain in the Settings > Pages page of the repository containing the static resources (here, stephane-deraco.github.io
).
Then fill in the domain (blog.deraco.fr
) in Custom domain and save.
Registar configuration
We have to prove to Github that we actually own the personal domain in question, and configure the DNS.
A way to do that is to add a CNAME
record in the console of our registar.
I use Gandi, and this is done by connecting to the console, then in the Domains page click on Add DNS record. Two parameters are important:
- Name :
blog.deraco.fr
- Hostname :
stephane.deraco.github.io.
(Do not forget the final dot!)
Now, all we have to do is to wait for the DNS propagation.
HTTPS
As the web site is hosted on Github, the certificate sent by the site will not match the personal domain we have just configured, and the brower will display on error like this one:
Websites guarantee their identity through certificates. Firefox does not consider this site reliable as it uses a certificate that is not valid for blog.deraco.fr. The certificate is valid only for the following names: www.github.com, *.github.com, github.com, *.github.io, github.io, *.githubusercontent.com, githubusercontent.com
Error code: SSL_ERROR_BAD_CERT_DOMAIN
If you regularly refresh the Github page of the site (Settings > Pages), you will see the personal domain verification status, and also that a certificate is being generated. Just be patient!
config.yaml
modification
As the site is on another URL now, we have to modify the baseURL
parameter of the config.yaml
file in order to use the personal domain.
Conclusion
We now have a blog site with its own domain, hosted by Github Pages (that has also generated a certificate). Its content is static, is generated by Github Action when commits on the source code of the site are pushed, and is generated by Hugo based on Markdown files.