Setting up Webhooks on Linux for Automated Deployments

written by Müjdat Korkmaz
DevOps

I’ve used variety of different tools or services over the last few years to deploy my applications. These are called serverless but in reality, it’s just another computer, somewhere out there, on the cloud. These take care of a lot of stuff for you and make your life as a developer very easy!

  • Automatic deployments
  • Preview deployments
  • Environment management
  • Reverse proxy
  • Custom domains

and many other things, however, sometimes all you might just want to host on your own VPS, like on Hetzner or DigitalOcean and have automatic deployments.

This is where Webhooks come in handy. You can set them up on your Linux server and add the webhook URL to your GitHub, GitLab or BitBucket. This guide will show you how you can install and configure webhooks on your server.

Installing Webhooks

My favorite and one of the most starred tools for this is, webhook by adnanh. It’s written in go, and uses JSON or YAML formatted files for configuring webhooks.

There are multiple ways of installing it, in my experience on Debian, I found easiest way to install it to be apt-get repository. Just running the following command will install it. For other installation methods, you can check their readme.

sudo apt-get install webhook

Configuring Webhooks

Now it’s time to register some webhooks! First let’s create a folder called hooks on our home directory (this can be anywhere, but for the purposes of this guide, I’ll create it on home folder)

mkdir ~/hooks

Next we’ll create a new file inside hooks called hooks.json. We can do it with Nano, but any other text editor will do the trick.

nano ~/hooks/hooks.json

Next, let’s add the following into our file. This is a very simple webhook definition, that the tool can use, which defines some rules in order to execute the given script.

[
  {
    "id": "my-deploy-hook-id",
    "execute-command": "/root/apps/my-app-1/deploy.sh",
    "command-working-directory": "/root/apps/my-app-1",
    "response-message": "Executing deploy script...",
    "trigger-rule": {
      "match": {
        "type": "value",
        "value": "refs/heads/main",
        "parameter": {
          "source": "payload",
          "name": "ref"
        }
      }
    }
  }
]

Keep in mind, that this is a very simple webhook configuration, and that you can create a lot more complex trigger rules for your specific use case. This one, simply defines a command to be executed on a specific folder with a simple trigger rule, that expects a ref parameter to have the value of refs/heads/main. Check webhook repository for more examples with different trigger rules.

Whenever this webhook URL is called and trigger rule is a match, deploy.sh script inside /root/apps/my-app-1/deploy.sh will be executed but first, we need to start the webhook server.

By running following command, webhook server will start on port 9000 (Replace mujdat with your username and set your server’s IP)

/home/mujdat/go/bin/webhook -hooks /home/mujdat/hooks/hooks.json -ip "YOUR-SERVER-IP" -verbose

Next, you can check if your webhook is correctly configured by sending a request to your that URL with the following structure:

http://YOUR-SERVER-IP:9000/hooks/my-deploy-hook-id

Using Supervisor to Keep Webhooks Running

Now that we know everything is working, we need to make sure that this webhook server is always running and the easiest way to do that is using supervisor, a process control system.

We can install it by running following command, if we’re on Debian.

sudo apt install supervisor

And with the following, we’ll to create a config file for a webhook process:

cd /etc/supervisor/conf.d
sudo nano webhooks.conf

And we’re going to add the following to our webooks.conf file (make sure to change mujdat with your username and set your server’s IP)

[program:webhooks]
command=bash -c "/home/mujdat/go/bin/webhook -hooks /home/mujdat/hooks/hooks.json -ip 'YOUR-SERVER-IP' -verbose"
redirect_stderr=true
autostart=true
autorestart=true
user=user
numprocs=1
process_name=%(program_name)s_%(process_num)s
stdout_logfile=/home/mujdat/hooks/supervisor.log
environment=HOME="/home/user",USER="user"

This defines a configuration for the webhook server that is going to be managed by supervisor, such as command to start it, standart output log file location, environment etc.

We then need to create the initial log file, then have supervisor reread check if the new configuration is registered, if so, update it and finally start webhooks server via supervisor.

touch ~/hooks/supervisor.log
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start webhooks:*

That’s pretty much it, any time that URL is hit, your script, if trigger rules match, will be executed. Supervisor will keep the process running in the background. Remember that, whenever you add a new configuration file, or another hook to the hooks.json file, you’ll need to reread, update and restart supervisor process.

On another post, I’ll write about how I’ve been using webhooks and supervisor with some custom deploy scripts on my Hetzner VPS.

In case you want to check Hetzner, you can use my referral link to get some credit to start with.