Skip to content

System hooks

Configuring system hooks

Entries in gitlab_settings_instance.system_hooks are reconciled with full lifecycle semantics: created when missing, updated when drifted, and removed with state: absent. The same hook schema applies to hooks lists under group and project entries.

Hook identity

A hook's identity is an explicit server-assigned id when supplied, otherwise its name when present, otherwise its url. GitLab permits duplicate names and URLs, so use id to address one existing duplicate. An id is lookup-only and cannot create a hook. Without an ID, give hooks stable names: renaming one changes its identity and creates a new hook rather than updating the old one.

Example system hook definition

gitlab_settings_instance:
  system_hooks:
    - name: audit-forwarder
      url: https://hooks.example.com/gitlab/system
      token: "{{ vault_gitlab_system_hook_token }}"
      push_events: true
      merge_requests_events: true
      repository_update_events: true
      enable_ssl_verification: true
      url_variables:
        tenant: fde
      custom_headers:
        X-GitLab-Environment: lab
      state: present

System Hook Spec

GitLab API reference

GitLab's API documentation defines the hook fields and event toggles:

  1. System hooks API
  2. Group hooks API
  3. Project hooks API

idinteger

Optional server-assigned lookup identity for one existing hook, particularly when names or URLs are duplicated. Lookup-only: omit it when creating a hook.

Example:
system_hooks:
  - id: 42
    name: audit-forwarder
...

namestring

Hook display name and preferred identity. When id is omitted, declare name or url.

Example:
system_hooks:
  - name: audit-forwarder
...

urlstringRequired on create

Endpoint the hook posts to. Used as the identity when name is absent. Treated as a private value because hook URLs can embed credentials: fingerprinted for comparison and never displayed in diffs (matching the audit-destination and integration URL handling).

Example:
system_hooks:
  - url: https://hooks.example.com/gitlab/system
...

statestring

Lifecycle of the hook.

Can be one of: present, absent

Default: present

Example:
system_hooks:
  - name: unused-hook
    state: absent
...

tokenstring

Shared secret sent with hook deliveries. Write-only: GitLab never returns it, so it is never drift-compared; it is carried on every write, and force_secret_update: true forces a rotation write when nothing else drifted. Handled as a secret end to end — never displayed, logged, or diffed.

Example:
system_hooks:
  - name: audit-forwarder
    token: "{{ vault_hook_token }}"
...

signing_tokenstring

Payload signing secret. Same write-only and secrecy semantics as token.

Example:
system_hooks:
  - name: audit-forwarder
    signing_token: "{{ vault_signing_token }}"
...

force_secret_updateboolean

Rewrite token/signing_token on an existing hook even when nothing else drifted. Use for secret rotation, then remove.

Default: false

Example:
system_hooks:
  - name: audit-forwarder
    token: "{{ new_token }}"
    force_secret_update: true
...

descriptionstring

Human-readable hook description.

Scopes: system, group, project

enable_ssl_verificationboolean

Verify the destination's TLS certificate when delivering the hook.

Scopes: system, group, project

push_eventsboolean

Deliver the hook for repository push events.

Scopes: system, group, project

push_events_branch_filterstring

Restrict push-event deliveries to branches matching this filter.

Scopes: system, group, project

branch_filter_strategystring

How push_events_branch_filter is interpreted. Can be one of: wildcard, regex, all_branches.

Scopes: system, group, project

tag_push_eventsboolean

Deliver the hook when tags are pushed.

Scopes: system, group, project

merge_requests_eventsboolean

Deliver the hook for merge-request events.

Scopes: system, group, project

custom_webhook_templatestring

Custom template used to construct the webhook request payload.

Scopes: system, group, project

repository_update_eventsboolean

Deliver the hook when a repository is updated.

Scope: system

issues_eventsboolean

Deliver the hook for issue events.

Scopes: group, project

confidential_issues_eventsboolean

Deliver the hook for confidential-issue events.

Scopes: group, project

note_eventsboolean

Deliver the hook for note and comment events.

Scopes: group, project

confidential_note_eventsboolean

Deliver the hook for confidential-note events.

Scopes: group, project

job_eventsboolean

Deliver the hook for CI/CD job events.

Scopes: group, project

pipeline_eventsboolean

Deliver the hook for pipeline events.

Scopes: group, project

wiki_page_eventsboolean

Deliver the hook for wiki-page events.

Scopes: group, project

deployment_eventsboolean

Deliver the hook for deployment events.

Scopes: group, project

feature_flag_eventsboolean

Deliver the hook for feature-flag events.

Scopes: group, project

releases_eventsboolean

Deliver the hook for release events.

Scopes: group, project

milestone_eventsboolean

Deliver the hook for milestone events.

Scopes: group, project

emoji_eventsboolean

Deliver the hook for award-emoji events.

Scopes: group, project

resource_access_token_eventsboolean

Deliver the hook for group or project access-token expiry events.

Scopes: group, project

vulnerability_eventsboolean

Deliver the hook for vulnerability events.

Scopes: group, project

project_eventsboolean

Deliver the group hook when projects are created, updated, transferred, or deleted.

Scope: group

subgroup_eventsboolean

Deliver the group hook for subgroup events.

Scope: group

member_eventsboolean

Deliver the group hook for membership events.

Scope: group

resource_deploy_token_eventsboolean

Deliver the project hook for deploy-token expiry events.

Scope: project

url_variablesobject or array

Hook URL variables. Write-only children: GitLab masks the values in responses, so reconciliation is by key presence — a listed key is treated as in sync, and value drift is not detectable.

Properties of url_variables

keystringRequired in list form

  Variable identity. In map form, the map key supplies it.


valuestringRequired when state is present

  Write-only value; GitLab masks it in responses. It is required when this entry's state is present (the default). Omit it when state: absent; deletion uses the entry's key.


force_secret_updateboolean

  Rewrite the write-only value when no readable child attribute drifted. Default: false.


statestring

  Can be one of: present, absent. Default: present


 Map form: {key: value}

 Map form with controls: {key: {value: v, state: present|absent, force_secret_update: true|false}}

 List form: [{key: k, value: v, state: present|absent, force_secret_update: true|false}]

Example:
system_hooks:
  - name: audit-forwarder
    url_variables:
      tenant:
        # state: present (default) — value required
        state: present
        value: fde
      obsolete:
        # deletion — value must be omitted
        state: absent
...

custom_headersobject or array

Custom HTTP headers sent with deliveries. Values have the same write-only presence semantics as url_variables. GitLab permits at most 20 present headers per hook; header names must satisfy the HTTP header-name grammar, and case-insensitive duplicates are rejected.

Properties of custom_headers

keystringRequired in list form

  Header name and identity. In map form, the map key supplies it.


valuestringRequired when state is present

  Write-only header value. It is required when this entry's state is present (the default). Omit it when state: absent; deletion uses the entry's key.


force_secret_updateboolean

  Rewrite the write-only value when no readable child attribute drifted. Default: false.


statestring

  Can be one of: present, absent. Default: present


 Map form: {key: value}

 Map form with controls: {key: {value: v, state: present|absent, force_secret_update: true|false}}

 List form: [{key: k, value: v, state: present|absent, force_secret_update: true|false}]

Example:
system_hooks:
  - name: audit-forwarder
    custom_headers:
      X-GitLab-Environment:
        # state: present (default) — value required
        value: lab
      X-Unused-Header:
        # deletion — value must be omitted
        state: absent
...