diff --git a/_ansible/node002.yml b/_ansible/node002.yml
index 1966878..abaaffc 100644
--- a/_ansible/node002.yml
+++ b/_ansible/node002.yml
@@ -50,6 +50,8 @@
       tags: [watchtower]
     - role: webdis
       tags: [webdis]
+    - role: webhook
+      tags: [webhook]
     - role: wiki_js
       tags: [wiki-js]
     - role: woodpecker
diff --git a/_ansible/roles/webhook/files/teamspeak-fallback-db b/_ansible/roles/webhook/files/teamspeak-fallback-db
new file mode 100755
index 0000000..7a3ad52
--- /dev/null
+++ b/_ansible/roles/webhook/files/teamspeak-fallback-db
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+
+chown -R "${TEAMSPEAK_USER}:${TEAMSPEAK_GROUP}" /mnt/teamspeak-fallback-data
+install -o "${TEAMSPEAK_USER}" -g "${TEAMSPEAK_GROUP}" -m 644 "$WEBHOOK_DATA" "/mnt/teamspeak-fallback-data/ts3server.sqlitedb"
diff --git a/_ansible/roles/webhook/tasks/main.yml b/_ansible/roles/webhook/tasks/main.yml
new file mode 100644
index 0000000..4930776
--- /dev/null
+++ b/_ansible/roles/webhook/tasks/main.yml
@@ -0,0 +1,44 @@
+---
+- name: Set common facts
+  ansible.builtin.import_tasks: tasks/set-default-facts.yml
+
+- name: Deploy {{ svc.name }}
+  vars:
+    svc: "{{ webhook_svc }}"
+    compose: "{{ webhook_compose }}"
+    env: "{{ webhook_env }}"
+    yml: "{{ webhook_yml }}"
+  block:
+    - name: Import prepare tasks for common service
+      ansible.builtin.import_tasks: tasks/prepare-common-service.yml
+
+    - name: Set webhook config path
+      ansible.builtin.set_fact:
+        config_path: "{{ (service_path, 'config') | path_join }}"
+
+    - name: Create config directory
+      ansible.builtin.file:
+        path: "{{ config_path }}"
+        state: directory
+        mode: "0755"
+
+    - name: Template main config
+      ansible.builtin.template:
+        src: service.yml.j2
+        dest: "{{ (config_path, 'hooks.yml') | path_join }}"
+        mode: "0644"
+      register: cmd_result
+
+    - name: Set the docker force-recreate flag
+      ansible.builtin.set_fact:
+        docker_force_recreate: --force-recreate
+      when: cmd_result.changed # noqa: no-handler We need to handle the restart per service. Handlers don't support variables.
+
+    - name: Copy the teamspeak-fallback-db script
+      ansible.builtin.copy:
+        src: teamspeak-fallback-db
+        dest: "{{ (config_path, 'teamspeak-fallback-db') | path_join }}"
+        mode: "0755"
+
+    - name: Import start tasks for common service
+      ansible.builtin.import_tasks: tasks/start-common-service.yml
diff --git a/_ansible/roles/webhook/vars/main.yml b/_ansible/roles/webhook/vars/main.yml
new file mode 100644
index 0000000..91e05a3
--- /dev/null
+++ b/_ansible/roles/webhook/vars/main.yml
@@ -0,0 +1,45 @@
+---
+webhook_teamspeak_fallback_db_token: "{{ vault_webhook.teamspeak_fallback_db_token }}"
+webhook_teamspeak_user: 9987
+webhook_teamspeak_group: 9987
+
+webhook_svc:
+  name: webhook
+  domain: hook.serguzim.me
+  port: 9000
+
+webhook_env:
+  TEAMSPEAK_USER: "{{ webhook_teamspeak_user }}"
+  TEAMSPEAK_GROUP: "{{ webhook_teamspeak_group }}"
+
+webhook_yml:
+  - id: teamspeak-fallback-db
+    trigger-rule-mismatch-http-response-code: 400
+    execute-command: /config/teamspeak-fallback-db
+    pass-file-to-command:
+      - source: payload
+        name: data
+        envname: WEBHOOK_DATA
+        base64decode: true
+    trigger-rule:
+      and:
+        - match:
+            type: value
+            value: "{{ webhook_teamspeak_fallback_db_token }}"
+            parameter:
+              source: header
+              name: X-Webhook-Token
+
+webhook_compose:
+  watchtower: true
+  image: ghcr.io/thecatlady/webhook
+  volumes:
+    - ./config:/config:ro
+    - teamspeak-fallback-data:/mnt/teamspeak-fallback-data
+  file:
+    services:
+      app:
+        command: ["-verbose", "-hooks=/config/hooks.yml"]
+    volumes:
+      teamspeak-fallback-data:
+        name: teamspeak-fallback-data
diff --git a/caddy/config/conf.002.d/hook.serguzim.me.conf b/caddy/config/conf.002.d/hook.serguzim.me.conf
deleted file mode 100644
index 97fe58f..0000000
--- a/caddy/config/conf.002.d/hook.serguzim.me.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-hook.serguzim.me {
-	import default
-	reverse_proxy host.docker.internal:3002
-}