How to setup automatic Hugo website generation and deployment with Git
Tags: devops, tutorial, ubuntu, git
Published: 2018-01-28 09:56:45

---
title: How to setup automatic Hugo website generation and deployment with Git
published: true
tags: ["devops", "tutorial", "ubuntu", "git"]
canonical_url: https://lobotuerto.com/blog/how-to-setup-automatic-hugo-website-generation-and-deployment-with-git/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/940lr1ppy482163k3j3q.png
---

Let’s say that you have tried [Hugo,](https://gohugo.io/) you liked it, and made a website with it.  
Now you are ready to deploy that website for the _whole world_ to see.

Wouldn’t it be great if you could just do:

```
git add .
git commit -m "Updated blog content"
git push
```

And be **done** with it?

Well, if that sounds like your kind of thing; something you’d like to have…  
Then read on my friend!

* * *

# Inventory

What do you need for this tutorial?

- A public server somewhere. If you don’t have one, you can get a **VPS** (Virtual Private Server) from [Linode](https://www.linode.com/), [DigitalOcean](https://www.digitalocean.com/) or similar providers.
- An account with access to `sudo`.
- You have `git` available, from [this guide.](https://dev.to/lobo_tuerto/cmo-instalar-git-en-ubuntu-285g-temp-slug-759430 "Cómo instalar Git en Ubuntu")
- You use Gitolite to manage your repositories, from [this guide.](https://dev.to/lobo_tuerto/how-to-setup-your-own-private-git-repositories-with-gitolite-k66 "How to setup a private Git server with Gitolite")
- A configured webserver —I recommend looking into [NGINX](https://www.nginx.com/), since it’s super easy to setup in Ubuntu.

Let’s assume:

● A local `~/.ssh/config` file with this content:

```
Host git-server
  # This is the IP for your VPS
  HostName 111.111.111.111
  Port 22
  # This is the remote user
  User yolo

Host web-server
  # This is the IP for your other VPS
  HostName 222.222.222.222
  Port 22
  # This is the remote user
  User webcustomer
```

● You have your Hugo project versioned with **git** and you can push code to the remote repository.

● The repository’s name is `yolo-web`, so you can clone it like this:

```
git clone git@git-server:yolo-web
```

# Install dependencies

First, let’s login on the remote machine; the one you want to setup automatic deployment on.

Open a terminal and SSH into it:

```
ssh git-server
```

We need the `hugo` command available, for that the easiest way is to use `snapd`:

```
sudo apt install snapd
sudo snap install hugo
```

Login as the `git` user and verify `hugo` is working:

```
sudo su git -l
hugo version
```

You should see something like:

```
Hugo Static Site Generator v0.34 linux/amd64 BuildDate:
```

# Create and configure the `post-receive` hook script

This is the important part.

This script will be in charge of doing **something** after the repository receives a `git push`.  
In our case, we want the script to `git checkout` a copy of the current `master`branch in a directory of our choosing and then call `hugo` on it to generate the HTML files for the web server.

Let’s create the `post-receive` file:

```
touch ~/repositories/yolo-web.git/hooks/post-receive
chmod 700 ~/repositories/yolo-web.git/hooks/post-receive
```

And put this content inside:

```
#!/bin/bash

export GIT_WORK_TREE=/home/git/yolo-web-compiled

echo `pwd`
echo "Generating site with Hugo for yolo-web"

mkdir -p $GIT_WORK_TREE
chmod 755 $GIT_WORK_TREE

git checkout -f master

rm -rf $GIT_WORK_TREE/public
cd $GIT_WORK_TREE && /snap/bin/hugo

find $GIT_WORK_TREE/public -type f -print | xargs -d '\n' chmod 644
find $GIT_WORK_TREE/public -type d -print | xargs -d '\n' chmod 755

echo "All done! 0 problems"
```

You now have a process in place that will leave the latest HTML files generated by Hugo in `/home/git/yolo-web-compiled`.

Go ahead, try it out, make some local changes, `git commit` and `git push`, then SSH in and see what’s inside `/home/git/yolo-web-compiled`.

# The web server situation

## Same server for compiling and web serving

If your web server is in the same machine as your repos, then you can simply point with a _symbolic link_ to the `/home/git/yolo-web-compiled/public` directory and call it a day!

Else…

## Compiling in one server, web serving in another

What if you have different machines for hosting your Git repositories and hosting your web pages?

How would that work? Glad you asked...

* * *

What follows is an opinionated soluion to this problem.

● Generate an SSH key pair for the **git@git-server** user with an empty passphrase:

```
ssh git-server
sudo su git -l
sshkey-gen -t rsa -b 4096 -C "git@git-server"
```

● Try to access the server through SSH —it’ll fail, but we need this so its _signature_ gets registered into the `~/.ssh/know_hosts` file.


```bash
ssh webcustomer@222.222.222.222
```

You should answer `yes` ---don't just type `y`--- when it asks:

```bash
Are you sure you want to continue connecting (yes/no)?
```

● `exit` the **git** user shell, you are now in your **yolo** shell.

● Copy the public key from **git** to your home:

```
sudo cp /home/git/.ssh/id_rsa.pub ~/git.pub
```

● `exit` the remote session, you are now in your **local** machine.

● Copy the `git.pub` file to your local machine:

```
mkdir ~/tmp
scp git-server:git.pub ~/tmp/
```

● Upload the key to the server where the page is going to be hosted:

```
scp ~/tmp/git.pub web-server:
```

● Login to the web server machine:

```
ssh web-server
```

● Copy the contents of `~/git.pub` at the end of `~/.ssh/authorized_keys`.

That’s it, SSH into `git-server`, then `sudo su git -l` and test that`ssh webcustomer@222.222.222.222` works.

If the last SSH login work, you can now `scp` or `rsync` content from the **repository machine** to the **web server machine!**

● Modify the `~/repositories/yolo-web.git/hooks/post-receive` file and include a call to`rsync` or `scp` to transfer files from `git-server` to `web-server` —I prefer to use `rsync`:

```
#!/bin/bash

export GIT_WORK_TREE=/home/git/yolo-web-compiled

echo `pwd`
echo "Generating site with Hugo for yolo-web"

mkdir -p $GIT_WORK_TREE
chmod 755 $GIT_WORK_TREE

git checkout -f master

rm -rf $GIT_WORK_TREE/public
cd $GIT_WORK_TREE && /snap/bin/hugo

find $GIT_WORK_TREE/public -type f -print | xargs -d '\n' chmod 644
find $GIT_WORK_TREE/public -type d -print | xargs -d '\n' chmod 755

rsync -avzP $GIT_WORK_TREE/public/ \
webcustomer@222.222.222.222:/var/www/yolo-web/html

echo "All done! 0 problems"
```

NOTE: You’ll need to tweak the last param for the `rsync` command above to match your website’s files path.