1. Introduction
  2. Preparation
    1. Installing Hugo
    2. Configuring Server
  3. Creating Hugo Blog
  4. Resources


As I was thinking about starting a blog, I came across a few blogging platform contenders that I had trouble deciding between. Among those I eventually narrowed it down to two: Ghost and Hugo. I detailed installing Ghost and went over a few of its benefits in my last post. Today, we’ll be exploring Hugo’s pros/cons and setting up a simple Hugo blog.

Hugo is a static site generator that likes to boast of it’s speed. These are the two things that eventually won me over. It basically takes in your posts and spits out a website comprised of HTML, CSS, and javascript. There is no backend code needed. This is beneficial because it cuts down on the number of things that can go wrong. This speeds up the browsing experience for the end user because each page has it’s own HTML and doesn’t need to be queried from a database before being served. Another thing I like is that instead of posts being stored in a database, I have a structured folder with all my posts in it. However, the strongest point of Hugo is probably that since it generates static files, it can be hosted in a lot of places for free, such as GitHub pages.

While Hugo has some nice benefits, it also has some downsides. Personally, I feel like the biggest barrier to entry is that you need to know your way around command line tools and code for the best experience. Adding to that, the documentation can be a bit sparse at times. Since that is the case, I would recommend Ghost to most people.


There are quite a few ways to go about hosting a Hugo blog. You could set up a server that you upload the generated HTML/CSS/JS files to, or you could install everything on the server and generate your content directly on the server. I’ll go through setting up both of these scenarios.

The first thing you’ll need to do is have a server and domain name to server the blog from. This could be any hosting service that lets you upload your own files, but I like to use cloud VPS services like Linode or DigitalOcean (Full disclosure, these are referral links, and at the time of writing if you use the Digital Ocean link, you get $100 of credit to use for the first 60 days). I went over setting up a server with Digital Ocean in my last post.

Installing Hugo

After you’ve figured out your server situation, you will need to install the Hugo command line application on either your server or personal computer depending on which workflow you want to use. Regardless of which workflow you want to use, installing Hugo is the same. Hugo supports most platforms due to the nature of Go. I’ll be covering Linux and MacOS, but the installation process should be pretty similar across all platforms. The official Hugo site has a nice writeup of all the ways to install Hugo.

MacOS installation

Installing on MacOS is pretty simple with the help of homebrew. You just install homebrew first:

/bin/bash -c "$(curl -fsSL"

Then you install Hugo:

brew install hugo

That’s it!

Linux installation

While, theoretically, you could also use homebrew on linux, I like to use snap to install Hugo on linux.

First you’ll need to install snap. If you’re on any recent release of Ubuntu, snap should come preinstalled on the system. If you aren’t, you can follow the instructions for your distribution here.

Then you’ll need to install Hugo with snap:

snap install hugo --channel=extended

That’s it!

Server configuration

Server configuration is needed if you’re running your own server either locally or via a VPS service. If you’re using a web hosting server that takes file uploads, you can skip this part. We’re going to be using NGINX for serving our webpages and configuring TLS/SSL to work with it.

Assuming you’ve already set up the basics for your server, let’s get the SSL/TLS certificates needed and set up NGINX next. To set up SSL/TLS we can use letsencrypt to generate certificates:

sudo apt install certbot
sudo certbot certonly --standalone

After running these commands, you’ll be guided through obtaining certificates via a text prompt. When you reach the step of putting in your domain name, you’ll need to put in both and Putting in them both at once didn’t work for me, so you might want to put in first and then run the second command again to get the certificate for After successfully getting your certificates, let’s install and set up NGINX:

sudo apt install nginx

The default location that nginx is installed into is /etc/nginx. Since we’re setting up TLS/SSL we’ll need to change a few things:

cd /etc/nginx/sites-enabled/
sudo vim default

This will open up the default configuration file. We’ll want to edit this to redirect all traffic to the TLS/SSL connection. Let’s delete everything before we start adding things by typing d100d, this deletes 100 lines starting from where the cursor is. Afterwards, hit i to start editing and paste this in:

server {
        listen          80;
        return 301$request_uri;

This will redirect all traffic from port 80 to port 443. Port 80 is used by the http protocol and port 443 is used by https. If you want your default domain to be, you can add the www before in the code above. Next, we’ll need to configure redirecting to or vice-versa depending on what you want your default domain to be. I’ll be redirecting to, so if you want it to be the other way around, just swap the two. Write this code in after the previous server block:

server {
        listen 443 ssl          http2;
        server_name   ;
        ssl_certificate         /etc/letsencrypt/live/;
        ssl_certificate_key     /etc/letsencrypt/live/;
        ssl_trusted_certificate /etc/letsencrypt/live/;
        ssl_protocols           TLSv1.2 TLSv1.3;
        return                  301$request_uri;

Finally, we can set up the server block that actually deals with serving the blog to the end user. Input this after the previous block:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    charset utf-8;
    expires $expires;
    root /var/www/html; # directory you of your blog

    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;
    ssl_trusted_certificate /etc/letsencrypt/live/;
    ssl_protocols TLSv1.2 TLSv1.3;

    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Referrer-Policy no-referrer;
    add_header X-Frame-Options "SAMEORIGIN";

    index index.html;

Then type :wq to exit VIM. You can reconfigure the file path where you want to install your blog in by changing /var/www/html which is the default directory that NGINX is configured with. Now that we have the configuration set up, we can test our configuration:

sudo nginx -t

This should give you a success message. If not, a common error is the certificates not being set up properly. If that’s the case, rerun the command to get your certificates and make sure the file path to your certificates is correct in the server blocks. Once the test says successful, we can enable the configuration be restarting NGINX:

sudo systemctl restart nginx

Now the server is all hooked up and we’re ready to create our blog!

Creating Hugo Blog

Depending on which set up you chose in the beginning, you will want to do the following steps on the computer you installed Hugo on.

Navigate to where you want your blog to be and create a new blog:

hugo new site blogname

After that we can add a theme from the theme selection:

cd blogname
git init
git submodule add themeURL themes/theme_name

If you wanted to install the ananke theme you would change the third command to be this:

git submodule add themes/ananke

Now we need to tell Hugo that we want to use the theme we just installed by editing config.toml:

vim config.toml

Then you want to hit i to start editing and tell Hugo to use the theme:

theme = "theme_name"

Type :wq to save and exit the text editor. Now that we have our Hugo configuration set up, we can put some content onto the blog:

hugo new posts/

This will create a markdown file in posts/. You can use all the markdown you want, and Hugo will convert it to HTML when the blog is compiled. Let’s add some content to the file:

cd posts/

Hit i to start editing and paste in some basic post information and content:

title: "My First Post"
date: 2020-06-05T00:00:00+00:00
draft: true

This is some content. Blah Blah Blah.

After you’re done with your post, type :wq to save and exit. The configuration from above will give Hugo the basic content and information about the post to help generate the blog.

Now that we have a post we can build our blog and publish it. Let’s start by generating the blog files:

cd rootPathOfHugoBlog

This generates all the non draft posts in your posts/ folder. To change a draft from a draft to a published article, just remove the draft: true from your post text. Alternatively you can run this:

hugo -D

Hugo will put all the site files into a new folder called public/. If you’re using Hugo that is installed on your server, you can either point NGINX to this directory or you can copy the files to the directory you want your website to be served from. If you’re running Hugo on your own computer, you’ll want to upload the contents of this folder to your server via ftp/scp.

This completes the basic set up of Hugo and you should be able to see your blog when you visit your domain name!


  1. Installing Hugo (
  2. Hugo quick start (