Hugo on Azure from GitLab

February 17, 2016

Why?

I recently came across Hugo, a static website generator. It’s based on Go, and uses the Go templating engine. It sounded interesting, and I had been looking for something to re-build my personal website, so I decided to give it a try. The only thing one needs in order to host a Hugo-based website is hosting of some kind. I have Azure credits, so that seemed easy. I also wanted to push the sources for my website to a private repository, and I don’t have a paid GitHub account, so I needed something else. GitLab.com allows users to have private repositories, so I decided to go with that.

Setting up Hugo

Setting up a Hugo site is very easy. Really, it’s probably best to follow the documentation. However, I would add that once you pick a theme you’re going to work with (or create your own), you should probably not commit all the themes as submodules. After I selected a theme, I cleared everything out of the themes directory and then cloned just my theme directly as a submodule.

Also, go ahead and commit the Hugo executable in your repository. It’s not that big, and we’ll need it during deployment. It’s actually a beautiful thing: we don’t have to deploy the entire Golang stack anywhere. All we need is the Hugo executable.

Setting up Azure

Next, I needed to set up the Azure website. Using the portal, it’s pretty simple to create a “web app” service. Once that was done, I needed to set up continuous deployment so I could deploy from Git.

Continuous Deployment

continuous deployment

Since I’m using GitLab and Azure doesn’t have a specific integration for it, I set this up as an “External Repository”. All that’s required for an external repository is a clone url and a branch name. Since I’m going to later rely on SSH keys to authenticate the Azure deployment service (Kudu) to my private repository, I use an SSH clone url: git@gitlab.com:myusername/mysitename.git. I’m using the master branch.

Customizing Deployment

Kudu allows you to customize your deployment process, and that’s what I needed to do. I also wanted to support more advanced deployment features, like Azure’s deployment slots. In order to support those kinds of things, I wanted to do some basic variable substitution in the Hugo config file (config.toml). For example, I set baseurl to http://%%HTTP_HOST%%/, and then in my deployment script I replace that with the $env:WEBSITE_HOSTNAME environment variable on Azure. That allows me to have one set of files that can be continuously deployed to production and non-production deployment slots. .

Kudu will read a .deployment file in the root of your repository, and in it we can specify a deployment command. Also, the Azure CLI can generate a deployment script to use as a basis for your own custom steps (see the Kudu link above regarding custom deployment scripts), so I did that, and then wrote these steps:

# 1. Variable substitutions
if ($env:HTTP_HOST -ne "") {
    echo "doing substitutions on $DEPLOYMENT_SOURCE\config.toml"
    gc "$DEPLOYMENT_SOURCE\config.toml" `
        | %{ $_ -replace '%%HTTP_HOST%%', $env:WEBSITE_HOSTNAME } `
        | out-file -encoding ascii "$DEPLOYMENT_SOURCE\config.new.toml"
    mv "$DEPLOYMENT_SOURCE\config.toml" "$DEPLOYMENT_SOURCE\config.old.toml"
    mv "$DEPLOYMENT_SOURCE\config.new.toml" "$DEPLOYMENT_SOURCE\config.toml"
    rm "$DEPLOYMENT_SOURCE\config.old.toml"
    exitWithMessageOnError "HTTP_HOST substitution failed"
}

# 2. Hugo in temporary path
& "$DEPLOYMENT_SOURCE/bin/hugo.exe" -s "$DEPLOYMENT_SOURCE" `
    -d "$DEPLOYMENT_SOURCE/public" --log -v
exitWithMessageOnError "Hugo site generation failed"

Setting up GitLab

It doesn’t take much to “set up” GitLab. Once you have a repository and you’re able to push to it, all that remains is to ensure that the Azure deployment service (Kudu) has access to it and to set up a webhook to notify Azure when changes are pushed. If you’re using a public repo, you’re already done. Just use HTTPS and skip this step. If you’re using a private repo like me, then you’ll need to use Kudu’s ssh keys as deploy keys on GitLab.

Deploy Keys

First, log in to the Kudu service for your Azure website: https://{sitename}.scm.azurewebsites.net - there’s actually a link with the password in it on the azure portal blade for the site. Once you’re authenticated, you’ll have a cookie and will be able to do the next part (or you could skip this and just use the username:password-formatted url you can get from your publishing settings). Go to https://{sitename}.scm.azurewebsites.net/api/sshkey?ensurePublicKey=1. The result will be an ssh public key as a json string, so copy the parts between the quotes and then head over to GitLab and paste it in as a deploy key.

deploy keys

These keys will provide anonymous, read-only access to the repository for the Kudu service.

Webhook

Finally, to get your website to deploy when you push to Git, you need to configure a webhook on your project in GitLab. Again referencing the Kudu documentation, we need the hook to target https://$mysite:BigRandomPassword@mysite.scm.azurewebsites.net/deploy. You can copy the site credentials (the $mysite:pssword part in the url) from the Azure Portal:

Azure site credentials

With this information, you can navigate to your GitLab project and go to the “Webhook” tab (Project > Settings > Web Hooks). The default settings should be adequate (“Push events” checked, “Enable SSL verification” checked). Click on Add Web Hook, and then copy in the url above including the credentials obtained from the Azure portal.

Fin

That’s it! I (and hopefully you too, if that’s what you were going for) have continuous deployment set up for my Hugo site on Azure.