Skip to content

Webhooks

ordyn-webhooks lets external systems trigger Ordyn jobs through HTTP webhooks.

The webhook service receives public HTTP requests, normalizes them, authenticates them according to each webhook definition, and forwards events to Ordyn.

Use webhooks when another application should start an Ordyn job for a known endpoint, for example:

  • a monitoring system detects a condition and asks Ordyn to remediate the affected machine
  • a deployment platform notifies Ordyn after an infrastructure change
  • a company portal starts a controlled endpoint action without giving the caller direct Ordyn server access
  • another automation tool passes structured data into an Ordyn job

Webhooks are available in Administration > Services on the Webhooks tab.

How it works

At a high level:

  1. An admin creates a webhook service client in Ordyn.
  2. An admin issues a service-client enrollment token scoped to that webhook service client.
  3. The ordyn-webhooks service enrolls through the configured edge service by using the scoped token once.
  4. Ordyn publishes signed runtime webhook configuration to the connected service client.
  5. External systems call the public webhook URL.
  6. The webhook service validates the request and forwards a signed normalized event to Ordyn.
  7. Ordyn stores the webhook event and starts matching endpoint trigger rules.

The webhook service accepts public ingress traffic. It does not require external callers to reach the Ordyn server directly.

The service-client control path uses edge:

  • the webhook service connects outward to edge for enrollment and runtime messages
  • Ordyn sends runtime configuration
  • received webhook events are sent back through the same service-client channel

Service clients

A webhook service client represents one running ordyn-webhooks instance.

Create it in Administration > Services on the Webhooks tab by selecting Create client.

The service client needs:

  • name
  • edge service
  • public base URL
  • enabled state

The public base URL is the externally reachable base address for that webhook service, for example:

text
https://ordyn-webhooks.example.com

Ordyn uses this value to display the full URL for each webhook. The service accepts webhook calls under:

text
<public base URL>/v1/hooks/<webhook slug>

After creating a service client, issue a service-client enrollment token for it from the enrollment tokens page. Run the service enrollment command with that token. The command stores the service-client certificate state on disk, and the token is only needed for that enrollment.

Each webhook service client has a detail page that shows connection state, version, current certificate serial, certificate expiration, enrollment timestamps, and the configured public base URL. Admins can enable or disable the service client and revoke the current certificate from the detail page. A revoked certificate requires the service client to enroll again before it can connect. See service-client certificate lifetime and renewal for the renewal workflow.

Runtime configuration

The service needs these values at runtime:

Environment variablePurpose
ORDYN_WEBHOOK_EDGE_HOSTEdge host used for service-client enrollment and the service-client websocket.
ORDYN_WEBHOOK_SERVICE_CLIENT_IDThe service client ID from Ordyn.
ORDYN_WEBHOOK_PUBLIC_BASE_URLPublic base URL shown in Ordyn for webhook URLs.

Start the service, then enroll it after configuring those values:

bash
docker compose exec webhooks node dist/index.js enroll

For install answer file setup, pipe the enrollment token into the command:

bash
printf '%s' '<enrollment-token>' | docker compose exec -T webhooks node dist/index.js enroll --token-stdin

Common optional values:

Environment variablePurpose
ORDYN_WEBHOOK_STATE_PATHPersistent enrollment state file. Defaults to /data/service-client-state.json.
ORDYN_WEBHOOK_BODY_LIMITMaximum accepted request body size.
ORDYN_RUNTIME_LOG_DIRDirectory for service runtime logs.
ORDYN_RUNTIME_LOG_RETENTION_DAYSRetention for logs written by the service.
PORTHTTP listen port inside the service container.

Backend webhook event retention is configured separately:

Environment variablePurpose
ORDYN_WEBHOOK_EVENT_RETENTION_DAYSNumber of days to keep stored webhook event payloads in Ordyn. Defaults to 30. Set to 0 or lower to disable pruning.

Keep the state path on persistent storage. If the state file is removed, the service must enroll again.

Installation

Prerequisites:

Checkout the webhook deployment folder from the Ordyn compose repository:

bash
if [ ! -d /opt/ordyn-compose/.git ]; then
  git clone --filter=blob:none --sparse https://github.com/ordyn-project/compose.git /opt/ordyn-compose
fi
cd /opt/ordyn-compose
git sparse-checkout add webhooks

Create the environment file:

bash
cd /opt/ordyn-compose/webhooks
cp .env.example .env

Set these values in .env:

dotenv
SERVICE_DOMAIN=ordyn-webhooks.example.com
ORDYN_WEBHOOK_EDGE_HOST=ordyn-edge.example.com
ORDYN_WEBHOOK_SERVICE_CLIENT_ID=<service-client-id>
ORDYN_WEBHOOK_PUBLIC_BASE_URL=https://ordyn-webhooks.example.com

Start the service:

bash
docker compose pull
python3 /opt/cosign-docker-verify/verify.py

Continue with docker compose up -d only when the webhook image verifies successfully and no failed verification message appears.

bash
docker compose up -d

Issue a service-client enrollment token for the webhook service client in Ordyn. Enroll the service once:

bash
printf '%s' '<enrollment-token>' | docker compose exec -T webhooks node dist/index.js enroll --token-stdin

The webhook service needs public HTTPS ingress for /v1/hooks/. The provided compose file routes that path through Traefik.

Public ingress

The service exposes incoming webhook calls at:

text
/v1/hooks/:slug

The slug is generated by Ordyn when the webhook is created. It is part of the copied webhook URL.

Only that ingress path needs to be publicly reachable. Service-client enrollment and control traffic are outbound from the webhook service to edge.

Source-IP authentication uses caller addresses forwarded by Traefik.

Configure rate limiting on public webhook routes when a webhook endpoint is exposed to untrusted networks or high-volume callers.

Webhook definitions

A webhook definition belongs to one webhook service client and one approved endpoint.

Create it in Administration > Services on the Webhooks tab by selecting Create webhook.

A webhook has:

  • service client
  • endpoint
  • name
  • allowed HTTP methods
  • authentication mode
  • optional source IP allowlist
  • optional job variable mappings
  • enabled state

The endpoint binding is part of the webhook definition. A received webhook can start jobs for the configured endpoint. Endpoint selection from the incoming payload is not part of this workflow.

Disabled webhooks are not accepted by the ingress service and do not trigger jobs.

Allowed methods

Each webhook can allow one or more HTTP methods:

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE

The default method is POST.

If a request uses a method that is not allowed, the service rejects it before forwarding an event to Ordyn.

Authentication

Webhook authentication is configured per webhook definition.

Supported modes:

ModeBehavior
UnauthenticatedNo token is required. Use only for trusted networks or low-risk integrations.
Bearer tokenThe caller sends Authorization: Bearer <token>.
Header tokenThe caller sends the token in the configured header, for example X-Ordyn-Webhook-Token.
Source IP allowlistThe caller source IP must match one configured IP address or CIDR range.

Bearer-token and header-token values are hashed before they are stored in Ordyn. Tokens are not shown again after saving.

Source IP allowlists support individual IP addresses and CIDR ranges, for example:

text
203.0.113.10
203.0.113.0/24
2001:db8::/32

Source-IP checks use the caller address forwarded by Traefik.

Request payloads

The webhook service stores and forwards a normalized request shape.

It records:

  • webhook ID and slug
  • receive timestamp
  • HTTP method
  • source IP
  • content type
  • sanitized headers
  • query parameters
  • parsed body
  • raw body

JSON request bodies are parsed as JSON. application/x-www-form-urlencoded bodies are parsed into fields. Other body types are forwarded as text in the normalized request.

Sensitive caller tokens are used for authentication and should not be treated as job input.

Job trigger rules

Webhook-triggered jobs are configured from the endpoint's automation or trigger area.

Create a job trigger rule with:

  • event Webhook received
  • the webhook definition to match
  • the job to run
  • optional maximum random delay

Webhook trigger rules apply to endpoint scopes. The rule matches only when:

  • the webhook definition is active
  • the webhook's endpoint is approved
  • the rule is enabled
  • the rule is attached to the same endpoint
  • the rule references the received webhook definition

When multiple matching rules exist for the endpoint, Ordyn evaluates them in their configured order. The optional random delay can spread bursts when an external system sends many events.

Job variables

Triggered jobs receive webhook trigger details under:

text
trigger.webhook

The run also has trigger.type set to webhook_received and trigger.source set to webhook. See Variables for the full trigger field list.

Webhook definitions can also map selected request values to short job variables under:

text
webhook.<name>

For example, a mapping with:

NamePath
build_idbody.build.id

makes the value available as:

text
{{ webhook.build_id }}

Mapping paths are evaluated against the normalized request, so useful prefixes are usually:

  • body
  • query
  • headers
  • source_ip
  • method
  • content_type

Use mappings for values that job authors should consume directly. Use trigger.webhook.* when a job needs the full request context.

Example

An external system sends:

bash
curl -X POST \
  https://ordyn-webhooks.example.com/v1/hooks/3d72... \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  --data '{"build":{"id":"2026.06.25.1"},"action":"restart-service"}'

With a variable mapping:

NamePath
build_idbody.build.id
actionbody.action

the triggered job can use:

text
{{ webhook.build_id }}
{{ webhook.action }}
{{ trigger.webhook.source_ip }}

Events and diagnostics

Ordyn stores each received webhook event with the normalized request, mapped variables, matching trigger rules, dispatched trigger rules, and any dispatch error.

Webhook events are retained for 30 days by default. Ordyn removes events outside the retention window according to ORDYN_WEBHOOK_EVENT_RETENTION_DAYS.

The webhook definition shows the last receive timestamp and last error. Common last-error causes are:

  • the webhook's endpoint is not approved
  • no enabled trigger rule matched the webhook and endpoint
  • the webhook was received while the definition was inactive

Service-client connection state is shown on the Webhooks page. It includes connection status, version, certificate serial, last enrollment, last connection, last seen time, and last error.

Support bundles

Webhook service clients participate in service-client log bundles.

Use support bundles when troubleshooting:

  • webhook service enrollment problems
  • service-client connection loss
  • runtime configuration not reaching the service
  • received requests not triggering jobs
  • authentication failures reported by the webhook service

Select the webhook service client as a log source when creating a service-client log bundle.

Security recommendations

Use token authentication or source-IP allowlists for production webhooks.

Prefer:

  • HTTPS on public webhook routes
  • long random bearer or header tokens
  • source-IP allowlists when the caller has stable egress addresses
  • one webhook per integration purpose
  • narrow job trigger rules on the intended endpoint
  • mapped variables for the specific fields a job needs

Avoid:

  • unauthenticated public webhooks
  • passing secrets in request bodies unless the job genuinely requires them
  • using a shared webhook for unrelated external systems
  • exposing service-client control paths publicly

Limitations

Webhook definitions are endpoint-bound.

Limitations:

  • a webhook definition targets one approved endpoint
  • endpoint selection is not extracted from the incoming payload
  • webhook trigger rules are endpoint-scope rules
  • authentication is per webhook definition, not per trigger rule
  • request bodies are normalized for job input, but Ordyn does not transform arbitrary payload formats beyond JSON and form parsing

Use variable mappings to adapt different caller payload shapes into stable job variables.