Setup Hugo blog on Digital Ocean and Wercker

For the first post I think a good topic is to explain how I made the setup of my Hugo blog on a Digital Ocean small server and configure Wercker to make the deploy of my blog when I made pushes on my git repository.
Why hugo?
I tried many blog frameworks (blogger, wordpress) but after all that I decided to go simple. Simple is the new cool nowadays so I saw jekyll but didn’t like and then I discover Hugo, a great product that promise to be a great static pages generator.
I saw that a static page generator is what I need and I like the simplicity of Hugo instead of Jekyll.
Let’s begin
First of all this is what we need to start and configure our blog:
- 1 - Install Hugo Locally
- 2 - Git repository for blog
- 3 - Digital Ocean Droplet
- 4 - Nginx to serve the pages
- 5 - Deploy with Wercker
Ok this is the list of things we need to do, let’s follow this steps and start to configure our environment.
1 - Install Hugo Locally
If you are on mac os and have homebrew installed like me it’s preety easy to install hugo, you just need to do this:
brew update && brew install hugo
That’s it. After the installation finish you can run:
hugo version
And something like that will be printed:
Hugo Static Site Generator v0.18.1 BuildDate: 2016-12-29T14:12:41-03:00
For more information about the installation in other platforms you can look here on Hugo doc page.
Now that we have hugo installed in our local machine let’s create a new site. Hugo have a command to create a new website with all the folders structure, you just need to run:
hugo new site [site-name]
This command will create a new folder with the site name you choose. Now go to that folder and create a git repository inside and create a .gitignore file with the content:
public/
This is the default folder that hugo use to put all the build content of your site so you don’t need to version this folder because this folder will be created with wercker and copied to Digital Ocean server on deploy process.
2 - Git repository for blog
Now you need to create a git repository for blog. This is simple just create a new repository on GitHub or BitBucket or any other that you already use and configure the git remote on your blog local folder.
3 - Digital Ocean Droplet
I choose digital ocean because is cheap and easier to use also they have great tutorials about how to configure a droplet and other stuffs that you could use later for your projects.
First of all you need to sign up on Digital Ocean and add your payment info, after that you can just click on the big green button on top of the web page: “Create Doplet”. Then you will be guided to choose all the configs of the server by a simple form, it’s very simple not secrets there just choose one with Ubuntu 16.04 installed that is the linux distribution I will use on this tutorial.
I choose the smallest droplet with 512MB, 1CPU and 20GB SSD. It’s the cheapest one, just US$ 5/month.
After that you need to configure your droplet to access with ssh and block some ports with a firewall and so on. Since this is not the main reason of this post I suggest you to follow this Digital Ocean tutorial that it’s good explained how to do that and easier to understand: Initial Server Setup with Ubuntu 16.04.
4 - Nginx to serve the pages
Now we have our server created, configured and with ssh access, let’s install and configure the Nginx.
Access your server with ssh and run:
sudo apt-get update
sudo apt-get install nginx
After that we will have the Nginx installed in our server, if you enabled the firewall on your server you need to configure the firewall to allow access to nginx http server, let’s do that.
First run:
sudo ufw app list
It will the available applications, something similar to that:
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
There are 3 options of Nginx there, we will allow just the HTTP now, since we will not configure HTTPS for our blog. Run:
sudo ufw allow 'Nginx HTTP'
And then if you run:
sudo ufw status
The output should be something similar to this:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
After that the Nginx will be installed and running, you can check by these two steps:
You can run:
systemctl status nginx
The output should be:
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2016-04-18 16:14:00 EDT; 4min 2s ago
Main PID: 12857 (nginx)
CGroup: /system.slice/nginx.service
├─12857 nginx: master process /usr/sbin/nginx -g daemon on; master_process on
└─12858 nginx: worker process
Or you can access the IP of your droplet on the browser and se the nginx default page:
One last thing I did was change the default folder of Nginx. The default was /var/www/html and I changed to /var/www/blog. To do that you need to change a line on default config file of sites-available of nginx. You can do that using vi or nano and edit the file /etc/nginx/sites-available/default and change the line on server config scope:
root /var/www/html;
To:
root /var/www/blog;
After this change you need to reload the nginx to get the new configs:
sudo systemctl reload nginx
Now if you access the ip of your droplet you will get an error cause on the /var/www/blog folder there is no index file, to test if you config works just copy the index.nginx-debian.html from /var/www/html folder to /var/www/blog folder and access the IP again on the browser then you will see the nginx default page again.
If you want more information about the nginx see this tutorial of How To Install Nginx on Ubuntu 16.04 of digital ocean.
Ok, now we have the Server with Nginx installed and configured, let’s go to the next step.
5 - Deploy with Wercker
Wercker is a CI service that have a free and paid version, the free version meets our needs.
After you signup on Wercker you need to create a new application:
And follow the wizard steps. On step 3 about configure access choose the recommended one about wecker using ssh key to access your code.
Then finish the wizard.
We have to configure the created app to generate the ssh keys, allow ssh access to this new ssh key in our server and configure the HOSTNAME env var on wercker container.
To generate the ssh key pair you need to access your app on Wercker dashboard and go to environment tab:
And click on Generate SSH Keys button at the bottom right of the page:
Also create a new environment varibale named HOSTNAME and put the IP of your server as value.
Now we need to copy the value of WERCKER_PUBLIC variable and add as authorized on our server. After copy the value make an ssh access to your server and chage to root user:
sudo su
You will be asked to put your user password. With root user edit the file /root/.ssh/authorized_keys and add the WERCKER_PUBLIC key that you copied from enviroment tab on wercker. Save the file and close. Now the wercker will be allowed to access your server to make the deploy as root.
Now we have the app created and configured on Wercker and on our server we need to tell the wercker what steps it need to do to deploy our blog, we do that creating a wercker.yml file on the root of our blog folder.
I will use the wercker.yml file I used as base to create mine, it’s almost the same thing I just made some changes to debug a problem that I will explain later:
wercker.yml
box: ubuntu
build:
steps:
- arjen/hugo-build@1.14.1:
version: "0.18.1"
theme: theme-name
flags: --buildDrafts=false --noTimes
deploy:
steps:
- install-packages:
packages: openssh-client rsync
- add-to-known_hosts:
hostname: $HOSTNAME
- mktemp:
envvar: PRIVATEKEY_PATH
- create-file:
name: write key
filename: $PRIVATEKEY_PATH
content: $WERCKER_PRIVATE
overwrite: true
- script:
name: transfer blog
code: |
rsync -au -e "ssh -i $PRIVATEKEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress public/* root@$HOSTNAME:/var/www/blog
ssh -i $PRIVATEKEY_PATH -l root -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $HOSTNAME chown -R www-data:www-data /var/www/
- script:
name: restart nginx
code: ssh -i $PRIVATEKEY_PATH -l root -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $HOSTNAME nginx -s reload
Important steps here:
1 - If you didn’t have a theme on your hugo blog you can just remove the theme line on wercker file. 2 - If you didn’t change the nginx default folder change this line:
rsync -au -e "ssh -i $PRIVATEKEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress public/* root@$HOSTNAME:/var/www/blog
To:
rsync -au -e "ssh -i $PRIVATEKEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress public/* root@$HOSTNAME:/var/www/html
Now we have our wecker.yml file let’s add a new workflow to our app on wercker to deploy the blog. Access the workflow tab on our wercker app dashboard:
Click on add a new pipeline button and create a new pipeline like the image:
After that add the new pipeline to workflow when the master branch receives the push, like I did on this image and add the deploy pipeline that you created as Execute Pipeline:
To test if everything is working just push on your master branch and you will see a new deploy process running on the Runs tab of your wercker app dashboard. After the steps finish you can access and see that your blog is up and running.
Important tip:
When I was doing that my theme was just working locally, when it was deploying a message appeared:
=============================================================
Your rendered home page is blank: /index.html is zero-length
* Did you specify a theme on the command-line or in your
"config.toml" file? (Current theme: "hugo-icarus-theme")
* For more debugging information, run "hugo -v"
=============================================================
And I discover that I need to remove the .git/ folder inside the theme folder because this creates a submodule and the deploy process could not make the theme works on linux. After I opened a issue on ArjenSchwarz/wercker-step-hugo-build project I discovered the problem, he also gave me another solution that I didn’t tried if you want to test feel free to do that, here the issue link.
Thanks
I’d like to thanks the digital ocean tutorials that I used to make this post and to thanks gettingthingstech.com that have a great tutorial of how to setup this environment to that I also used as based to create this post.
You can access the gettingthingstech.com post of how to setup this environment here.