Adding the Webhook Gateway on Upgrade (Pro)
DefectDojo Pro can put a webhook gateway in front of Triage Engine webhook receivers, the URLs Jira and other tools post to for two-way sync. The gateway stores each webhook and answers the sender before DefectDojo is involved, then delivers it with retries, so a DefectDojo restart or short outage loses nothing.
This page is for operators upgrading an existing self-hosted installation to the first release that ships the gateway. Most installations have nothing to do: the upgrade creates everything the gateway needs. Read on if your database user has restricted privileges, if you count database connections, or if you want to know what to check and how to roll back.
What changes
Docker Compose
The Docker Compose bundles turn the gateway on (DD_WEBHOOK_GATEWAY_MODE=whook and WEBHOOK_GATEWAY_ENABLED=true). An upgrade with dojo-compose-cli brings:
- A new container and image,
webhook-gateway, from the same registry and version as the rest of DefectDojo Pro. The standard image is published forlinux/amd64andlinux/arm64; FIPS deployments use the-fipsvariant, published forlinux/amd64. Air-gapped installations need this image in the transferred bundle too. - Two new nginx files in the deployment directory,
nginx/webhook-gateway.confandnginx/webhook-direct.conf, bind-mounted into the nginx container.dojo-compose-cli deploy downloadfetches them with the rest of the deployment files. - A new named volume,
webhook_gateway_secrets. DefectDojo’sinitcontainer writes the gateway’s secrets and database URL there, and onlyinitand the gateway mount it. - A schema and a database role inside DefectDojo’s existing database (see below). No new database is needed.
Kubernetes
The Helm chart runs the gateway when webhookGateway.enabled is on. Check the value’s default in the chart version you install: a chart may ship it off until the DefectDojo Pro release that publishes the gateway image. With it off, DefectDojo serves receiver URLs itself (DD_WEBHOOK_GATEWAY_MODE=direct). With it on, the gateway pod’s webhook-gateway-db-setup init container prepares the same schema and role described below and prints the statements to run when it cannot. An installation that uses dojo.existingSecret keeps the gateway off until you add its keys to your Secret and set webhookGateway.existingSecretHasKeys, because the chart cannot derive them without seeing dojo.secretKey.
ECS
The ECS task definitions do not include the gateway. They set DD_WEBHOOK_GATEWAY_MODE=direct, so DefectDojo answers receiver URLs itself and nothing below applies.
The database schema and role
The gateway keeps its tables in a schema of its own, whook by default (DD_WEBHOOK_GATEWAY_SCHEMA), inside DefectDojo’s database. It logs in with a role of its own, named after DefectDojo’s database by default (<database>_webhook_gateway, set with DD_WEBHOOK_GATEWAY_DB_ROLE), which owns that schema and can use nothing else of DefectDojo’s. Because PostgreSQL roles belong to the whole server, each installation on a shared server gets its own role, and DefectDojo never changes a role that was created for another database.
On startup, DefectDojo creates both when they are missing, using DefectDojo’s own database user:
- Creating the role needs
CREATEROLE. The admin user of most managed databases has it, and so does DefectDojo’s user in a new installation of the Docker Compose bundle with a bundled database. A bundled database created before this release does not grant it: runALTER USER <DefectDojo database user> CREATEROLE;once as thepostgresuser, then restart DefectDojo. Without it, the gateway connects with DefectDojo’s credentials, confined to its schema bysearch_pathonly, andinitlogs the statements that would give it a role of its own. - Creating the schema needs
CREATEon DefectDojo’s database, which the database’s owner always has. Without it,initlogs the exact statement to run, the gateway refuses to start and prints the same statement, and the receivers list shows the gateway as Not Started.
When DefectDojo’s user may do neither, have a database administrator run the following once, with your database name and a password of your choosing, connected to DefectDojo’s database:
CREATE ROLE <database>_webhook_gateway LOGIN PASSWORD '<password>';
GRANT CONNECT ON DATABASE <database> TO <database>_webhook_gateway;
CREATE SCHEMA IF NOT EXISTS whook AUTHORIZATION <database>_webhook_gateway;Then set DD_WEBHOOK_GATEWAY_DB_PASSWORD to that password in the deployment’s environment, so DefectDojo hands the gateway the same one. To keep the gateway on DefectDojo’s own credentials instead, set DD_WEBHOOK_GATEWAY_DB_ROLE to an empty value and create only the schema:
CREATE SCHEMA IF NOT EXISTS whook AUTHORIZATION <DefectDojo's database user>;Secrets
The gateway needs an admin token, a key that encrypts stored receiver tokens, a key it signs its deliveries to DefectDojo with, and its database role’s password. Each installation derives its own from DD_SECRET_KEY, so there is nothing to generate before the upgrade, and the gateway container never receives DD_SECRET_KEY itself. The Helm chart derives them from dojo.secretKey. To manage one yourself, set DD_WEBHOOK_GATEWAY_ADMIN_TOKEN, DD_WEBHOOK_GATEWAY_SECRET_KEY, DD_WEBHOOK_GATEWAY_DELIVERY_SECRET or DD_WEBHOOK_GATEWAY_DB_PASSWORD; a value that is set wins over the derived one.
Because the derived secrets follow DD_SECRET_KEY, an installation still running on the DD_SECRET_KEY from DefectDojo’s deployment files gets a startup warning (system check pro.W002). Give it its own key. When you change DD_SECRET_KEY later, restart DefectDojo, its workers and the gateway together; see Changing the secret key or the gateway secrets.
Connections and rate limits
- The gateway holds at most 5 connections to DefectDojo’s database server by default (
WHOOK_DB_MAX_CONNS;webhookGateway.database.maxConnectionsin the Helm chart), on top of DefectDojo’s own. Count them against the server’smax_connections, or a managed database’s connection limit. During a Kubernetes rollout two gateway pods briefly run at once. - nginx allows each sender address 100 receiver requests per second by default (
DD_WEBHOOK_RECEIVER_RATE, burstDD_WEBHOOK_RECEIVER_BURST, 1000), and the gateway accepts 100 deliveries per second per receiver (WHOOK_INGEST_RATE, burstWHOOK_INGEST_BURST, 1000). Both answer429above the limit, which senders retry. - The largest webhook body is
DD_RULES_V2_WEBHOOK_MAX_BODY_BYTES(1 MiB by default), one value that nginx, the gateway and DefectDojo all read.
Verifying the upgrade
The initializer prepared the database. In the
initcontainer’s log, look for:Prepared the webhook gateway's database role and schema Wrote the webhook gateway's secretsPrepared the webhook gateway's schema (it uses DefectDojo's database credentials)means the role could not be created and the gateway uses DefectDojo’s user.Could not prepare the webhook gateway's database; see the warning abovemeans the schema could not be created either: run the statements from the warning.docker compose logs init | grep -i "webhook gateway"The gateway is running and healthy. Its health check fails while it cannot reach its database.
docker compose ps webhook-gatewayThe gateway created its tables. Connected to DefectDojo’s database with
psql:\dt whook.*lists the gateway’s tables once it has started.
\du *_webhook_gatewayshows its role.DefectDojo can reach it. In DefectDojo, open Triage Engine > Webhook Receivers. The top of the list shows the gateway as Healthy. Unreachable means DefectDojo cannot reach the gateway container, Not Started means its schema is missing, and Turned Off means the Inbound Webhooks feature flag is off.
On Kubernetes, the gateway pod’s setup log shows the same preparation:
kubectl logs -n <namespace> deploy/<release>-webhook-gateway -c webhook-gateway-db-setupRunning without the gateway
To have DefectDojo answer receiver URLs itself, set WEBHOOK_GATEWAY_ENABLED=false and DD_WEBHOOK_GATEWAY_MODE=direct together (on Kubernetes, webhookGateway.enabled: false). Receivers keep working, but a delivery that arrives while DefectDojo is down is lost unless the sender retries it.
Rolling back
A release without the gateway does not need anything the gateway added, but three things outlive a rollback and should be removed by hand:
The gateway container. An older bundle has no
webhook-gatewayservice, so a plaindocker compose upleaves the running one behind, still holding database connections. Remove it with:docker compose up -d --remove-orphansThe secrets volume. Once the gateway container is gone:
docker volume rm <project>_webhook_gateway_secretsThe schema and the role. The schema holds captured webhook bodies and headers for up to 30 days (90 for failed deliveries). Drop it once nothing needs to be replayed from it, and drop the role if DefectDojo created it:
DROP SCHEMA whook CASCADE; DROP ROLE <database>_webhook_gateway;
On a release without webhook receivers, their URLs answer 404, and senders retry for their own retry window.