docs(deploy): describe the deploy webhook's signature and strict mode

The compose comment still called DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP a
requirement for a fresh timestamp header, which the route stopped
accepting in strict mode once requests could be signed, and the env
manifest named only the secret header and lacked the strict switch. Both
now say what the route checks: the secret header, which has no replay
protection, or X-Deploy-Webhook-Signature over the timestamp and body,
and that the strict setting takes signed requests only. The development
example says the same and points at the deploy runbook instead of a page
that no longer exists.
This commit is contained in:
Marc-André Bombeck committed 2026-10-25 16:00:35 +01:00
1 parent 877db9a5b7
commit aebd7ea612
3 files changed
+26 -13

No files matched your search

+10 -4
View File
@@ -361,11 +361,17 @@ API_TOKEN_HMAC_KEY="REPLACE-WITH-OUTPUT-OF-openssl-rand-hex-32"
# Auto-deploy webhook (v1.4.15 — phase C2)
# -----------------------------------------------------------------------------
# Coolify (or any CI) pings POST /api/internal/deploy-webhook after a deploy
# attempt with success/failure. We verify the request via this shared secret
# carried in the `X-Deploy-Webhook-Secret` header (timing-safe compare).
# Generate with `openssl rand -hex 32`. Configure the SAME value in Coolify's
# Notifications → Webhook custom-headers panel. See docs/audit/v1415-auto-deploy.md.
# attempt with success/failure. A request authenticates with this shared
# secret in the `X-Deploy-Webhook-Secret` header (timing-safe compare; what
# Coolify's stock sender does, with no replay protection), or by signing:
# `X-Deploy-Webhook-Signature: sha256=<hex>`, the HMAC-SHA256 under this
# secret of the `X-Deploy-Webhook-Timestamp` value, a dot and the raw body,
# the timestamp within 5 minutes. Generate with `openssl rand -hex 32`.
# Configure the SAME value in Coolify's Notifications → Webhook
# custom-headers panel. See docs/ops/deploy.md.
# DEPLOY_WEBHOOK_SECRET=""
# "true" accepts signed requests only; leave unset for Coolify's stock sender.
# DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP=""
# -----------------------------------------------------------------------------
+10 -8
View File
@@ -299,16 +299,18 @@ x-healthlog-env: &healthlog_env
OIDC_SCOPES: "${OIDC_SCOPES:-}"
OIDC_BUTTON_LABEL: "${OIDC_BUTTON_LABEL:-}"
OIDC_ONLY: "${OIDC_ONLY:-}"
# Deploy-result webhook (optional). DEPLOY_WEBHOOK_SECRET authenticates
# POST /api/internal/deploy-webhook; DEPLOY_LOGS_URL is the
# deployment-dashboard URL (e.g. the Coolify UI) linked in
# deploy-failure notifications. Listed here so operator values in
# .env reach the container (the `environment:` block is a whitelist).
# Deploy-result webhook (optional). POST /api/internal/deploy-webhook
# authenticates either with DEPLOY_WEBHOOK_SECRET in the
# X-Deploy-Webhook-Secret header (what Coolify's stock sender can do; no
# replay protection) or with X-Deploy-Webhook-Signature: sha256=<HMAC of
# "<X-Deploy-Webhook-Timestamp>.<body>" under the secret>, the timestamp
# within 5 minutes. DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP=true accepts signed
# requests only. DEPLOY_LOGS_URL is the deployment-dashboard URL (e.g. the
# Coolify UI) linked in deploy-failure notifications. Listed here so
# operator values in .env reach the container (the `environment:` block is
# a whitelist). See docs/ops/deploy.md.
DEPLOY_WEBHOOK_SECRET: "${DEPLOY_WEBHOOK_SECRET:-}"
DEPLOY_LOGS_URL: "${DEPLOY_LOGS_URL:-}"
# Optional replay hardening: when "true", the deploy webhook
# requires a fresh X-Deploy-Webhook-Timestamp header (±5 min).
# See docs/ops/deploy.md.
DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP: "${DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP:-}"
# TLS leaf SPKI-change alarm baseline (optional). The native client
# pins the served TLS leaf; this is the known-good pin set the monitor
+6 -1
View File
@@ -260,11 +260,16 @@
"variables": [
{
"name": "DEPLOY_WEBHOOK_SECRET",
"purpose": "Shared secret for the X-Deploy-Webhook-Secret header on POST /api/internal/deploy-webhook. 64 hex chars."
"purpose": "Shared secret of POST /api/internal/deploy-webhook. 64 hex chars. A request authenticates by sending it in the X-Deploy-Webhook-Secret header (Coolify's stock sender; no replay protection), or by signing: X-Deploy-Webhook-Signature: sha256=<HMAC-SHA256 under this secret of the X-Deploy-Webhook-Timestamp value, a dot and the raw body>, the timestamp within 5 minutes."
},
{
"name": "DEPLOY_LOGS_URL",
"purpose": "URL of the deployment dashboard (e.g. the Coolify UI) linked in deploy-failure notifications. Optional; when unset the notification omits the link."
},
{
"name": "DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP",
"purpose": "\"true\" (or \"1\") accepts only signed deploy-webhook requests (X-Deploy-Webhook-Signature with a fresh X-Deploy-Webhook-Timestamp); the secret header alone is refused with 401. Leave unset for Coolify's stock sender, which can only send the secret header.",
"example": "true"
}
]
},