DEV Community

loading...

Integrate automatic deployment in 20 minutes using Webhook.

Ankit_Susne
Curious mind, developer and an otaku with a knack for building things.
Originally published at anksus.me ・4 min read

Introduction

Once a developer’s changes to an application are merged into the repository. It should be deployed to production and available to users. In order to automate this process, we need some tools to integrate into our ecosystem. We can use Github Actions with GitHub-hosted runners or self-hosted runner machines but they both come with a usage limit. We can integrate this process independently without any usage limits or without using any SaaS solutions by simply using the Webhook tool.

Webhook is a lightweight server written in Go. This allows us to create an HTTP endpoint on our server, which when triggered can execute specified commands. It takes two files as an input one JSON configuration file for hooks and one bash file for commands. So, let's implement it on our private GitHub repo and Ubuntu server.

Installing Webhook server

I'm using Google Cloud's VM instance but you can use your own existing server. SSH into your server and
download the Webhook binary. I'm on Ubuntu, so I'll download this one webhook-linux-amd64.tar.gz.

wget https://github.com/adnanh/webhook/releases/download/2.8.0/webhook-linux-amd64.tar.gz
Enter fullscreen mode Exit fullscreen mode

To verify the integrity of the downloaded file, run the below command and cross verify the checksum provided on the official repo.

md5 webhook-linux-amd64.tar.gz
Enter fullscreen mode Exit fullscreen mode

Extract the tar file using

tar -xvf webhook-linux-amd64.tar.gz
Enter fullscreen mode Exit fullscreen mode

To access webhook binary globally move it to the /usr/local/bin directory.

sudo mv  webhook-linux-amd64/webhook /usr/local/bin
Enter fullscreen mode Exit fullscreen mode

To verify, if everything went down correctly type webhook --version, if we see a version in the output then the setup is correct. Now let's start our webhook server, type webhook -verbose. It shows the server is running on port 9000. Later, we will make it run in the background as a service using the systemd. We can close it now.
webhook verbose

Creating webhook on GitHub

Go to WebHooks under settings and click on Add webhook Type IP address or URL of your server in place of XX.YYY.XX.YYY without port 9000 http://XX.YYY.XX.YYY/hooks/redeploy-app. Later we will configure Nginx to proxy pass it. Content-type to application.json Add a secret that will be used to verify the webhook trigger on our server and then click on Add webhook

webhook

Configuring our webhook server.

So, our webhook server setup is complete. Now we have to create an endpoint that will execute our bash script. Let's create a directory webhook-setup and two files hooks.json and redeploy.sh.

mkdir webhook-setup
cd webhook-setup
touch hooks.json
touch redeploy.sh
Enter fullscreen mode Exit fullscreen mode

make redeploy.sh an executable file. By writing the below command.

chmod +x redeploy.sh
Enter fullscreen mode Exit fullscreen mode

Open your favorite editor and paste the following code in hooks.json. I'm using vim. In case you got stuck.
how-do-i-exit-the-vim-editor

vim hooks.json
Enter fullscreen mode Exit fullscreen mode
[
  {
    "id": "redeploy-app",
    "execute-command": "/home/ankit/webhook-setup/redeploy.sh",
    "command-working-directory": "/home/ankit/demo-app",
    "response-message": "Deployed.......",
     "trigger-rule":
    {
      "and":
      [
        {
          "match":
          {
            "type": "payload-hash-sha1",
            "secret": "some-super-secret",
            "parameter":
            {
              "source": "header",
              "name": "X-Hub-Signature"
            }
          }
        },
        {
          "match":
          {
            "type": "value",
            "value": "refs/heads/main",
            "parameter":
            {
              "source": "payload",
              "name": "ref"
            }
          }
        }
      ]
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

The id field will create a new endpoint as http://0.0.0.0:9000/hooks/{id}. Whenever a request comes to the Webhook server it will execute the script mentioned in execute-command field inside a command-working-directory. The secret field should have the same secret as we generated on GitHub. Replace the value field with your branch. Right now it points to the main branch. To know more about the parameters visit webhook parameters

Now, let's create a script that will pull our code from the GitHub repo. We can write any commands here like running tests, building, or deploying a new version (basically, it's a bash script).

vim redeploy.sh
Enter fullscreen mode Exit fullscreen mode

paste the following code into redeploy.sh and save it.

#!/bin/bash

git pull
npm install
pm2 reload all
pm2 save
Enter fullscreen mode Exit fullscreen mode

I am using pm2 to manage all the nodejs processes. Now, all the setup is complete. We can spin up our webhook server. But first, let's make it a background process by using systemd. So that, it restarts when our server reboots.

Creating webhook service

First, create a file called webhook.service in /etc/systemd/system. The below command creates that file and opens it.

sudo vim /etc/systemd/system/webhook.service
Enter fullscreen mode Exit fullscreen mode

and paste the following code into it.

[Unit]
Description=Webhooks
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
User=ankit
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/webhook -verbose -hotreload -hooks /home/ankit/webhook-setup/hooks.json  port 9000 -ip "127.0.0.1" -http-methods post

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

In User type your username. Let's try to understand the ExecStart, it executes the command passed to it. /usr/local/bin/webhook is the location of our webhook binary and /home/ankit/webhooks-setup/hooks.json of hooks.json. The HTTP method is POST because GitHub makes a POST request.

Now, we have to start the webhook service and enable it so that it restarts if our server reboots.

sudo systemctl start webhook.service
sudo systemctl enable webhook.service
Enter fullscreen mode Exit fullscreen mode

Now, our integration is complete. We can make changes to the local repo and test pushing changes to origin. It will get automatically deployed to our server as well.

To know how to setup Nginx to proxy pass the URL, read my complete blog here.

If there's a way to improve the setup, then please let me know in the comments.

Discussion (0)