--- title: "Deploy a Hugo Website with GIT" tags: ["hugo", "gogs", "git", "deploy", "webhooks", "hooks"] categories: ["recipe", "sysadmin"] description: "How to deploy a hugo-powered static website to a webserver with Gogs" date: 2019-05-27T20:34:30+02:00 author: "Ettore Dreucci" draft: false --- ## How to deploy a hugo-powered static website to a webserver with GIT [This](https://ettore.dreucci.it) website is powered by [Hugo](https://gohugo.io/), an open-source static website generator written in [Go](https://golang.org/). I can write pages and posts in [Markdown](https://daringfireball.net/projects/markdown/) and then generate some static .html pages to upload to a webserver. For this project, as I usually do, I push every change to a self-hosted [GIT](https://git-scm.com/) server with [Gogs](https://gogs.io/) (another open-source, golang written GIT server), so why not use webhooks to automate the deployment? Gogs, as GitHub, GitLab and other well-known services provides webhooks to notify other services of changes in a repository: they are basically HTTP callbacks triggered by some user-defined events such as a push or a pull request. Each time you, for instance, push to a repo, Gogs will send a **HTTP POST** payload to the webhook’s configured URL: the payload will contain the relevant event information. To protect from unauthorized requests you could tell Gogs to send, in the header of the POST request, a `X-Gogs-Signature` that contains the **HMAC hex digest of the payload** generated using the `sha256` hash function and a **secret** as the HMAC key. My event-chain is the following: I push the new content to the repo, Gogs trigger a webook that send a HTTP POST payload to a .php page in the webserver. The php-page pulls the repo to the server, generates the static website with `hugo` and copies the newly generated `public` directory to the document root of the webserver. #### So, let’s see the practical part: 1. Add in the Gogs repository configuration an ssh *Deploy Key*, to pull the repo in the webserver. The *deploy key* will have read-only access. You can generate the ssh key with `ssh-keygen` but keep it password-less to make the pull completely automated. 2. Clone the repo in the document root with ```` git clone user@git.server:repo /var/www/ ```` 3. Insert in your `.htaccess` file the secret like that: ```` SetEnv GOGS_DEPLOY_SECRET y0uRs3cRetC0d3 ```` 4. Create a `deploy.php` page that will pull the repo, generate the website and deploy it when called. You can use the following script: ```` commits)){ // When merging and pushing to Gogs, the commits array will be empty. // In this case there is no way to know what branch was pushed to, so we will do an update. $commit_message .= 'true'; } else { foreach ($data->commits as $commit) { $commit_message .= $commit->message; } } if (!empty($commit_message)) { // Do a git pull, run Hugo, and copy files to public directory exec('cd ' . $repo_dir . ' && git pull'); exec('cd ' . $repo_dir . ' && ' . $hugo_path); exec('cd ' . $repo_dir . ' && cp -r ' . $repo_dir . $rendered_dir . '/. ' . $web_root_dir); // Log the deployment file_put_contents('deploy.log', date('m/d/Y h:i:s a') . " Deployed branch: " . $branch . " Commit: " . $commit_message . "\n", FILE_APPEND); } ```` 5. In the Gogs repository webpage, activate a webhook, specifying the `deploy.php` URL, the content type (`application/json`) and a secret. Then select the event(s) that will trigger the webhook. 6. You’re done! Write a new post, push it and see the magic ;)