Skip to main content

Event Webhooks Reference

Event webhooks deliver HTTP POST notifications when registry operations occur.


Configuration

Webhooks are defined in the [event_webhook.<name>] section of the configuration file.

Webhook Definition (event_webhook.<name>)

OptionTypeDefaultDescription
urlstringrequiredHTTP/HTTPS endpoint URL
policystringrequiredDelivery policy: required, optional, async
events[string]requiredEvent types to deliver (at least one)
tokenstring-Bearer token and HMAC signing secret
timeout_msu645000HTTP request timeout in milliseconds
max_retriesu320Maximum retry attempts after initial failure
repository_filter[string]-Regex patterns to match repository names

Webhook References

Webhooks are enabled by referencing their names in global or repository configuration:

LocationOptionTypeDescription
globalevent_webhooks[string]Webhook names for all repositories
repository."<namespace>"event_webhooks[string]Webhook names for this repository

Delivery Policies

PolicyBehavior
requiredSynchronous. Waits for response. Non-2xx or network failure fails the client operation.
optionalSynchronous. Waits for response. Failure is logged but does not affect the client.
asyncAsynchronous. Dispatched in background. Client receives response immediately.

Retry Behavior

Retries apply to required, optional, and async policies when max_retries > 0.

Backoff formula: 100ms * 2^(attempt - 1)

max_retriesTotal attemptsDelays
01-
12100ms
23100ms, 200ms
34100ms, 200ms, 400ms

Event Types

EventTrigger
manifest.pushManifest stored successfully
manifest.deleteManifest deleted
blob.pushBlob upload completed
tag.createTag created (part of manifest push with tag ref)
tag.deleteTag deleted (part of manifest delete by tag)

Event Payload

Events are delivered as JSON via HTTP POST.

Schema

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2025-01-15T10:30:00.123456Z",
"kind": "manifest.push",
"namespace": "library/nginx",
"repository": "docker-hub",
"digest": "sha256:abc123def456...",
"reference": "sha256:abc123def456...",
"tag": "latest",
"actor": {
"id": "user-123",
"username": "alice",
"client_ip": "192.168.1.100"
}
}

Fields

FieldTypeAlways presentDescription
idstringyesUnique event ID (UUID v4)
timestampstringyesISO 8601 timestamp (UTC)
kindstringyesEvent type (see Event Types)
namespacestringyesImage namespace (e.g., library/nginx)
repositorystringyesRepository name
digeststringnoContent digest (sha256/sha512)
referencestringnoTag or digest reference used in the request
tagstringnoTag name (present for tag operations)
actorobjectnoClient identity (present when authenticated)

Actor Fields

FieldTypeDescription
idstringIdentity identifier
usernamestringBasic auth or OIDC subject
client_ipstringClient IP address

All actor fields are optional and omitted when not available.


HTTP Request

Method

POST

Headers

HeaderAlways sentDescription
Content-Typeyesapplication/json
X-Registry-EventyesEvent type (e.g., manifest.push)
Authorizationwhen token setBearer <token>
X-Registry-Signature-256when token setsha256=<hmac-hex-digest>

HMAC Signature

When token is configured, the payload is signed with HMAC-SHA256:

  • Algorithm: HMAC-SHA256
  • Key: The token value (UTF-8 encoded)
  • Message: The raw JSON request body
  • Format: sha256= followed by the hex-encoded digest

The signature is sent in the X-Registry-Signature-256 header.

Test vector:

HMAC-SHA256("test-secret", "hello world")
= 046e2496e13e0bfd8dbef84244dd188311a48086646355161bc4ad0769a49cf4

Header value: sha256=046e2496e13e0bfd8dbef84244dd188311a48086646355161bc4ad0769a49cf4

Response

Any 2xx status code is considered success. All other status codes are treated as failure.


Repository Filters

When repository_filter is set, events are only delivered if the event's repository name matches at least one regex pattern. Patterns use Rust regex syntax.

PatternMatches
^production/.*production/api, production/web
^library/.*library/nginx, library/redis.
.*Everything

Without repository_filter, all repositories match.


Metrics

event_webhook_deliveries_total

Total event webhook delivery attempts.

TypeLabels
Counterwebhook, event, result

Labels:

  • webhook: Webhook name from configuration
  • event: Event type (e.g., manifest.push)
  • result: success or error

event_webhook_delivery_duration_seconds

Event webhook delivery duration.

TypeLabels
Histogramwebhook, event

Labels:

  • webhook: Webhook name from configuration
  • event: Event type (e.g., manifest.push)

Validation

The following conditions are validated at configuration load time:

  • url must be a valid URI
  • events must contain at least one event type
  • repository_filter patterns must be valid regex
  • Webhook names referenced in global.event_webhooks and repository.*.event_webhooks must exist in [event_webhook.*]

Invalid configuration is rejected with a descriptive error message.


Hot Reloading

Event webhook configuration is hot-reloaded when the configuration file changes. The new dispatcher replaces the old one atomically. In-flight deliveries on the old dispatcher continue to completion.

Changes that do not require restart:

  • Adding, removing, or modifying webhook definitions
  • Changing webhook references in global or repository configuration

Graceful Shutdown

On shutdown, the dispatcher:

  1. Stops accepting new async deliveries
  2. Waits for in-flight async deliveries to complete (with timeout)
  3. Logs any deliveries that did not complete within the timeout