Stack Link to heading
Hugo Setup Link to heading
Building the blog is fairly simple as outlined in their quick start guide:
First, install hugo:
brew install hugo
Create a new site:
hugo new site blog then
Initialize the git repo:
Add the theme of your choice:
git submodule add https://github.com/luizdepra/hugo-coder.git themes/<theme_name>
And finally, configure the
config.toml file using this template, filling in your personal info and adding your profile picture to
Hugo is then ready to be tested locally with
Open your browser and navigate to
http://localhost:1313/ to see your progress!
The next step is to start working on your blog posts. Create a new post with
hugo new posts/<name_of_blog_post> and write your blog in markdown below the
As you update your content, you can run
hugo server -D to run a self-updating local site.
The final step is to copy the contents of
themes/layouts into your main
Server Setup Link to heading
Now that the site is working locally, it’s time to build a server to host it.
It’s possible to host a static site on AWS S3, and there are many blog posts detailing how, but I chose to use an EC2 server as I already one to host other sites.
- Consistent and safe from human error
- Modular tasks for easy reuse between projects
- Use of variables to easily control/update parameters of the server (i.e. varaibles for app versions, hostname, etc…)
- Identical environments for Production, Staging and Local for testing consistency
- Easy to scale: Can build 1 or 1,000 servers just as easily
- Saves time for more productivity and eliminates repetitive tasks. I can build a server with one command and work on other things as it’s created and/or control many servers at once.
- Documentation is inherent. Human readable code vs undocumented black box
- Not locked into any one provider. Can be easily modified to work anywhere
- No worries about backing up servers as they can be easily recreated
I git cloned my Ansible template which includes my tasks to connect to AWS EC2, create the instance, update and upgrade the OS, setup my config files, install and configure Apache/Passenger web server and restart the OS. After setting up the playbook, I ran it to provision the server. Check the Readme on information about how it works and how to set it up.
After the server is configured, I gave it an Elastic IP then setup a CNAME record under my domain’s hosted zone in AWS Route 53 and pointed it to the EIP.
Deploying Link to heading
With the server up and running, we are now able to deploy the Hugo site.
To create the static site, simply run
hugo from the hugo directory. This will create a your static site in the
Deploying your site is as simple as moving the
public folder to your server and have it set as your webserver’s document root. There are many ways to do this but I chose to use scp, a secure transfer protocol over ssh.
I set my document root to
/var/www/blog/public in my apache config. This directory is owned by the root user. For security best practices, I have setup my ssh keys on a non-root user which has sudo permissions. However, this means that I can’t deploy directly to my document root via scp.
To work around this, I created
blog directory in my user’s home dir and symlinked it to
/var/www/blog. This allows me to deploy to my non-root user’s home directory and the symlink will duplicate the files to the document root.
Connect to the server and create the soft symlink:
sudo ln -s ~/blog/public/ /var/www/blog/public
You should then be able to deploy your site with scp:
sudo scp -r public <username>@<hostname_or_ip_address>:/home/<username>/blog
<username>to the user on the server
- Run this command from the hugo directory or change
Aliases Link to heading
To make this process easier, I created some aliases in my
Note: Make sure to chage
~/location/of to your blog’s directory on your local machine
This alias deletes the old
public directory, builds a new updated one with the
hugo command, then pushes it to the server with
scp while providing status updates on the command line during each step with the
alias blog-push="sudo rm -rf ~/location/of/blog/public && echo 'Removed original public directory' && cd ~/location/of/blog && hugo && echo 'Built new hugo static site' && ssh email@example.com 'rm -rf ~/blog/public' && echo 'Removed old public directory from server' && scp -r ~/location/of/blog/public firstname.lastname@example.org:/home/ubuntu/blog && echo 'Successfully deployed site :)'"
This alias opens the blog directory in Atom:
alias blog-edit="atom ~/location/of/blog"
This alias loads the local site with drafts from any location and returns to the previous directory when exiting:
alias blog-test="cd ~/location/of/blog && hugo server -D && cd -"
HTTPS with Lets Encrypt and Certbot Link to heading
Certbot provides easy guides for your specific distribution here. I will cover my setup with Apache and Ubuntu 18.04.
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-apache
Run certbot in certonly mode and follow the instructions:
sudo certbot certonly --apache
It should find your apache site in
/etc/apache2/sites-available/<hostname>.conf and create a cert for that in
/etc/letsencrypt/live/. If you encounter issues regarding the apache config, comment out the problem lines in the apache config (most likely the SSL cert location as they haven’t been created yet).
Then, uncomment the commented lines if neccissary and verify your apache configuration is setup properly. The configuration in my Ansible template uses the variables in the
var/vars.yml file to redirect incoming connections to port 80 (HTTP) to port 443 (HTTPS), sets the document root to your blog’s public directory and provides the location of the SSL certs created by certbot.
Enable apache SSL module:
sudo a2enmod ssl
Finally, reload the apache config:
sudo service apache2 reload
Important: Make sure to change your Hugo site’s
baseurl = in
https:// and redeploy your site