Skip to content

webhook service with TLS and Let's Encrypt certificate

For a number of services, I need a system/service which can receive web hooks, and act when such a trigger is received.

Just a few examples:

  • GitHub can send web hooks when something changes in a repo (in any repository you administer, go to "Settings" -> "Webhooks", and add your own hook)
  • Tasker for Android can send HTTP(s) requests
  • JIRA can send web hooks when certain events occur
  • openHAB can send messages to other services

Now it would be useful to have your own receiver for web hooks, and run any task you want. There are a number of tools out there, which can solve this problem. I settled with "webhook". In addition, I deploy everything using Ansible, therefore I had to write a bit of code in order to automate this process.


Let's start with installing "webhook":

- name: webhook packages
  apt: name={{ item }} state=present
    - webhook
    - python3-yaml
  register: webhook_install

Let's Encrypt requires that certificate renewal happens on port 80 (if you are using the HTTP-01 challenge mechanism). Doing the certificate renewal is beyond this blog post, there are several possible methods. Let's just assume there is another service running which renews the certificate every once in a while, and "webhook" has access to the certificate and can use it.

By default, webhook will not use encryption. But of course we want that. Encryption can be enabled using the "-secure" option, and providing the certificate (-cert option) and the key (-key option). Let's update everything in the systemd service file:

# update systemd service file for webhooks
# TLS certificate is Let's Encrypt
- name: /lib/systemd/system/webhook.service
    dest: /lib/systemd/system/webhook.service
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
    state: "{{ item.state }}"
    - { regexp: '^ExecStart', line: 'ExecStart=/usr/bin/webhook -nopanic -port 6500 -hotreload -verbose -hooks /etc/webhook.conf -secure -cert /etc/ssl/signed.crt -key /etc/ssl/domain.key', state: present }
  register: webhook_service

It also needs a webhook.conf, with the actual configuration of what you want to listen to:

- name: Upload webhook.conf
    src: webhook.conf
    dest: /etc/webhook.conf
    owner: root
    group: root
    mode: 0640
  register: etc_webhook_conf

Make sure (mode: 0640) that not everyone can read this file - most likely you have secrets configured in it. Documentation how to write a webhook config is here, examples are here.

The next part is a bit more tricky: although the above systemd service file specifies the "-hotreload" option, this only applies to changes in the webhooks.conf. webhook will not recognize when the certificate is renewed, and needs to be restarted for that. I'm using another systemd service for that - and because of the way systemd handles that, you need two files: the service file, and a file for the timer. Wasn't it easy when you just created a single line in a cron job?


Description=restart webhook

ExecStart=/bin/systemctl restart webhook


OnCalendar=*-- 3:00:00


Upload everything to the server:

- name: Upload webhook restart service
    src: containers/files/webhooks/webhook-restart.service
    dest: /etc/systemd/system/webhook-restart.service
    owner: root
    group: root
    mode: 0640
  register: webhook_restart_service

- name: Upload webhook restart timer
    src: containers/files/webhooks/webhook-restart.timer
    dest: /etc/systemd/system/webhook-restart.timer
    owner: root
    group: root
    mode: 0640
  register: webhook_restart_time

Enable and start the service and the timer:

# the service is not automatically registered and started
- name: enable webhook service
    name: webhook
    state: started
    enabled: yes
  when: webhook_install.changed

- name: enable webhook-restart service
    name: webhook-restart
    state: started
    enabled: yes

- name: enable webhook-restart timer
    name: webhook-restart.timer
    state: started
    enabled: yes

And if something has changed, systemd must be reloaded, and webhook must be restarted:

- name: force systemd to reread configs
    daemon_reload: yes
  when: webhook_service.changed or webhook_restart_service.changed or webhook_restart_time.changed

- name: restart webhook
    name: webhook
    state: restarted
  when: webhook_service.changed

- name: reload webhook service
  shell: killall -USR1 webhook
  when: etc_webhook_conf.changed


That's it. The webhook service is now up and running on port 6500. webhook itself does not do any host verification. It will just listen to any hostname which points to this server.


No Trackbacks


Display comments as Linear | Threaded

No comments

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
To leave a comment you must approve it via e-mail, which will be sent to your address after submission.
Form options