1--- 2stage: Create 3group: Gitaly 4info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments 5type: reference, howto 6disqus_identifier: 'https://docs.gitlab.com/ee/administration/custom_hooks.html' 7--- 8 9# Server hooks **(FREE SELF)** 10 11> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196051) in GitLab 12.8 replacing Custom Hooks. 12 13Git supports hooks that are executed on different actions. These hooks run on the server and can be 14used to enforce specific commit policies or perform other tasks based on the state of the 15repository. 16 17Git supports the following hooks: 18 19- `pre-receive` 20- `post-receive` 21- `update` 22 23See [the Git documentation](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_server_side_hooks) 24for more information about each hook type. 25 26Server-side Git hooks can be configured for: 27 28- [A single repository](#create-a-server-hook-for-a-repository). 29- [All repositories](#create-a-global-server-hook-for-all-repositories). 30 31Note the following about server hooks: 32 33- Server hooks must be configured on the file system of the GitLab server. Only GitLab server 34 administrators are able to complete these tasks. If you don't have file system access, see 35 possible alternatives such as: 36 - [Webhooks](../user/project/integrations/webhooks.md). 37 - [GitLab CI/CD](../ci/index.md). 38 - [Push Rules](../push_rules/push_rules.md), for a user-configurable Git hook 39 interface. 40- Server hooks aren't replicated to [Geo](geo/index.md) secondary nodes. 41 42## Create a server hook for a repository 43 44If you are not using [hashed storage](repository_storage_types.md#hashed-storage), the project's 45repository directory might not exactly match the instructions below. In that case: 46 47- For an installation from source, the path is usually 48 `/home/git/repositories/<group>/<project>.git`. 49- For Omnibus GitLab installs, the path is usually 50 `/var/opt/gitlab/git-data/repositories/<group>/<project>.git`. 51 52Follow the steps below to set up a server-side hook for a repository: 53 541. Go to **Admin area > Projects** and select the project you want to add a server hook to. 551. Locate the **Gitaly relative path** on the page that appears. This is where the server hook 56 must be implemented. For information on interpreting the relative path, see 57 [Translate hashed storage paths](repository_storage_types.md#translate-hashed-storage-paths). 581. On the file system, create a new directory in this location called `custom_hooks`. 591. Inside the new `custom_hooks` directory, create a file with a name matching the hook type. For 60 example, for a pre-receive hook the filename should be `pre-receive` with no extension. 611. Make the hook file executable and ensure that it's owned by the Git user. 621. Write the code to make the server hook function as expected. Hooks can be in any language. Ensure 63 the ["shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top properly reflects the 64 language type. For example, if the script is in Ruby the shebang is probably 65 `#!/usr/bin/env ruby`. 66 67Assuming the hook code is properly implemented, the hook code is executed as appropriate. 68 69## Create a global server hook for all repositories 70 71To create a Git hook that applies to all of the repositories in your instance, set a global server 72hook. The default global server hook directory is in the GitLab Shell directory. Any 73hook added there applies to all repositories, including: 74 75- [Project and group wiki](../user/project/wiki/index.md) repositories, 76 whose storage directory names are in the format `<id>.wiki.git`. 77- [Design management](../user/project/issues/design_management.md) repositories under a 78 project, whose storage directory names are in the format `<id>.design.git`. 79 80The default directory: 81 82- For an installation from source is usually `/home/git/gitlab-shell/hooks`. 83- For Omnibus GitLab installs is usually `/opt/gitlab/embedded/service/gitlab-shell/hooks`. 84 85To use a different directory for global server hooks, set `custom_hooks_dir` in Gitaly 86configuration: 87 88- For Omnibus installations, this is set in `gitlab.rb`. 89- For source installations, the configuration location depends on the GitLab version. For: 90 - GitLab 13.0 and earlier, this is set in `gitlab-shell/config.yml`. 91 - GitLab 13.1 and later, this is set in `gitaly/config.toml` under the `[hooks]` section. 92 93NOTE: 94The `custom_hooks_dir` value in `gitlab-shell/config.yml` is still honored in GitLab 13.1 and later 95if the value in `gitaly/config.toml` is blank or non-existent. 96 97Follow the steps below to set up a global server hook for all repositories: 98 991. On the GitLab server, navigate to the configured global server hook directory. 1001. Create a new directory in this location. Depending on the type of hook, it can be either a 101 `pre-receive.d`, `post-receive.d`, or `update.d` directory. 1021. Inside this new directory, add your hook. Hooks can be in any language. Ensure the 103 ["shebang"](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top properly reflects the 104 language type. For example, if the script is in Ruby the shebang is probably 105 `#!/usr/bin/env ruby`. 1061. Make the hook file executable and ensure that it's owned by the Git user. 107 108Now test the hook to check whether it is functioning properly. 109 110## Chained hooks 111 112Server hooks set [per project](#create-a-server-hook-for-a-repository) or 113[globally](#create-a-global-server-hook-for-all-repositories) can be executed in a chain. 114 115Server hooks are searched for and executed in the following order of priority: 116 117- Built-in GitLab server hooks. These are not user-customizable. 118- `<project>.git/custom_hooks/<hook_name>`: Per-project hooks. This was kept for backwards 119 compatibility. 120- `<project>.git/custom_hooks/<hook_name>.d/*`: Location for per-project hooks. 121- `<custom_hooks_dir>/<hook_name>.d/*`: Location for all executable global hook files 122 except editor backup files. 123 124Within a directory, server hooks: 125 126- Are executed in alphabetical order. 127- Stop executing when a hook exits with a non-zero value. 128 129`<hook_name>.d` must be either `pre-receive.d`, `post-receive.d`, or `update.d` to work properly. 130Any other names are ignored. 131 132Files in `.d` directories must be executable and not match the backup file pattern (`*~`). 133 134For `<project>.git` you need to [translate](repository_storage_types.md#translate-hashed-storage-paths) 135your project name into the hashed storage format that GitLab uses. 136 137## Environment Variables 138 139The following set of environment variables are available to server hooks. 140 141| Environment variable | Description | 142|:---------------------|:----------------------------------------------------------------------------| 143| `GL_ID` | GitLab identifier of user that initiated the push. For example, `user-2234` | 144| `GL_PROJECT_PATH` | (GitLab 13.2 and later) GitLab project path | 145| `GL_PROTOCOL` | (GitLab 13.2 and later) Protocol used for this change. One of: `http` (Git Push using HTTP), `ssh` (Git Push using SSH), or `web` (all other actions). | 146| `GL_REPOSITORY` | `project-<id>` where `id` is the ID of the project | 147| `GL_USERNAME` | GitLab username of the user that initiated the push | 148 149Pre-receive and post-receive server hooks can also access the following Git environment variables. 150 151| Environment variable | Description | 152|:-----------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| 153| `GIT_ALTERNATE_OBJECT_DIRECTORIES` | Alternate object directories in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). | 154| `GIT_OBJECT_DIRECTORY` | GitLab project path in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). | 155| `GIT_PUSH_OPTION_COUNT` | Number of push options. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). | 156| `GIT_PUSH_OPTION_<i>` | Value of push options where `i` is from `0` to `GIT_PUSH_OPTION_COUNT - 1`. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). | 157 158NOTE: 159While other environment variables can be passed to server hooks, your application should not rely on 160them as they can change. 161 162## Custom error messages 163 164To have custom error messages appear in the GitLab UI when a commit is declined or an error occurs 165during the Git hook, your script should: 166 167- Send the custom error messages to either the script's `stdout` or `stderr`. 168- Prefix each message with `GL-HOOK-ERR:` with no characters appearing before the prefix. 169 170### Example custom error message 171 172This hook script written in Bash generates the following message in the GitLab UI: 173 174```shell 175#!/bin/sh 176echo "GL-HOOK-ERR: My custom error message."; 177exit 1 178``` 179 180![Custom message from custom Git hook](img/custom_hooks_error_msg.png) 181