4 minutes
Making a Hugo Static Site, and Auto Deployment
This not only documents the making of this website, but will also help in setting up any Hugo static site with self hosting.
Ok but why these technologies?
Mainly, nginx is used because it’s already setup and ready to go on my VPS. The GitHub actions auto deployment will allow you to have this as a private repo as well. All serving to a public domain over https.
Tech Used
- Nginx (Serving)
- CertBot (SSL)
- Hugo (Static site generation)
- VPS (for self hosting)
Recommended
- A VPS
- A domain
Hugo
Get Hugo installed onto both your dev machine and your server. It is important to note that some distro’s (like Ubuntu/Debian) may have very old versions of Hugo within their repo. In such cases, you can install Hugo manually from the Github.
GitHub Setup + Hugo
If you already have a github repo ready for your website, you can create a hugo site on top of it using:
hugo new site <repo name> --force
--force
is used here because the folder is not empty. For example, it’s already a git repo folder.
Theme
At the time of writing, this website uses the hello-friend-ng theme. This can be installed using:
git clone https://github.com/rhazdon/hugo-theme-hello-friend-ng.git themes/hello-friend-ng
Then you need to let git know about the submodule.
git submodule add https://github.com/rhazdon/hugo-theme-hello-friend-ng.git themes/hello-friend-ng
Within your config.toml
, you can set theme = "hello-friend-ng"
to activate the theme.
My site configs are as follows:
baseurl = "https://foreveranapple.com"
title = "Dave's Learnings"
languageCode = "en-us"
theme = "hello-friend-ng"
paginate = 10
[params]
dateform = "Sep 3, 2022"
dateformShort = "Sep 3"
dateformNum = "2022-09-03"
dateformNumTime = "2022-09-03 15:04"
# Subtitle for home
homeSubtitle = "Don't make my mistakes."
# Set disableReadOtherPosts to true in order to hide the links to other posts.
disableReadOtherPosts = false
# Enable sharing buttons, if you like
enableSharingButtons = true
# Metadata mostly used in document's head
description = "Dave's learnings."
keywords = "homepage, blog, tech"
images = [""]
[taxonomies]
category = "blog"
tag = "tags"
series = "series"
[languages]
[languages.en]
title = "Dave's Learnings"
subtitle = "Don't make my mistakes."
keywords = "blog, tech"
copyright = '<a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener">CC BY-NC 4.0</a>'
readOtherPosts = "Read other posts"
[languages.en.params.logo]
logoText = "Dave's Learnings"
logoHomeLink = "/"
[[menu.main]]
identifier = "blog"
name = "Blog"
url = "/posts"
Finally, you can add a new blog post using:
hugo new posts/my-first-post.md
Make sure you check everything with:
hugo serve -D
Deployment
Now, let’s serve it. First, we setup Nginx to serve static files. We create a file under /etc/nginx/sites-available/
with our site configurations. For example:
sudo touch /etc/nginx/sites-available/blog
Populate it with the following:
server {
server_name example.com www.example.com;
root /home/username/blog/public/; #Absolute path to where your hugo site is
index index.html; # Hugo generates HTML
error_page 404 /404.html;
}
Move this file onto sites-enabled
:
sudo ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/blog
Make sure that your DNS is setup to point to your server. And the website is ready to serve!
SSL/HTTPS
Let’s get SSL setup. The simplest way is to get it up and going is by using certbot. It’s extremely easy to use with nginx and almost fully automated for certificate renewals.
Install certbot (on Debian/Ubuntu):
sudo apt install certbot python3-certbot-nginx
Afterwards, simply run certbot and follow the prompts.
sudo certbot --nginx
Autodeployment with GitHub Actions
Here’s a simple GitHub actions to get deployment on push:
---
name: CI
# Controls when the action will run.
on:
# Triggers the workflow on push to master (including merged PRs)
push:
branches: [main]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or
# in parallel
jobs:
# This workflow contains a single job called "build"
update:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of
# the job
steps:
- name: Updating website.
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd blog
git stash
git pull --force origin main
git submodule update
hugo -s /full/path/to/your/static/page --cacheDir ~/hugocache
Make sure to replace parts as needed! And make sure that the secrets are populated.
That’s it!
Hope this helps, and happy making a Hugo static site!
hugo github automation selfhosting
725 Words
2022-05-09 21:04 (Last updated: 2025-13-03 13:41)
f3417da @ 2025-13-03