VACVAC
Reference

Webhooks

Inbound push-to-deploy webhooks, and outbound deploy/health notifications.

2 min readUpdated June 15, 2026Edition · v0.5.xBeta

"Webhooks" in VAC means two distinct things: inbound webhooks that trigger deploys when you push, and outbound notifications that VAC sends when something happens.

Inbound: push-to-deploy

Each app exposes a signed inbound webhook so your Git host can tell VAC to deploy.

1. Get the webhook URL and secret

In the app, open its webhook config. VAC gives you a delivery URL of the form:

https://vac.example.com/webhooks/{appID}

Generate (or rotate) a secret for it — VAC seals the secret at rest and shows the plaintext once. Add the URL and secret to your repository's webhook settings (GitHub, GitLab, etc.).

2. Add a deploy trigger

A webhook delivery only deploys if it matches a deploy trigger you've created — so a push to a feature branch doesn't redeploy production. A trigger has:

  • an eventpush or tag,
  • a filter — a pattern like main, release/*, or v* (empty matches anything).

3. How a delivery is handled

When a delivery arrives, VAC:

  1. validates the HMAC signature against the stored secret,
  2. parses the ref (branch or tag) from the payload,
  3. matches it against the app's triggers,
  4. enqueues a deployment (triggered_by: push or tag) if a trigger matches and no deploy is already running.
Coalescing and rate limits

If a deploy is already in flight for the app, an incoming delivery is coalesced rather than queued behind it. Inbound webhooks are also rate-limited per window to absorb bursts.

Outbound: notifications

VAC can push events to Discord and Slack via incoming-webhook URLs.

Events

EventFires when
deploy_succeededa deploy completes and services are healthy
deploy_faileda deploy fails or times out on health checks
crash_loopa service is stopped after repeated crashes
oom_killeda container is killed by the OOM killer
vac_restartedthe control plane restarts
cert_expiringa certificate is within ~14 days of expiry without renewing
backup_faileda scheduled or manual backup fails
traffic_anomalythe security monitor sees a request/error spike from one IP

All events default on; you can toggle them individually.

Configuration

Set webhook URLs in Settings → Notifications (stored encrypted with the master key), or via the VAC_NOTIFY_DISCORD_URL / VAC_NOTIFY_SLACK_URL environment variables, which take precedence. There's a test button to confirm delivery.

Delivery details

Notifications are fire-and-forget on a background goroutine — they never block a deploy — with a few retries on failure. Messages are color-coded by severity and deep-link back to the app. URLs that resolve to private/loopback addresses are refused (SSRF guard). There is no email channel.

Next

On this page