Webhook Updates
The documentation portal can update catalogs instantly — right after a push to the repository, without waiting for the next scheduled update cycle. A Git host sends a webhook notification to the portal, and the portal immediately pulls the changes for the affected catalog.
Supported Git hosts
The portal recognizes webhooks in GitHub or GitLab format — by the event header (X-GitHub-Event or X-Gitlab-Event), the signature or token, and the request body fields (repository URL and branch). Processing is not tied to a specific service, so any host that can send a webhook in one of these formats is supported.
GitHub — GitHub format, supported out of the box.
GitLab and GitLab Self-Hosted — GitLab format, supported out of the box.
Gitea — sends a GitHub-compatible webhook (the
X-GitHub-Eventheader and theX-Hub-Signature-256signature), supported. Configure it the same way as for GitHub.GitVerse, GitFlic, and others.
Portal setup
Set the
WEBHOOK_SECRETenvironment variable in the Docker Compose file — a secret string the portal uses to verify the authenticity of notifications. If the variable is not set, webhook processing is disabled.Set the
WEBHOOK_TOKENenvironment variable — the repository access token the portal uses to pull changes after a notification.
WEBHOOK_TOKEN is a dedicated token for webhook updates, independent of AUTO_PULL_TOKEN. Webhook updates work even when the scheduled update is disabled.
Webhook setup in GitLab
Open the catalog repository and go to Settings → Webhooks.
In the URL field, enter
https://{portal address}/api/webhook.In the Secret token field, enter the
WEBHOOK_SECRETvalue.Check the Push events trigger and save the webhook.
Webhook setup in GitHub
Open the catalog repository and go to Settings → Webhooks → Add webhook.
In the Payload URL field, enter
https://{portal address}/api/webhook.In the Content type field, select
application/json.In the Secret field, enter the
WEBHOOK_SECRETvalue.Select Just the push event and save the webhook.
The portal pulls changes only when the push targets the branch published on the portal. Pushes to other branches and tags are ignored.
Docker Compose example
A single portal instance accepting webhooks with a scheduled update configured:
services: docportal: image: docker.io/gramax/docportal:latest container_name: docportal restart: unless-stopped ports: - "80:80" environment: - WEBHOOK_SECRET=${WEBHOOK_SECRET} - WEBHOOK_TOKEN=${WEBHOOK_TOKEN} - AUTO_PULL_TOKEN=${AUTO_PULL_TOKEN} - AUTO_PULL_INTERVAL=180 volumes: - ./gramax:/app/data
To update catalogs via webhook only, without timed updates, omit AUTO_PULL_TOKEN and AUTO_PULL_INTERVAL — WEBHOOK_SECRET and WEBHOOK_TOKEN are enough.
Multiple portal instances
If several portal instances serve the same catalogs, for example on a shared disk, set the WEBHOOK_PEERS environment variable on the main instance — a comma-separated list of the other instances' addresses. Whenever the main instance changes a catalog on disk, it notifies the others, and they reconcile their state with the disk.
A notification is sent after any catalog change: a webhook pull, clone, synchronization, branch switch, discard, branch deletion, or catalog removal. On receiving a notification, an instance re-reads the catalog from disk:
the catalog exists on disk — the instance re-reads it (or adds it, if it was not present yet);
the catalog is gone from disk — the instance drops it from memory.
Configure the scheduled update credentials on one instance only. The other instances receive changes through notifications — this prevents conflicts caused by simultaneous pulls.
Any instance also accepts a POST /api/webhook/refresh/{catalog name} request with the X-Webhook-Token: {WEBHOOK_SECRET} header — the instance reconciles the catalog with the disk without pulling from the repository. This is useful after a branch switch, a synchronization, or a catalog removal performed by another process.
An example with two instances on a shared disk — the main one pulls changes and notifies the replica, the replica only re-reads the catalog from disk:
services: docportal-primary: image: docker.io/gramax/docportal:latest container_name: docportal-primary restart: unless-stopped ports: - "80:80" environment: - WEBHOOK_SECRET=${WEBHOOK_SECRET} - WEBHOOK_TOKEN=${WEBHOOK_TOKEN} - WEBHOOK_PEERS=http://docportal-replica volumes: - catalogs:/app/data docportal-replica: image: docker.io/gramax/docportal:latest container_name: docportal-replica restart: unless-stopped ports: - "8080:80" environment: - WEBHOOK_SECRET=${WEBHOOK_SECRET} volumes: - catalogs:/app/data volumes: catalogs:
Configure the Git host webhook to target the main instance. The replica does not need WEBHOOK_TOKEN — it never pulls changes itself, but WEBHOOK_SECRET must match the main instance so the replica accepts the refresh notification.