Hugo with CircleCI
Hugo
I’ve finally gotten around to redoing my personal site. I had high hopes of making my own web platform using indieweb standards, but have finally faced reality and decided that with all my other hobbies that was just too ambitious. So instead I’ve chosen a static site generator so that I do not have to worry about databases or many other dependencies.
The new site is running hugo with the casper-two theme.
I will cover a few details of setting up the site with a focus on deploying to a custom server. These details assume that you already have hugo installed locally.
Setup a new site
hugo new site YOURSITENAME
This creates a new hugo site found in the directory YOURSITENAME
.
Initialize new site as a git repository and commit initial hugo build.
cd YOURSITENAME
git init
git add
git commit -m "Initial commit of hugo site"
From here we need to add a theme. There are plenty to choose from see hugo themes and choose a theme of your liking. I chose casper-two as indicated above and added that to my codebase via the following;
git submodule add https://github.com/eueung/hugo-casper-two.git themes/casper-two/
This sets up casper-two as a git submodule which can be updated independently of my local code.
From here I followed the instructions for casper-two
to set appropriate variables and configuration settings in my config.toml
file. Mine looks like the following;
baseurl = "/"
theme = "casper-two"
languageCode = "en-US"
disqusShortname = ""
paginate = 6
#SectionPagesMenu = "main"
[params]
title = "Jeff Graham"
subtitle = "Random Ramblings"
cover = "images/cover.jpg"
description = "Here is a description of your site."
metaDescription = ""
googleAnalytics = ""
customCSS = []
RSSLink = ""
twitterName = "jgraham909"
githubName = "jgraham909"
logo = ""
orgName = ""
orgWebsite = ""
orgDescription = ""
author = "Jeff Graham"
authorAvatar = "images/me.jpg"
authorLocation = ""
authorWebsite = ""
authorDescription = ""
pageNotFoundTitle = "404 - Page not found"
#casper or caspertwo
singleViewStyle = "casper"
[permalinks]
post = "/:slug/"
[[menu.main]]
name = "Home"
url = "/"
weight = 200
For the casper-two theme static files are served from the static
directory. So create that directory and add a favicon.ico and any images you wish to use.
Circle CI (securely)
After that portion I wanted to set this up so that I could push new posts to github and have those automatically deployed to my site on a custom server running nginx. After pushing the repository to github we can now step over to circleCI setup.
.circleci/config.yml
version: 2
jobs:
build:
docker:
- image: felicianotech/docker-hugo:0.33
working_directory: ~/jgraham909.com
steps:
- checkout
- run:
name: "Initialize git submodules"
command: git submodule init
- run:
name: "Update submodles"
command: git submodule update
- run:
name: "Run Hugo"
command: HUGO_ENV=production hugo -v -s ~/jgraham909.com
- run:
name: "Test Website"
command: htmlproofer ~/jgraham909.com/public --allow-hash-href --check-html --empty-alt-ignore --disable-external
- run:
name: "Add HostKeys"
command: echo $HOSTKEY1 >> ~/.ssh/known_hosts && echo $HOSTKEY2 >> ~/.ssh/known_hosts && echo $HOSTKEY3 >> ~/.ssh/known_hosts
- run:
name: "Deploy"
command: rsync -avz -e "ssh -i ~/.ssh/id_rsa" --delete ~/jgraham909.com/public/ jgraham909@jgraham909.com:/var/www/jgraham909/
But there are two things we need to configure first. We don’t want to have to provide a password to deploy and CircleCI does not have our server in the known hosts.
Add a new user and set ssh keys
After logging into your server create a new user account with an appropriately secure password.
adduser USERNAME
Once you have created the new user logout as your privileged user and login as the newly created account with the password you set. At this point we need to do two things: generate ssh keys, and set authorized ssh keys.
We do that via the following commands
ssh-keygen
cp .ssh/id_rsa.pub .ssh/authorized_keys
The first step ssh-keygen
generates new ssh keys for this user do not set a passphrase for this portion so that we can authenticate without needing to supply a password. The second step adds this new public key to the authorized_keys
file which will allow us to login using this ssh key.
This has a corresponding step in circle CI we need to add the newly created .ssh/id_rsa
(note this is the private key) to our Circle CI page’s “ssh permissions” section.
Add our server’s ssh key to circleCI
ssh-keyscan HOSTNAME
will list out your server ssh key signatures for each of these entries I added a corresponding HOSTKEYX
environment variable in Circle CI where X
started with 1 and was incremented for each entry from ssh-keyscan
. Ignore the lines that start with #
.
During deploy we add all of these keys (3 in my case) to our ~/.ssh/known_hosts
file. This will avoid CircleCI from hanging during deploy when encountering a server with a host key not already in its known_hosts
file.
echo $HOSTKEY1 >> ~/.ssh/known_hosts && echo $HOSTKEY2 >> ~/.ssh/known_hosts && echo $HOSTKEY3 >> ~/.ssh/known_hosts
Deploy
Our final step in the CircleCI process is the actual deploy stage.
rsync -avz -e "ssh -i ~/.ssh/id_rsa" --delete ~/jgraham909.com/public/ USERNAME@SERVERNAME:/var/www/jgraham909/
In this process we deploy using rsync via ssh. In our case hugo built the site files in ~jgraham/public
and that is what we deploy to our server to the directory /var/www/jgraham909
.
nginx config
Earlier I mentioned that I have nging running on this server. In addition to creating a directory at /var/www/jgraham909
and chowning that to the user we previously created we need to set nginx to serve those files. In my case the server is running ubuntu so we edit /etc/nginx/sites-enabled/default
and add an entry to map the appropriate incoming domain to the appropriate directory in our case that looks like the following;
server {
listen 80;
server_name jgraham909.com;
root /var/www/jgraham909;
index index.html;
I’m sure I’ve missed some details if you have questions hit me up on twitter.