diff --git a/content/blog/deploy-hugo-git.md b/content/blog/deploy-hugo-git.md new file mode 100644 index 0000000..1f6b878 --- /dev/null +++ b/content/blog/deploy-hugo-git.md @@ -0,0 +1,113 @@ +--- +title: "Deploy a Hugo Website with GIT" +tags: ["hugo", "gogs", "git", "deploy", "webhook"] +categories: ["recipe"] +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 +--- + +## [[recipe]({{< ref "/categories/recipe" >}})]: 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 ;) +