Peter Chng

My Hugo Setup

I recently switched to using Hugo for my personal blog, and here’s my setup for publishing to my website:

The directory created by hugo new site ... is a git repository:

.
├── .git
├── .gitmodules
├── public      # Default Hugo public output directory
├── archetypes
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes

Within this top-level git repo are two submodules. (Hence the .gitmodules file)

In .gitmodules:

[submodule "themes/blank"]
	path = themes/blank
	url = <path to git repo for the theme>
[submodule "public"]
  path = public
	url = <path to the git repo for the public output>

The first submodule (themes/blank) is for the theme I’m using, which was based upon this blank/starter theme. Using a submodule for a theme was based upon the instructions in the [quick start guide], which were meant to make fetching new themes easy, and to keep them independent of any specific Hugo site. However, there’s no reason why you couldn’t just make the theme part of the top-level git repo.

The second submodule (public) points at the default Hugo output directory when you run hugo. This is its own git repository. I could have made this live outside the top-level git repository, but because this is the default location hugo outputs to, I wanted to make continuing operation simple at the expense of a little more setup at first. (Since I’m sure to forget details like overriding defaults later on)

When I want to update this site, the process is like this:

  1. hugo
  2. Change to the ./public directory: git commit -am '<some message>' and then git push origin master.
  3. On the server: The web root itself is a git repository cloned from where I pushed ./public to. So to update, I just have to run: git pull origin master

One problem with this approach is that it creates a .git directory in the web root, exposing it. To prevent leaking this, I’ve added this to .htaccess: (Based on this SO answer)

# Block access to .git directory
RedirectMatch 404 /\.git

This also blocks access to any .gitignore file present.

Overall, I think this process is straightforward enough for me to not forget over time.