Setting Up Hugo on Ubuntu (Step-by-Step)

This guide walks you through setting up a Hugo static site generator on Ubuntu 22.04+, including theme installation, site configuration, and web server deployment using Nginx or Apache

Introduction

In this guide I’ll cover steps for installing Hugo on a server running Ubuntu. This may work on other Debian distros as well, however this has not been tested by me. Before starting this guide, you’ll need:

  1. A server running a Ubuntu 22.04+
  2. A working web host (nginx or apache) running
  3. A FQDN (Fully Qualified Domain Name) to use for the site — either a local A record (for internal hosting) or a public A record (for internet access)

Step 1. Installing Hugo

There’s a couple of ways to go about this, and I’ll detail two common methods

Prepare working space

The purpose of this is to keep your hugo website(s) in a single place, to make it easier to work with in the future. You can create this anywhere, but we’ll just be using the home directory for now.

cd ~
mkdir hugo
cd hugo/

Install using apt

The most basic and simplest way is to use Ubuntu’s built in apt command. Run the following command to install Hugo using apt:

sudo apt update
sudo apt install hugo

And that’s it!

Install directly from github

This is a little more complicated. Depending on your version of Ubuntu, you may get an older version of hugo which can cause compatibility issues with some themes. To do ths, follow the steps below.

First, grab the latest version of hugo from their github. You’ll want to find the one that contains the relevant architecture for your system - arm64 or amd64. Make sure to select the Linux one and get the tar.gz. Right-click this and select copy link. Run the following commands (this will be using the link to the latest version at the time of writing)

wget https://github.com/gohugoio/hugo/releases/download/v0.148.2/hugo_0.148.2_linux-amd64.tar.gz
tar -xzf hugo_*
sudo mv hugo /usr/local/bin/hugo
hash -r

Confirm installation

To confirm hugo is installed and running, run the following command.

hugo version

This should print an output of the version.

Step 2. Create first site

Now that it’s all up and running, make sure you’re in your working directory and run the command below to create your site.

cd ~/hugo
hugo new site mysite

Replace mysite above with the desired name of your site, such as blog. We’ll be using mysite for this.

Step 3. Install theme

Browse for a theme here. Once you find one you like, run the following commands to install it.

cd ~/hugo/mysite
git init
git submodule add https://github.com/user/example-theme themes/example-theme

Replace the url and name above with the url and name of the theme selected. For example, the theme Blowfish by nunocoracao

git submodule add https://github.com/nunocoracao/blowfish themes/blowfish

This will copy the theme down into the themes/ directory - full path should be ~/hugo/mysite/theme/

Step 4. Edit config file

Once that’s installed, time to edit the config file. This can be either hugo.toml, hugo.yaml, config.toml or config.yaml. Use what’s there by default. I’ll provide an example config for both yaml and toml formats. Feel free to edit this as you want. Make sure to update the baseURL to whatever you’ll be using for your website. If this isn’t set property, links and static assets may break when deployed.

Config example - toml

baseURL = "http://blog.example.com/"
languageCode = "en-us"
title = "My Blog"
theme = "name-of-theme"

[params]
  mainSections = ["posts"]
  description = "A Hugo blog"
  enableDarkMode = true
  favicon = "favicon.ico"

[menu]
  [[menu.main]]
    identifier = "about"
    name = "About"
    url = "/about"

Config example - yaml

baseURL: "http://blog.example.com/"
languageCode: "en-us"
title: "My Blog"
theme: "name-of-theme"

params:
  mainSections:
    - "posts"
  description: "A Hugo blog"
  enableDarkMode: true
  favicon: "favicon.ico"

menu:
  main:
    - identifier: "about"
      name: "About"
      url: "/about"

Step 5. First post!

Now it’s time to make your first post. We do this by running the following command:

hugo new posts/my-first-post.md
nano content/posts/my-first-post.md

Here’s an example of a first post:

+++                                                 
title = 'My first post'
date = 2025-07-27
draft = false
description = "The first post of many!"
tags = ["blog", "intro"]
categories = ["blog posts"]
+++

This is my first post. Hello, world!

Step 6. Build website

To build the site, simply issue the below commands

cd ~/hugo/mysite
hugo

It’s important that this is run in the base directory of your site - from this guide we’ve been using ~/hugo/mysite, but if you’ve changed that make sure you’re in the base directory of your site.

Step 7. Serve with web hosting software

Now that the site’s been built, all the files have been placed in the public directory - ~/hugo/mysite/public/*

We’ll have to move this to where your website can access them and servce the pages. Create a directory and copy the files as below.

sudo mkdir -p /var/www/mysite
sudo cp -r ~/hugo/mysite/public/* /var/www/mysite

Now depending on what you’re using to host the website, you will need to set up a config file. I’ll provide some basic examples for nginx and apache.

Nginx config

For Nginx, you’ll need to create the config file in /etc/nginx/sites-available. Run the commands below to do this:

sudo nano /etc/nginx/sites-available/blog.example.com

Then use the example config file below:

server {
    listen 80;
    server_name blog.example.com;

    root /var/www/mysite;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Create a symbolic link to enable to site.

sudo ln -s /etc/nginx/sites-available/blog.example.com /etc/nginx/sites-enabled/blog.example.com

Test to make sure the config is all good

sudo nginx -t

Then restart Nginx

sudo systemctl restart nginx

Apache config

First, let’s make sure the permissions are all good

sudo chown -R www-data:www-data /var/www/mysite
sudo chmod -R 755 /var/www/mysite

Now we need to create the config file for Apache.

sudo nano /etc/apache2/sites-available/mysite.conf

Use the example config below


<VirtualHost *:80>
    ServerName blog.example.com
    DocumentRoot /var/www/mysite

    <Directory /var/www/mysite>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/mysite_error.log
    CustomLog ${APACHE_LOG_DIR}/mysite_access.log combined
</VirtualHost>

Now run these commands to enable the site and restart apache

sudo a2ensite mysite.conf
sudo systemctl reload apache2

Step 8. Site now live

With the configuration files created and services restarted, your website should now be live! Visit its URL to view the main page and your first blog post.

All that’s left now is to create more posts and pages! Make sure to check out your theme’s demo or example sites if they have them to see everything that’s available.

Optional - Simple deploy script

The only issue I found with Hugo was it was a bit of an annoyance to build the site, copy the public directory, then restart the webhost. So, I put together a couple of quick scripts to do this. I created this script in the base directory of the site, ~/hugo/mysite/deploy.sh. Run the command below to create the script file.

nano ~/hugo/mysite/deploy.sh

nginx script

#!/bin/bash

# Exit immediately on error
set -e

# Define paths
HUGO_SITE_DIR="$HOME/hugo/mysite"       # change as needed
WEB_ROOT="/var/www/mysite"

echo ">> Building Hugo site..."
cd "$HUGO_SITE_DIR"
hugo

echo ">> Copying files to $WEB_ROOT..."
sudo cp -r public/* "$WEB_ROOT"

echo ">> Restarting Nginx..."
sudo systemctl restart nginx

echo ">> Done. Site should be live."

Save this script and then make it executable.

sudo chmod +x ~/hugo/mysite/deploy.sh

apache script

#!/bin/bash

# Exit immediately on error
set -e

# Define paths
HUGO_SITE_DIR="$HOME/hugo/mysite"       # change as needed
WEB_ROOT="/var/www/mysite"

echo ">> Building Hugo site..."
cd "$HUGO_SITE_DIR"
hugo

echo ">> Copying files to $WEB_ROOT..."
sudo cp -r public/* "$WEB_ROOT"

echo ">> Restarting Apache..."
sudo systemctl restart apache2

echo ">> Done. Site should be live."

Save this script and then make it executable.

sudo chmod +x ~/hugo/mysite/deploy.sh

Now whenever you finish creating a post or making a change you can just run ./deploy.sh from your website’s working space directory. This also helps prevent any possible issues from running hugo in the wrong directory.

Endnote

That’s it for this guide. I hope it was helpful to some! Before switching to Hugo, I was manually editing .html files for every post—this change has been a massive time-saver!

Built with Hugo
Theme Stack designed by Jimmy