webhook is a lightweight incoming webhook server to run shell commands

What is webhook? build-status

Webhook

webhook is a lightweight configurable tool written in Go, that allows you to easily create HTTP endpoints (hooks) on your server, which you can use to execute configured commands. You can also pass data from the HTTP request (such as headers, payload or query variables) to your commands. webhook also allows you to specify rules which have to be satisfied in order for the hook to be triggered.

For example, if you're using Github or Bitbucket, you can use webhook to set up a hook that runs a redeploy script for your project on your staging server, whenever you push changes to the master branch of your project.

If you use Mattermost or Slack, you can set up an "Outgoing webhook integration" or "Slash command" to run various commands on your server, which can then report back directly to you or your channels using the "Incoming webhook integrations", or the appropriate response body.

webhook aims to do nothing more than it should do, and that is:

  1. receive the request,
  2. parse the headers, payload and query variables,
  3. check if the specified rules for the hook are satisfied,
  4. and finally, pass the specified arguments to the specified command via command line arguments or via environment variables.

Everything else is the responsibility of the command's author.

Hookdoo

hookdoo

If you don't have time to waste configuring, hosting, debugging and maintaining your webhook instance, we offer a SaaS solution that has all of the capabilities webhook provides, plus a lot more, and all that packaged in a nice friendly web interface. If you are interested, find out more at hookdoo website. If you have any questions, you can contact us at [email protected]

hookdeck If you need a way of inspecting, monitoring and replaying webhooks without the back and forth troubleshooting, give Hookdeck a try!

Getting started

Installation

Building from source

To get started, first make sure you've properly set up your Go 1.14 or newer environment and then run

$ go build github.com/adnanh/webhook

to build the latest version of the webhook.

Using package manager

Snap store

Get it from the Snap Store

Ubuntu

If you are using Ubuntu linux (17.04 or later), you can install webhook using sudo apt-get install webhook which will install community packaged version.

Debian

If you are using Debian linux ("stretch" or later), you can install webhook using sudo apt-get install webhook which will install community packaged version (thanks @freeekanayaka) from https://packages.debian.org/sid/webhook

Download prebuilt binaries

Prebuilt binaries for different architectures are available at GitHub Releases.

Configuration

Next step is to define some hooks you want webhook to serve. webhook supports JSON or YAML configuration files, but we'll focus primarily on JSON in the following example. Begin by creating an empty file named hooks.json. This file will contain an array of hooks the webhook will serve. Check Hook definition page to see the detailed description of what properties a hook can contain, and how to use them.

Let's define a simple hook named redeploy-webhook that will run a redeploy script located in /var/scripts/redeploy.sh. Make sure that your bash script has #!/bin/sh shebang on top.

Our hooks.json file will now look like this:

[
  {
    "id": "redeploy-webhook",
    "execute-command": "/var/scripts/redeploy.sh",
    "command-working-directory": "/var/webhook"
  }
]

NOTE: If you prefer YAML, the equivalent hooks.yaml file would be:

- id: redeploy-webhook
  execute-command: "/var/scripts/redeploy.sh"
  command-working-directory: "/var/webhook"

You can now run webhook using

$ /path/to/webhook -hooks hooks.json -verbose

It will start up on default port 9000 and will provide you with one HTTP endpoint

http://yourserver:9000/hooks/redeploy-webhook

Check webhook parameters page to see how to override the ip, port and other settings such as hook hotreload, verbose output, etc, when starting the webhook.

By performing a simple HTTP GET or POST request to that endpoint, your specified redeploy script would be executed. Neat!

However, hook defined like that could pose a security threat to your system, because anyone who knows your endpoint, can send a request and execute your command. To prevent that, you can use the "trigger-rule" property for your hook, to specify the exact circumstances under which the hook would be triggered. For example, you can use them to add a secret that you must supply as a parameter in order to successfully trigger the hook. Please check out the Hook rules page for detailed list of available rules and their usage.

Multipart Form Data

webhook provides limited support the parsing of multipart form data. Multipart form data can contain two types of parts: values and files. All form values are automatically added to the payload scope. Use the parse-parameters-as-json settings to parse a given value as JSON. All files are ignored unless they match one of the following criteria:

  1. The Content-Type header is application/json.
  2. The part is named in the parse-parameters-as-json setting.

In either case, the given file part will be parsed as JSON and added to the payload map.

Templates

webhook can parse the hooks configuration file as a Go template when given the -template CLI parameter. See the Templates page for more details on template usage.

Using HTTPS

webhook by default serves hooks using http. If you want webhook to serve secure content using https, you can use the -secure flag while starting webhook. Files containing a certificate and matching private key for the server must be provided using the -cert /path/to/cert.pem and -key /path/to/key.pem flags. If the certificate is signed by a certificate authority, the cert file should be the concatenation of the server's certificate followed by the CA's certificate.

TLS version and cipher suite selection flags are available from the command line. To list available cipher suites, use the -list-cipher-suites flag. The -tls-min-version flag can be used with -list-cipher-suites.

CORS Headers

If you want to set CORS headers, you can use the -header name=value flag while starting webhook to set the appropriate CORS headers that will be returned with each response.

Interested in running webhook inside of a Docker container?

You can use one of the following Docker images, or create your own (please read this discussion):

Examples

Check out Hook examples page for more complex examples of hooks.

Guides featuring webhook

Community Contributions

See the webhook-contrib repository for a collections of tools and helpers related to webhook that have been contributed by the webhook community.

Need help?

Check out existing issues to see if someone else also had the same problem, or open a new one.

Support active development

Sponsors

DigitalOcean

DigitalOcean is a simple and robust cloud computing platform, designed for developers.

BrowserStack

BrowserStack is a cloud-based cross-browser testing tool that enables developers to test their websites across various browsers on different operating systems and mobile devices, without requiring users to install virtual machines, devices or emulators.


Support this project by becoming a sponsor. Your logo will show up here with a link to your website.

By contributing

This project exists thanks to all the people who contribute. Contribute!.

By giving money


Thank you to all our backers!

License

The MIT License (MIT)

Copyright (c) 2015 Adnan Hajdarevic [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Owner
Adnan Hajdarević
Software engineer from Sarajevo, Bosnia & Herzegovina
Adnan Hajdarević
Comments
  • Too many open files

    Too many open files

    After a few hours of running I get "Too many open files" error, and webhook dies.

    OS: debian buster, Webhook installed from official apt sources

    ls -l /proc/11294/fd | wc -l result: 721 open socket: lrwx------ 1 root root 64 Apr 24 21:44 718 -> 'socket:[3390743]' lrwx------ 1 root root 64 Apr 24 21:44 719 -> 'socket:[3390857]'

    my conf:

    [
      {
        "id": "minio-webhook",
        "execute-command": "/root/webhook/rclone-sync.sh",
        "command-working-directory": "/root/webhook/",
        "pass-arguments-to-command":
        [
          {
                "source": "payload",
                "name": "Key"
          }
        ]
      }
    ]
    

    Any ideas how to fix it?

    thanks

  • fork/exec: exec format error (question)

    fork/exec: exec format error (question)

    Hi, I have following settings:

    [
      {
        "id": "redeploy-webhook",
        "execute-command": "/home/joseluis/test/hooks/redeploy.sh",
        "command-working-directory": "/home/joseluis/test",
        "response-message": "I got the payload!"
      }
    ]
    

    I request the hook:

    $ curl http://localhost:9000/hooks/redeploy-webhook
    I got the payload!
    

    On the terminal I got this error:

    $ webhook -hooks hooks.json -verbose 
    [webhook] 2015/12/06 16:58:02 version 2.3.6 starting
    [webhook] 2015/12/06 16:58:02 setting up os signal watcher
    [webhook] 2015/12/06 16:58:02 attempting to load hooks from hooks.json
    [webhook] 2015/12/06 16:58:02 loaded 1 hook(s) from file
    [webhook] 2015/12/06 16:58:02   > redeploy-webhook
    [webhook] 2015/12/06 16:58:02 os signal watcher ready
    [webhook] 2015/12/06 16:58:02 starting insecure (http) webhook on :9000
    [webhook] 2015/12/06 16:58:07 Started GET /hooks/redeploy-webhook
    [webhook] 2015/12/06 16:58:07 redeploy-webhook got matched (1 time(s))
    [webhook] 2015/12/06 16:58:07 redeploy-webhook hook triggered successfully
    [webhook] 2015/12/06 16:58:07 Completed 200 OK in 265.558µs
    [webhook] 2015/12/06 16:58:07 executing /home/joseluis/test/hooks/redeploy.sh 
    (/home/joseluis/test/hooks/redeploy.sh) with arguments 
    ["/home/joseluis/test/hooks/redeploy.sh"] and environment [] 
    using /home/joseluis/test as cwd
    [webhook] 2015/12/06 16:58:07 command output: 
    [webhook] 2015/12/06 16:58:07 error occurred: 
    fork/exec /home/joseluis/test/hooks/redeploy.sh: exec format error
    [webhook] 2015/12/06 16:58:07 finished handling redeploy-webhook
    

    My simple echo "Hello" command in redeploy.sh doesn't execute. What am I doing wrong?

  • webhook error

    webhook error

    Error "parsing JSON: couldn't retrieve argument for {Source:payload Name:payload}" work with BitBucket. before everything was good whats wrong?

    Thanks

  • gogs payload validation failed

    gogs payload validation failed

    I'm trying to use the webhook with Gogs (Go Git Server) and the payload validation is failing:

    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | [webhook] 2020/05/19 23:25:29 [c84770] incoming HTTP GET request from 172.22.0.1:52448
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | [webhook] 2020/05/19 23:25:29 [c84770] gogs got matched
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | [webhook] 2020/05/19 23:25:29 [c84770] error parsing JSON payload EOF
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | [webhook] 2020/05/19 23:25:29 [c84770] error evaluating hook: invalid payload signatures [76cda40505e58837211ee37fe7e8c819e31f33a1221a686fbebbe5829002ea01]
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] GET /hooks/gogs
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] Accept-Encoding: gzip
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] Content-Type: application/json
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] Referer: http://nixie.home.honig.net:18140//hooks/gogs
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] User-Agent: GogsServer
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] X-Github-Delivery: f45348ae-7fdf-4697-8230-45b07e55e056
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] X-Github-Event: push
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] X-Gogs-Delivery: f45348ae-7fdf-4697-8230-45b07e55e056
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] X-Gogs-Event: push
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] X-Gogs-Signature: 76cda40505e58837211ee37fe7e8c819e31f33a1221a686fbebbe5829002ea01
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | > [c84770] id:
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | < [c84770] Internal Server Error
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | < [c84770] Error occurred while evaluating hook rules.
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k |
    May 19 19:25:29 nixie docker-compose[3608844]: puppet_g10k | [webhook] 2020/05/19 23:25:29 [c84770] 500 | 43 B | 133.025µs | nixie.home.honig.net:18140 | GET /hooks/gogs
    

    I'm using a version of https://github.com/camptocamp/docker-g10k-webhook where I've upgraded to 2.7.0 and swapped -verbose for -debug to try to debug this.

    Now the funny thing is that I have python flask implementation of a hook that verifies the signatures that has been working with Gogs webhooks for a long time.

    The template file looks to be derrived from the example in the git repo:

    - id: gogs
      execute-command: /push-to-g10k.sh
      command-working-directory: /
      pass-arguments-to-command:
      - source: payload
        name: ref
      - source: payload
        name: repository.ssh_url
      trigger-rule:
        and:
          - match:
              type: payload-hash-sha256
              secret: "{{ getenv "HOOK_SECRET" | js }}"
              parameter:
                source: header
                name: X-Gogs-Signature
    

    I've verified that HOOK_SECRET in the environment is correct. I even replaced

    with

                    secret: FRED
    

    (which is the secret I'm using so that I can share stuff here).

    Any tips to help debug this?

    Gogs gives me the following information about the hook call:

    Request URL: http://nixie.home.honig.net:18140//hooks/gogs
    Request method: POST
    Content-Type: application/json
    X-Github-Delivery: 9a37cb8c-151c-4801-9f38-f722e93c85fa
    X-Github-Event: push
    X-Gogs-Delivery: 9a37cb8c-151c-4801-9f38-f722e93c85fa
    X-Gogs-Event: push
    X-Gogs-Signature: 76cda40505e58837211ee37fe7e8c819e31f33a1221a686fbebbe5829002ea01
    
    {
      "ref": "refs/heads/production",
      "before": "0d63846da1e52542b34ec1cd7f63598a42e4a9fe",
      "after": "0d63846da1e52542b34ec1cd7f63598a42e4a9fe",
      "compare_url": "",
      "commits": [
        {
          "id": "0d63846da1e52542b34ec1cd7f63598a42e4a9fe",
          "message": "fixup! Fix trim_ssd errors with FUSE% variables\n",
          "url": "https://git.home.honig.net/Sysadmin/puppet/commit/0d63846da1e52542b34ec1cd7f63598a42e4a9fe",
          "author": {
            "name": "Jeffrey C Honig",
            "email": "[email protected]",
            "username": "jch"
          },
          "committer": {
            "name": "Jeffrey C Honig",
            "email": "[email protected]",
            "username": "jch"
          },
          "added": null,
          "removed": null,
          "modified": [
            "site/profile/files/bin/trim_ssd"
          ],
          "timestamp": "0001-01-01T00:00:00Z"
        }
      ],
      "repository": {
        "id": 10,
        "owner": {
          "id": 3,
          "username": "Sysadmin",
          "login": "Sysadmin",
          "full_name": "Sysadmin repos",
          "email": "",
          "avatar_url": "https://git.home.honig.net/avatars/3"
        },
        "name": "puppet",
        "full_name": "Sysadmin/puppet",
        "description": "Server puppet configs",
        "private": true,
        "fork": false,
        "parent": null,
        "empty": false,
        "mirror": false,
        "size": 23244800,
        "html_url": "https://git.home.honig.net/Sysadmin/puppet",
        "ssh_url": "[email protected]:Sysadmin/puppet.git",
        "clone_url": "https://git.home.honig.net/Sysadmin/puppet.git",
        "website": "",
        "stars_count": 0,
        "forks_count": 0,
        "watchers_count": 2,
        "open_issues_count": 0,
        "default_branch": "production",
        "created_at": "2017-04-22T23:31:30Z",
        "updated_at": "2020-05-19T13:02:51Z"
      },
      "pusher": {
        "id": 1,
        "username": "jch",
        "login": "jch",
        "full_name": "Jeffrey Honig",
        "email": "[email protected]",
        "avatar_url": "https://secure.gravatar.com/avatar/b25e2ae1f07ec30647f346df81d2d841"
      },
      "sender": {
        "id": 1,
        "username": "jch",
        "login": "jch",
        "full_name": "Jeffrey Honig",
        "email": "[email protected]",
        "avatar_url": "https://secure.gravatar.com/avatar/b25e2ae1f07ec30647f346df81d2d841"
      }
    }
    

    Any other suggestions for debugging this?

    Thanks.

    Jeff

  • kubernetes + webhook + hotreload + error locating command

    kubernetes + webhook + hotreload + error locating command

    Hi everyone!

    I found a weird behavior that should works (at least it's working docker-compose and volumes) with kubernetes!

    I'm trying to have pods with webhook and be able to hot-reload the hooks and scripts. 😄

    With docker-compose and volumes, it's working but now I want to step up a little bit with kubernetes!

    In this issue, normally you'll have everything to reproduce it on a k8s cluster!

    So I got a simple setup with this manifest:

    Manifest:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: d-webhook
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: a-webhook
      template:
        metadata:
          labels:
            app: a-webhook
        spec:  
          containers:
          - name: webhook-development
            imagePullPolicy: Always
            image: dalongrong/almir-webhook-curl
            ports:
            - containerPort: 9000
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: s-webhook-development
    spec:
      type: LoadBalancer
      ports:
      - port: 9000
        targetPort: 9000
      selector:
        app: a-webhook
    
    

    And then, I copy scripts and hooks.yaml with kubectl

    You'll need the podname sooo:

    kubectl get pods -l app=a-webhook -o json | jq -r '.items[].metadata.name'

    With the name, you can replace "podname" with the correct name.

    Copy the scripts to the pod:

    kubectl cp ./scripts podname:/var/ podname

    Copy the hooks to the pod:

    kubectl cp ./hooks.yaml podname:/etc/webhook podname

    hooks.yaml

    -   id: ping
        execute-command: /var/scripts/ping.sh
        command-working-directory: ./
        response-message: pong
    

    scripts/ping.sh

    #!/bin/sh
    echo "pong"
    

    After you executed the two commands, you should have this:

    [webhook] 2020/09/15 16:56:59 caught HUP signal
    [webhook] 2020/09/15 16:56:59 attempting to reload hooks from /etc/webhook/hooks.yaml
    [webhook] 2020/09/15 16:56:59 found 1 hook(s) in file
    [webhook] 2020/09/15 16:56:59 	loaded: ping
    

    So, normally it should mean the hook is hot-reloaded and the scripts are located at /var/scripts

    If you bash in the pod, you can see the scripts!

    And then, you can try to trigger the webhook but first you need to expose the port:

    kubectl port-forward service/s-webhook-development 9000:9000 
    

    And then on your browser to make it simply, go to : http://localhost:9000/hooks/ping

    You should see "pong" BUT on the logs :

    [webhook] 2020/09/15 17:09:21 [c8acb1] incoming HTTP GET request from 127.0.0.1:60918
    [webhook] 2020/09/15 17:09:21 [c8acb1] ping got matched
    [webhook] 2020/09/15 17:09:21 [c8acb1] error parsing body payload due to unsupported content type header: 
    [webhook] 2020/09/15 17:09:21 [c8acb1] ping hook triggered successfully
    [webhook] 2020/09/15 17:09:21 [c8acb1] 200 | 4 B | 68.101µs | localhost:9000 | GET /hooks/ping
    [webhook] 2020/09/15 17:09:21 [c8acb1] error locating command: '/var/scripts/ping.sh'
    

    Thanks you for this amazing tool, can't wait to resolve this, I'm having a lot of fun!

    I hope I didn't forgot something, normally it should work on your side!

    Hope someone could help on this 😃

  • Running webhook inside docker container can't find command working directory

    Running webhook inside docker container can't find command working directory

    Running webhook inside a docker container with the following Dockerfile

    FROM almir/webhook
    RUN mkdir -p /var/scripts
    WORKDIR /var/scripts
    
    COPY ["update.sh", "hooks.json", "/var/scripts/"]
    RUN chmod +x /var/scripts/update.sh
    CMD ["-verbose", "-hotreload"]
    

    here is a copy of my hooks.json

    [
        {
          "id": "update-hook",
          "execute-command": "/var/scripts/update.sh",
          "command-working-directory": "/home/olatunji/Documents/workspaces/folder/",
          "pass-arguments-to-command":
        [
          {
            "source": "payload",
            "name": "[email protected]"
          }
        ]
         }
      ]
    

    and this is the output of my docker logs container-name

    [webhook] 2019/12/02 10:35:01 version 2.6.10 starting
    [webhook] 2019/12/02 10:35:01 setting up os signal watcher
    [webhook] 2019/12/02 10:35:01 attempting to load hooks from hooks.json
    [webhook] 2019/12/02 10:35:01 os signal watcher ready
    [webhook] 2019/12/02 10:35:01 found 1 hook(s) in file
    [webhook] 2019/12/02 10:35:01 	loaded: update-hook
    [webhook] 2019/12/02 10:35:01 setting up file watcher for hooks.json
    [webhook] 2019/12/02 10:35:01 serving hooks on http://0.0.0.0:9000/hooks/{id}
    [webhook] 2019/12/02 10:35:15 [a5a168] incoming HTTP request from 172.17.0.1:54662
    [webhook] 2019/12/02 10:35:15 [a5a168] update-hook got matched
    [webhook] 2019/12/02 10:35:15 [a5a168] update-hook hook triggered successfully
    [webhook] 2019/12/02 10:35:15 200 | 140.758µs | localhost:9000 | GET /hooks/update-hook 
    [webhook] 2019/12/02 10:35:15 [a5a168] error extracting command arguments: couldn't retrieve argument for {Source:payload Name:[email protected] EnvName: Base64Decode:false}
    [webhook] 2019/12/02 10:35:15 [a5a168] executing /var/scripts/update.sh (/var/scripts/update.sh) with arguments ["/var/scripts/update.sh" ""] and environment [] using /home/olatunji/Documents/workspaces/folder/ as cwd
    [webhook] 2019/12/02 10:35:15 [a5a168] command output: 
    [webhook] 2019/12/02 10:35:15 [a5a168] error occurred: chdir /home/olatunji/Documents/workspaces/folder: no such file or directory
    [webhook] 2019/12/02 10:35:15 [a5a168] finished handling update-hook
    
    

    steps to reproduce: Run webhook inside a docker container. using: https://github.com/adnanh/webhook-contrib/tree/master/docker

    am i supposed to mount the command working directory as a path in the docker file? please help. Thanks.

  • Add support for building snaps

    Add support for building snaps

    Hey Adnan,

    I've created this PR to request support for building a snap package of webhook.

    I read the guidelines, and I outlined all the technical steps needed to get this done. I ran the same set of tests you have on the GH page, and I had webhook running correctly.

    Basically, this PR shows how to build and run webhook as a snap.

    Overview

    • Snaps are cross-distro Linux software packages, supported on LTS and non-LTS Ubuntus many others distributions (Debian, Fedora, openSUSE, etc).
    • Snaps come with automatic updates.
    • Snaps are featured in the Snap Store (snapcraft.io/store), with audience of millions.
    • Snaps are standalone, isolated apps, so you fully control the release cycle.

    Build and test

    You can use:

    • local system with snapcraft command line tool <-- this PR covers this
    • build/CI tool/system of your choice
    • our online, free build service (build.snapcraft.io)

    Build locally

    Used Ubuntu 18.04 for this.

    snap install snapcraft --classic --beta git clone https://github.com/igorljubuncic/webhook.git cd webhook git checkout add-snapcraft snapcraft

    This command will generate a .snap file, something like webhook_1.0_amd64.snap.

    Install locally

    snap install webhook_1.0_amd64.snap --dangerous

    The --dangerous flag is necessary because the app (snap) hasn’t gone through the snap store review process and is not digitally signed.

    Run webhook

    snap run webhook

    Register dev account

    In the snap store at: https://snapcraft.io/account.

    Register webhook name in the store

    This is done on the command line with snapcraft:

    snapcraft login snapcraft register

    Upload/push webhook to the store

    snapcraft push webhook_1.0_amd64.snap --release edge

    We use release channels to denote risk, as follows:

    • edge, typically for git master
    • beta, beta testing
    • candidate
    • stable

    You can promote after testing and validation.

    Install from store for (a second) test

    snap install webhook --edge

    I think this covers it.

    Once you land the PR, we can help you with the promotion. Feel free to ask any questions you may have.

    Thanks!

  • Support multipart requests

    Support multipart requests

    Hello, at first, I am very happy to found this "webhook server" here. its working very well for some tests, BUT the main reason for searching a "webhook server" was that I would send webhooks from my plex media server to webhook server localy.

    It looks like the paypload coming from plex media server is malformed, for every hook there are something like this: [webhook] 2019/04/02 14:33:36 [f022a4] error parsing form payload invalid URL escape "%4\x92"

    But a 2nd webhook-entry in the plex media server configuration to webhook.site (Testing Website) looks good, there the payload received successfully.

    Has someone maybe also a plex media server and can test this issue?

    edit: here is the payload:

    {"event":"media.play","user":true,"owner":true,"Account":{"id":1,"thumb":"https://plex.tv/users/35a30735d350ab11/avatar?c=34253252","title":"plex@myserver"},"Server":{"title":"PLEXSERVER","uuid":"0c242342473962532jilk23432432523522"},"Player":{"local":true,"publicAddress":"55.26.29.89","title":"Firefox","uuid":"z9yrpwerwrwerrwtkb808ev"},"Metadata":{"librarySectionType":"show","ratingKey":"57828","key":"/library/metadata/57838","parentRatingKey":"53825","grandparentRatingKey":"27834","guid":"com.plexapp.agents.thetvdb://315122/1/3?lang=de","librarySectionTitle":"Serien","librarySectionID":21,"librarySectionKey":"/library/sections/21","type":"episode","title":"The Ex-Best Friend","titleSort":"TitleXXXX","grandparentKey":"/library/metadata/57224","parentKey":"/library/metadata/57825","grandparentTitle":"SeriennameXXX","parentTitle":"Season 1","contentRating":"Not Rated","summary":"Plot der Serie XXX. ","index":3,"parentIndex":1,"viewOffset":199000,"lastViewedAt":1554210778,"year":2015,"thumb":"/library/metadata/57828/thumb/1554121566","art":"/library/metadata/57824/art/1554121566","parentThumb":"/library/metadata/57825/thumb/1554121566","grandparentThumb":"/library/metadata/57824/thumb/1554121566","grandparentArt":"/library/metadata/57824/art/1554121566","originallyAvailableAt":"2015-10-21","addedAt":1552565597,"updatedAt":1554121566}}
    

    Best regards

  • Could someone familiar with hook rules, help me figure out how to parse this body?

    Could someone familiar with hook rules, help me figure out how to parse this body?

    I am trying to figure out how to parse the body of a webhook message sent from node-sonos-http-api and have a match to an ID in my hooks.json config that matches when my Kitchen Sonos player ("roomName":"Kitchen",) is PLAYING and another when it is STOPPED ("playbackState":"PLAYING"). Below is the raw body of the webhook message that I am needing to create two rules for under one ID in my hooks.json file because the node-sonos-http-api only can send to a single webhook server url. Ultimately, I need to have the execute command be variable and send a different url to IFTTT like https://maker.ifttt.com/trigger/Kitchen_Music_Off and another like https://maker.ifttt.com/trigger/Kitchen_Music_On. I am not sure how to pass variables from the hooks.json file to the scripts that executes a CURL to IFTTT.

    RAW BODY {"type":"transport-state","data":{"uuid":"RINCON_000E583A2E2401400","coordinator":"RINCON_000E583A2E2401400","roomName":"Kitchen","state":{"volume":22,"mute":false,"equalizer":{"bass":9,"treble":10,"loudness":true},"currentTrack":{"artist":"Taylor Swift","title":"...Ready For It?","album":"Reputation","albumArtUri":"/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429750%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2","duration":208,"uri":"x-sonos-http:ondemand_track%3a%3atra.290429750%7cv1%7cALBUM%7calb.290429749.mp4?sid=202&flags=8224&sn=2","type":"track","stationName":"","absoluteAlbumArtUri":"http://172.30.17.220:1400/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429750%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2"},"nextTrack":{"artist":"Taylor Swift","title":"End Game","album":"Reputation","albumArtUri":"/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429751%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2","duration":245,"uri":"x-sonos-http:ondemand_track%3a%3atra.290429751%7cv1%7cALBUM%7calb.290429749.mp4?sid=202&flags=8224&sn=2","absoluteAlbumArtUri":"http://172.30.17.220:1400/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429751%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2"},"trackNo":1,"elapsedTime":26,"elapsedTimeFormatted":"00:00:26","playbackState":"PLAYING","playMode":{"repeat":"none","shuffle":false,"crossfade":true}},"groupState":{"volume":22,"mute":false},"avTransportUri":"x-rincon-queue:RINCON_000E583A2E2401400#0","avTransportUriMetadata":""}} {"type":"transport-state","data":{"uuid":"RINCON_000E583A2E2401400","coordinator":"RINCON_000E583A2E2401400","roomName":"Kitchen","state":{"volume":22,"mute":false,"equalizer":{"bass":9,"treble":10,"loudness":true},"currentTrack":{"artist":"Taylor Swift","title":"...Ready For It?","album":"Reputation","albumArtUri":"/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429750%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2","duration":208,"uri":"x-sonos-http:ondemand_track%3a%3atra.290429750%7cv1%7cALBUM%7calb.290429749.mp4?sid=202&flags=8224&sn=2","type":"track","stationName":"","absoluteAlbumArtUri":"http://172.30.17.220:1400/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429750%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2"},"nextTrack":{"artist":"Taylor Swift","title":"End Game","album":"Reputation","albumArtUri":"/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429751%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2","duration":245,"uri":"x-sonos-http:ondemand_track%3a%3atra.290429751%7cv1%7cALBUM%7calb.290429749.mp4?sid=202&flags=8224&sn=2","absoluteAlbumArtUri":"http://172.30.17.220:1400/getaa?s=1&u=x-sonos-http%3aondemand_track%253a%253atra.290429751%257cv1%257cALBUM%257calb.290429749.mp4%3fsid%3d202%26flags%3d8224%26sn%3d2"},"trackNo":1,"elapsedTime":26,"elapsedTimeFormatted":"00:00:26","playbackState":"PLAYING","playMode":{"repeat":"none","shuffle":false,"crossfade":true}},"groupState":{"volume":22,"mute":false},"avTransportUri":"x-rincon-queue:RINCON_000E583A2E2401400#0","avTransportUriMetadata":""}}

    Just to get started, I have been tinkering with the following hooks.json file and cannot figure out how to get a simple match on the playingback state. Am I on the right track?

    [
    	{
    		"id": "sonos",
    		"execute-command": "/etc/webhook/kitchen_music_on.sh",
    		"response-message": "Ok ...",
    		"trigger-rule": {
    			"match": {
    				"type": "value",
    				"value": "PLAYING",
    				"parameter": {
    					"source": "payload",
    					"name": "playbackState"
    				}
    			}
    
    		}
    	}
    ]
    

    Any help would be much appreciated.

  • git pull doesn't work

    git pull doesn't work

    I have a very very basic script that will lead to something more complex. However I need to figure out what's going on first before continuing.

    #!/usr/bin/env bash
    
    cd /home/ubuntu/some/repo/here
    git pull origin master
    

    works just fine if i run it from the command line:

    server % ./git.sh                                                                                                                                
    From github.com:company/repo
     * branch            master     -> FETCH_HEAD
    Already up-to-date.
    

    If I try running this script in my webhook I get this:

    [webhook] 2017/07/17 19:22:17 2017-07-17T19:22:17Z | 200 | 	 156.653µs | server.aws.comapany.net:9000 | GET /hooks/git-test
    [webhook] 2017/07/17 19:22:17 executing /home/ubuntu/hooks/git.sh (/home/ubuntu/hooks/git.sh) with arguments ["/home/ubuntu/hooks/git.sh"] and environment [] using  as cwd
    [webhook] 2017/07/17 19:22:17 command output:
    [webhook] 2017/07/17 19:22:17 error occurred: exit status 1
    [webhook] 2017/07/17 19:22:17 finished handling git-test
    

    Any help at all would be great.

  • HELP! How to send parameters via webhook?

    HELP! How to send parameters via webhook?

    Good afternoon people,

    Could you help me add a variable input via the webhook?

    In the json file, I run a shell script that needs a variable as input, but I can't send this value via the webhook url.

    [
      {
        "id": "restart-service",
        "execute-command": "/tmp/monitoring/restart-service.sh",
        "response-message": "I got the payload!",
        "include-command-output-in-response": true,
            "trigger-rule":
            {
          "and":
          [
                {
              "match":
              {
                          "type": "ip-whitelist",
                          "ip-range": "127.0.0.1/32"
                      }
                    }
           ]
            }
      }
    ]
    
    #!/bin/sh
    servico=$1
    STS=`systemctl status $servico |grep Active: |grep running |wc -l`
    
    if [ $servico ! "" ]
    then
            echo "Servico nao definido" >> /tmp/monitoring/web_node.log
    else
    ...
    

    How could I send this necessary value for the script, through the webhook?

    Thank you in advance

  • Handling OPTIONS preflight requests

    Handling OPTIONS preflight requests

    Not an issue, but perhaps a question: having this config (see below) I'm trying to trigger a hook from the browser (using fetch), but before sending POST request it sends a standard preflight OPTIONS request and surely, it fails cause if I specify "http-methods": ["POST", "OPTIONS"] it triggers the script without parameters and with "http-methods": ["POST"] it responds with 404.

    One workaround would be to have the script echo OK when there's no ARGV (and that's what I'm doing now), but it'd be nice to have multiple handlers with the same id, but different http-methods to handle them separately, i.e. responding to OPTIONS straight away, without triggering the script, or having GET and POST on the same endpoint / id. Is there any recommended way to achieve this? Did I miss something in the docs?

    Thank you!

    [
      {
        "id": "script",
        "execute-command": "script.sh",
        "command-working-directory": "/Users/blah-blah/hooks",
        "include-command-output-in-response": true,
        "http-methods": ["POST"]
        "response-headers": [
          {
            "name": "Access-Control-Allow-Origin",
            "value": "*"
          }
        ],
        "pass-arguments-to-command":
        [
          {
            "source": "payload",
            "name": "some_param"
          },
        ]
      }
    ]
    
  • New webhook version 2.5.0-2 doesn't support many params

    New webhook version 2.5.0-2 doesn't support many params

    Hi,

    I have installed new webhook version which does not support many parameters to configure like (ex. -logfile, -setgid, -setuid) etc.

    Can somebody tell me how to setup above params? I need to run the script with my user and with all the logs file

    Here is the latest

    user@xxxx:~$ /usr/bin/webhook -help Usage of /usr/bin/webhook: -cert string path to the HTTPS certificate pem file (default "cert.pem") -header value response header to return, specified in format name=value, use multiple times to set multiple headers -hooks string path to the json file containing defined hooks the webhook should serve (default "hooks.json") -hotreload watch hooks file for changes and reload them automatically -ip string ip the webhook should serve hooks on (default "0.0.0.0") -key string path to the HTTPS certificate private key pem file (default "key.pem") -nopanic do not panic if hooks cannot be loaded when webhook is not running in verbose mode -port int port the webhook should serve hooks on (default 9000) -secure use HTTPS instead of HTTP -urlprefix string url prefix to use for served hooks (protocol://yourserver:port/PREFIX/:hook-id) (default "hooks") -verbose show verbose output

    Old version

    user@xxx:~$ /usr/bin/webhook -help Usage of /usr/bin/webhook: -cert string path to the HTTPS certificate pem file (default "cert.pem") -cipher-suites string comma-separated list of supported TLS cipher suites -debug show debug output -header value response header to return, specified in format name=value, use multiple times to set multiple headers -hooks value path to the json file containing defined hooks the webhook should serve, use multiple times to load from different files -hotreload watch hooks file for changes and reload them automatically -http-methods string set default allowed HTTP methods (ie. "POST"); separate methods with comma -ip string ip the webhook should serve hooks on (default "0.0.0.0") -key string path to the HTTPS certificate private key pem file (default "key.pem") -list-cipher-suites list available TLS cipher suites -logfile string send log output to a file; implicitly enables verbose logging -max-multipart-mem int maximum memory in bytes for parsing multipart form data before disk caching (default 1048576) -nopanic do not panic if hooks cannot be loaded when webhook is not running in verbose mode -pidfile string create PID file at the given path -port int port the webhook should serve hooks on (default 9000) -secure use HTTPS instead of HTTP -setgid int set group ID after opening listening port; must be used with setuid -setuid int set user ID after opening listening port; must be used with setgid -template parse hooks file as a Go template -tls-min-version string minimum TLS version (1.0, 1.1, 1.2, 1.3) (default "1.2") -urlprefix string url prefix to use for served hooks (protocol://yourserver:port/PREFIX/:hook-id) (default "hooks") -verbose show verbose output -version display webhook version and quit -x-request-id use X-Request-Id header, if present, as request ID -x-request-id-limit int truncate X-Request-Id header to limit; default no limit

    Thanks,

  • "entire-payload" unmarshal array

    Hello everyone,

    After further investigation I changed my question. I'm using "entire-payload" in my webhook.conf in order to save any incoming request from SendGrid.

    [
            {
            "id": "sendgrid",
            "execute-command": "echo",
            "pass-arguments-to-command":
    [
            {
            "source": "entire-headers"
            },
            {
            "source": "entire-payload"
            }
    ]
            }
    ]
    

    But I receive 'error parsing JSON payload json: cannot unmarshal array into Go value of type map[string]interface {}' so the result is null.

    What am I doing wrong?

    Raw content which I should see is something like this:

    [
      {
        "email": "[email protected]",
        "event": "delivered",
        "ip": "208.117.55.133",
        "response": "250 2.0.0 Ok: queued as 02E07303458",
        "sg_event_id": "ZGVsaXZlcmVdAtMTk0NzA4MTEtT1d0eFQ0dG9SWnFwX1EybGV1WXJTUS0w",
        "sg_message_id": "OWtxT4toRZqp_Q2leuYrSQ.filterdrecv-8569859b9-kd4gr-1-63A17998-5F.0",
        "smtp-id": "<OWtxT4toRZqp_Q2leuYrSQ@geopod-ismtpd-4-0>",
        "timestamp": 1671526816,
        "tls": 1
      }
    ]
    
  • Unexpected behavior when webhook started @reboot from crontab

    Unexpected behavior when webhook started @reboot from crontab

    I have a weird issue when trying to automate webhook startup as part of my CI/CD workflow. Currently when webhook is started from the root crontab with either of the following options it starts and listens normally, but responds with HTTP 404 (message: Hook not found)

    @reboot sudo webhook -hooks /home/ubuntu/hooks.json -hotreload &

    @reboot sleep 120 && sudo webhook -hooks /home/ubuntu/hooks.json -hotreload &

    When I run the exact same command manually, webhook handles the requests normally, an HTTP 200 code and the message set in the hooks.json file is received. Seems to me that when webhook is started from crontab @reboot it has no access to the hooks.json file, even though it has access right set correctly. I tried adding a time delay for starting to maybe wait for the full boot process to finish but it does not change the outcome. Changing the hooks.json on the fly has no effect either when started from crontab, but I can see the change when webhook is run manually, so the hotreload works in that case.

    Any idea what causes this behavior?

  • Webhook not executing my deploy.sh script

    Webhook not executing my deploy.sh script

    Hey there, having some issues with webhook executing my deploy.sh script, i get a 200 as response but the script isnt executed. (I can see that since when I make some changes to my app, I have to manually run the script. I'll paste my scrips and files here so you can see them. I did check other similar threads but those didn't help me.

    hooks.json file:

    [
      {
        "id": "autodeploy",
        "execute-command": "/home/ubuntu/datadrill-infra-apps/deliverko/staging/deploy.sh",
        "command-working-directory": "/home/ubuntu/datadrill-infra-apps/deliverko/staging/",
        "response-message": "Executing deploy script..."
      }
    ]
    

    webhook.service file:

    [Unit]
    Description=Webhooks
    
    [Service]
    ExecStart=/usr/bin/webhook -hooks /home/ubuntu/datadrill-infra-apps/deliverko/staging/webhooks/hooks.json -hotreload
    
    [Install]
    WantedBy=multi-user.target
    

    deploy.sh:

    #!/bin/bash
    
    sudo docker compose pull
    sudo docker compose -f docker-compose.yml --env-file .env down
    sudo docker compose -f docker-compose.yml --env-file .env up -d
    

    ngnix.conf: (It's not a whole file, just copied the line that I added for webhook, these lines are under server { )

    location /hooks/ {
    			proxy_pass http://127.0.0.1:9000/hooks/;
    	    }
    
    

    Output of systemctl status webhook.service: image

    Any ideas what else can I try?

  • trying to use YAML

    trying to use YAML

    i am trying to use a hooks.yaml file instead of hooks.json but i am getting the error when loading the webhook

    [webhook] 2022/11/23 11:12:32 version 2.8.0 starting [webhook] 2022/11/23 11:12:32 setting up os signal watcher [webhook] 2022/11/23 11:12:32 attempting to load hooks from hook3.yaml [webhook] 2022/11/23 11:12:32 os signal watcher ready [webhook] 2022/11/23 11:12:32 couldn't load hooks from file! error unmarshaling JSON: json: cannot unmarshal object into Go value of type hook.Hooks [webhook] 2022/11/23 11:12:32 serving hooks on https://0.0.0.0:9000/hooks/{id} [webhook] 2022/11/23 11:17:32 [6a2470] incoming HTTP POST request from 172.17.12.16:33957 [webhook] 2022/11/23 11:17:32 [6a2470] 404 | 15 B | 51.874µs | 172.27.27.4:9000 | POST /hooks/testing_start

    What am I doing wrong?

Webhook-server - Webhook Server for KubeDB resources

webhook-server Webhook Server for KubeDB resources Installation To install KubeD

Feb 22, 2022
A k8s vault webhook is a Kubernetes webhook that can inject secrets into Kubernetes resources by connecting to multiple secret managers
A k8s vault webhook is a Kubernetes webhook that can inject secrets into Kubernetes resources by connecting to multiple secret managers

k8s-vault-webhook is a Kubernetes admission webhook which listen for the events related to Kubernetes resources for injecting secret directly from sec

Oct 15, 2022
Kubernetes webhook development (validating admission webhook) tutorial using kubewebhook

pod-exec-guard-kubewebhook-tutorial Introduction This is a tutorial that shows how to develop a Kubernetes admission webhook. To explain this, the tut

Aug 26, 2022
Tcpdump-webhook - Toy Sidecar Injection with Mutating Webhook

tcpdump-webhook A simple demonstration of Kubernetes Mutating Webhooks. Injects

Feb 8, 2022
Execute multiple shell commands like Docker-Compose

parx parx is a simple tool to run multiple commands in parallel while having the output structured like Docker Compose does that. This is useful when

Aug 15, 2022
Go package exposing a simple interface for executing commands, enabling easy mocking and wrapping of executed commands.

go-runner Go package exposing a simple interface for executing commands, enabling easy mocking and wrapping of executed commands. The Runner interface

Oct 18, 2022
`runenv` create gcloud run deploy `--set-env-vars=` option and export shell environment from yaml file.

runenv runenv create gcloud run deploy --set-env-vars= option and export shell environment from yaml file. Motivation I want to manage Cloud Run envir

Feb 10, 2022
Kubectl plugin to run curl commands against kubernetes pods

kubectl-curl Kubectl plugin to run curl commands against kubernetes pods Motivation Sending http requests to kubernetes pods is unnecessarily complica

Dec 22, 2022
Prestic - Lets you define and run restic commands from a YAML file

Pete's Restic Lets you define and run restic commands from a YAML file. Features

Jan 10, 2022
Witty - An unsafe web server to export shell to web
Witty - An unsafe web server to export shell to web

WiTTY: Web-based interactive TTY This program allows you to use terminal in the

Dec 30, 2022
🔑 Kubernetes Authentication & Authorization WebHook Server
🔑 Kubernetes Authentication & Authorization WebHook Server

Guard Guard by AppsCode is a Kubernetes Webhook Authentication server. Using guard, you can log into your Kubernetes cluster using various auth provid

Dec 16, 2022
Run VS Code on any server over SSH.
Run VS Code on any server over SSH.

sshcode This project has been deprecated in favour of the code-server install script See the discussion in #185 sshcode is a CLI to automatically inst

Dec 25, 2022
ginko-volkswagen detects when your tests are being run in a CI server, and reports them as passing

detects when your ginkgo-based tests are being run in a CI server, and reports them as passing

Dec 4, 2021
Lightweight but fully-capable WebTransport server for Go

webtransport-go This package provides a lightweight WebTransport-over-HTTP/3 server implementation in Go. What is WebTransport? WebTransport (https://

Dec 31, 2022
Shell script to download and set GO environmental paths to allow multiple versions.
Shell script to download and set GO environmental paths to allow multiple versions.

gobrew gobrew lets you easily switch between multiple versions of go. It is based on rbenv and pyenv. Installation The automatic installer You can ins

Nov 3, 2022
Making it easy to write shell-like scripts in Go
Making it easy to write shell-like scripts in Go

import github.com/bitfield/script What is script? script is a Go library for doing the kind of tasks that shell scripts are good at: reading files, ex

Jan 9, 2023
Go version manager. Super simple tool to install and manage Go versions. Install go without root. Gobrew doesn't require shell rehash.

gobrew Go version manager Install or update With curl $ curl -sLk https://git.io/gobrew | sh - or with go $ go get -u github.com/kevincobain2000/gobre

Jan 5, 2023
Censors or hides shell / Bash / console output based on defined patterns - great for hiding secrets in demos!
Censors or hides shell / Bash / console output based on defined patterns - great for hiding secrets in demos!

censor-shell Installation go install Usage Make the file ~/.censor-shell as an INI file with the following content: [nameofmyreplacement] pattern = b

Nov 11, 2022
Github Cloud Shell
Github Cloud Shell

GitHub Shell ghsh (or Github shell) is a command line tool available for windows, linux and macos that lets you use github as a shell. It is not anoth

May 11, 2022