Container Registry webhooks
Webhooks send registry events to an HTTP endpoint you control, so other systems can react to them, for example to deploy an image as soon as it's pushed. Each delivery is a JSON POST request in the CloudEvents format.
Add webhooks from the Webhooks tab of the registry in the Control Panel. Every webhook receives all of the events below.
Webhook settings
Each webhook has the following settings:
- Name: identifies the webhook and can't be changed later. To rename a webhook, delete it and add it again.
- URL: the endpoint that receives the deliveries.
- Custom headers: optional headers sent with every delivery, for example to route events or tag them with an environment.
- Secret: sent with every delivery so that your endpoint can check that the request comes from the registry. Leave the field blank to generate a secret, or enter your own.
The secret is shown once, right after you add the webhook, so copy it then and store it where your endpoint can read it. You can change a webhook's URL and custom headers later. If you lose the secret, delete the webhook and add it again to get a new one.
Events
| Event type | Sent when |
|---|---|
upcloud.container-registry.repository.created | The first image or artifact is pushed to a new repository. |
upcloud.container-registry.image.updated | A manifest is pushed to a repository. |
upcloud.container-registry.image.deleted | A tag or an image is deleted, including when its repository is deleted. |
A single push often uploads more than one manifest, for example an image index together with its platform and attestation manifests, and each manifest sends its own image.updated event. Manifests pushed by digest have the digest as their reference, and the one pushed with the tag has the tag. Pulls don't send events, and neither does pushing a tag that hasn't changed.
Deleting a repository sends an image.deleted event for each image in it.
Delivery format
Deliveries use CloudEvents 1.0 in binary mode, with the event attributes in ce- headers. The ce-type header holds the event type, and ce-source holds the registry endpoint.
The JSON body names the repository, the tag or digest, and the registry user that made the change. This is the body of an image.updated event for a pushed tag, with the manifest and useragent values shortened:
{
"actor": {
"name": "app-developer"
},
"digest": "sha256:2aaa6fd9896fc5a1f1d502693bda2a2ac6fb7e6598d58ac11bd1587ebcb2cf14",
"manifest": "{\n \"schemaVersion\": 2,\n \"mediaType\": \"application/vnd.oci.image.index.v1+json\", ...",
"mediaType": "application/vnd.oci.image.index.v1+json",
"name": "demo/hello-upcloud",
"reference": "1.1",
"request": {
"addr": "192.168.3.143:47712",
"method": "PUT",
"useragent": "docker/29.8.2 ..."
}
}An image.deleted event carries the same fields except manifest, and a repository.created event carries actor, name, and request only.
Delivery
The registry delivers webhooks over the public internet, so the endpoint must be reachable from outside your private networks. Every delivery carries the webhook's secret in an Authorization: Bearer header, so use an https:// URL and have your endpoint reject requests that don't carry the secret. Deliveries aren't signed.
Each event is delivered once. If the endpoint returns an error, the delivery isn't sent again.
Limits
The number of webhooks depends on the plan. See Plans.