Incident response · Event-Driven Ansible · Rundeck · StackStorm

Run remediation inside your network without exposing your automation

PagerDuty, Grafana and Alertmanager post their alerts to one public Webhook Relay URL. A relay agent next to your automation connects out and delivers each one to Event-Driven Ansible, Rundeck or StackStorm, so remediation starts automatically. The tools that can restart services and change config never get a public address.

Free plan · No credit card · SOC 2 Type II · Self-hosted option

Buying for a company? Talk to sales

One public URL in. One outbound connection out. Nothing else exposed.

Safe on company infrastructure

  • Outbound only

    The agent or operator connects out over TLS. No inbound port, no public IP.

  • Encrypted and scoped

    AES-256 at rest. Ephemeral buckets store no bodies or headers at all.

    Data handling →

  • Verified before forwarding

    Signatures checked and source IPs allowlisted on the input, so forged requests never reach you.

    Signatures →IP allowlist →

  • SOC 2 Type II

    Independently audited controls, SSO and audit logs.

    Security review kit →

Automation that can fix things can break things

A listener that runs playbooks is the most valuable endpoint an attacker could find. Keep it private.

Exposing your automation to alerting SaaS

  • Publish a webhook listener on a host that can run playbooks
  • Allow-list the alerting vendor's source addresses
  • Lose the trigger if the listener is restarting
  • Explain to security why automation is on the internet

With Webhook Relay

  • The agent makes one outbound connection
  • Automation hosts stay unreachable from outside
  • Signatures checked before anything runs
  • Every trigger logged and retried for up to 30 days

No public trigger endpoint

The relay agent connects out. The Event-Driven Ansible, Rundeck or StackStorm listener only ever receives deliveries from inside your network.

Only signed alerts run

Verify PagerDuty's X-PagerDuty-Signature in a function, or use basic auth on the input for Grafana and Alertmanager. Anything else is stopped before forwarding.

An audit trail for every run

Each alert is logged with the response your automation returned, so "what triggered this restart?" has an answer.

From the alerting you already use

Anything that can POST to an HTTPS URL when an alert fires:

  • PagerDuty

    V3 webhook subscriptions for incident events, signed with X-PagerDuty-Signature.

  • Grafana alerting

    A webhook contact point, with basic auth or an authorization header.

  • Prometheus Alertmanager

    A webhook_config receiver, with http_config credentials.

  • Datadog, Opsgenie and others

    Any monitor or on-call tool with a webhook notification.

Into the automation you run

Point the bucket's output at the listener's internal address.

  • Event-Driven Ansible

    The ansible.eda.webhook event source in your rulebook, matched to playbooks by conditions.

    http://eda.internal:5000/endpoint
  • Rundeck

    A Rundeck webhook that runs a job with the alert as options.

    http://rundeck.internal:4440/api/<version>/webhook/<token>
  • StackStorm

    A webhook trigger feeding your rules and workflows.

    http://st2.internal/api/v1/webhooks/<trigger>
  • Your own script

    Any internal HTTP service: a small handler that restarts a service or opens a ticket.

    http://ops-bot.internal:8080/alerts

Signature verification

Only signed alerts trigger a runbook

A Webhook Relay function runs on the input, before forwarding. This one verifies PagerDuty's X-PagerDuty-Signature (a single v1= signature). A forged alert gets a 401 and nothing runs.

How signature verification works
function (Lua) · runs before forwarding
local crypto = require('crypto')

-- Reject anything that isn't signed with your shared secret,
-- before it is forwarded into your network.
local sig, err = crypto.hmac('sha256', r.RequestBody, cfg:GetValue("WEBHOOK_SECRET"))
if err then error(err) end

if "v1=" .. sig ~= r.RequestHeader["X-PagerDuty-Signature"] then
  r:SetResponseStatusCode(401)
  r:SetResponseBody("invalid signature")
  r:StopForwarding()
  return
end

Set up in three steps

One agent on a host that can reach your automation. No inbound rule, no public IP.

  1. 1

    Run the agent next to your automation

    Install the relay CLI (or the Docker image) on a host that can reach the listener, with an access token scoped to this bucket.

    shell
    relay login -k $RELAY_KEY -s $RELAY_SECRET
    relay forward --bucket incident-automation \
      http://eda.internal:5000/endpoint
  2. 2

    Verify the alert source

    Attach the signature-checking function to the input, or enable basic auth on it and use the same credentials in Grafana or Alertmanager.

  3. 3

    Point your alerting at the URL

    Add the bucket's public URL as a PagerDuty webhook subscription, a Grafana contact point or an Alertmanager receiver. Fire a test alert and watch it in the bucket logs.

Start free, or buy through procurement

Try it on one pipeline

Free$0
150 webhooks a month, enough for a test alert route
Business$79.99/mo
60,000 webhooks a month, long log retention, priority support

7-day money-back guarantee on paid plans.

Buying for a company?

  • Annual plans paid by invoice and purchase order
  • Help with your security review
  • Vendor onboarding paperwork

Questions

Do I need to expose Event-Driven Ansible or Rundeck to receive PagerDuty webhooks?

No. A relay agent inside your network opens an outbound connection to Webhook Relay. PagerDuty posts to the public Webhook Relay URL and the agent delivers each event to your listener's internal address.

How do I make sure only real alerts run playbooks?

Attach a function to the input that verifies PagerDuty's X-PagerDuty-Signature HMAC and stops forwarding when it doesn't match. For Grafana and Alertmanager, enable basic auth on the input and set the same credentials on the contact point or receiver.

Do responses from my automation go back to PagerDuty?

Not by default. Forwarding is one-way: the sender gets Webhook Relay's response, and your listener's response is only recorded in the bucket logs. That keeps internal details out of the alerting vendor.

What if the listener is restarting when an alert fires?

Webhook Relay stores the alert and the sender gets a success response. With durable delivery it is retried for up to 30 days, and any delivery can be replayed from the logs.

More security pages: Security alerts into an on-prem SIEM · GitOps webhooks into a private cluster · Security review kit

Let your next alert fix itself

Run one agent, verify the sender, paste one URL into your alerting. Your automation stays private.

Free plan · No credit card required · 7-day money-back guarantee on paid plans