doc/administration/auth/ldap/ldap_synchronization.md
{{< details >}}
{{< /details >}}
If you have configured LDAP to work with GitLab, GitLab can automatically synchronize users and groups.
LDAP synchronization updates user and group information for existing GitLab users that have an LDAP identity assigned. It does not create new GitLab users through LDAP.
You can change when synchronization occurs.
Some LDAP servers have rate limits configured.
GitLab queries the LDAP server once for every:
In some cases, more queries to the LDAP server may be triggered. For example, when a group sync query returns a memberuid attribute.
If the LDAP server has a rate limit configured and that limit is reached during the:
You must consider your LDAP server's rate limits when configuring LDAP synchronization to prevent unwanted user blocks and group membership removals.
{{< history >}}
{{< /history >}}
Once per day, GitLab runs a worker to check and update GitLab users against LDAP.
The process executes the following access checks:
active_directory: true is set in the LDAP configuration.In Active Directory, a user is marked as disabled/blocked if the user
account control attribute (userAccountControl:1.2.840.113556.1.4.803)
has bit 2 set.
For more information, see Bitmask Searches in LDAP.
<!-- vale gitlab_base.Spelling = YES -->The process also updates the following user information:
name is not synchronized if
Prevent users from changing their profile name is enabled or sync_name is set to false.sync_ssh_keys is set.[!note] If your LDAP server has a rate limit, that limit might be reached during the user sync process. Check the rate limit documentation for more information.
By default, GitLab synchronizes the LDAP user's profile name field.
To prevent this synchronization, you can set sync_name to false.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_servers'] = {
'main' => {
'sync_name' => false,
}
}
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
ldap:
servers:
main:
sync_name: false
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_servers'] = {
'main' => {
'sync_name' => false,
}
}
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ldap:
servers:
main:
sync_name: false
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
A user is blocked if either the:
ldap_blocked state in GitLab.If a user is blocked, that user cannot sign in or push or pull code.
A blocked user is unblocked when they sign in with LDAP if all of the following are true:
All users are blocked if the LDAP server is unavailable when an LDAP user synchronization is run.
[!note] If all users are blocked due to the LDAP server not being available when an LDAP user synchronization is run, a subsequent LDAP user synchronization does not automatically unblock those users.
If your LDAP supports the memberof property, when the user signs in for the
first time GitLab triggers a sync for groups the user should be a member of.
That way they don't have to wait for the hourly sync to be granted
access to their groups and projects.
A group sync process runs every hour on the hour, and group_base must be set
in LDAP configuration for LDAP synchronizations based on group CN to work. This allows
GitLab group membership to be automatically updated based on LDAP group members.
The group_base configuration should be a base LDAP 'container', such as an
'organization' or 'organizational unit', that contains LDAP groups that should
be available to GitLab. For example, group_base could be
ou=groups,dc=example,dc=com. In the configuration file, it looks like the
following.
[!note] If your LDAP server has a rate limit, that limit might be reached during the group sync process. Check the rate limit documentation for more information.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_servers'] = {
'main' => {
'group_base' => 'ou=groups,dc=example,dc=com',
}
}
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
ldap:
servers:
main:
group_base: ou=groups,dc=example,dc=com
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_servers'] = {
'main' => {
'group_base' => 'ou=groups,dc=example,dc=com',
}
}
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ldap:
servers:
main:
group_base: ou=groups,dc=example,dc=com
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
To take advantage of group sync, group Owners or users with the Maintainer role must create one or more LDAP group links.
[!note] If you frequently experience connection issues between your LDAP server and GitLab instance, try reducing the frequency with which GitLab performs an LDAP group sync by setting the group sync worker interval to be greater than the 1 hour default.
For information on adding group links by using CNs and filters, refer to the GitLab groups documentation.
As an extension of group sync, you can automatically manage your global GitLab
administrators. Specify a group CN for admin_group and all members of the
LDAP group are given administrator privileges. The configuration looks
like the following.
[!note] Administrators are not synced unless
group_baseis also specified alongsideadmin_group. Also, only specify the CN of theadmin_group, as opposed to the full DN. Additionally, if an LDAP user has anadminrole, but is not a member of theadmin_groupgroup, GitLab revokes theiradminrole when syncing.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_servers'] = {
'main' => {
'group_base' => 'ou=groups,dc=example,dc=com',
'admin_group' => 'my_admin_group',
}
}
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
ldap:
servers:
main:
group_base: ou=groups,dc=example,dc=com
admin_group: my_admin_group
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_servers'] = {
'main' => {
'group_base' => 'ou=groups,dc=example,dc=com',
'admin_group' => 'my_admin_group',
}
}
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ldap:
servers:
main:
group_base: ou=groups,dc=example,dc=com
admin_group: my_admin_group
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
{{< details >}}
{{< /details >}}
You can assign a custom admin role to all users synced from an external LDAP group. This option is not available for SAML groups.
If a user belongs to multiple LDAP groups with different assigned custom roles, GitLab assigns the role associated with the LDAP group that was linked first.
[!note] If an LDAP user with a custom admin role is removed from the LDAP group after configuring a sync, the custom role is not removed until the next sync.
Prerequisites:
{{< tabs >}}
{{< tab title="Assign with an LDAP CN" >}}
To assign a custom admin role with an LDAP CN:
Group cn.group_base.GitLab begins linking the role to any matching LDAP users. This process may take over an hour to complete.
{{< /tab >}}
{{< tab title="Assign with an LDAP filter" >}}
To assign a custom admin role with an LDAP filter:
User filter.GitLab begins linking the role to any matching LDAP users. This process may take over an hour to complete.
{{< /tab >}}
{{< /tabs >}}
GitLab administrators can prevent group members from inviting new members to subgroups that have their membership synchronized with LDAP.
Global group membership lock only applies to subgroups of the top-level group where LDAP synchronization is configured. No user can modify the membership of a top-level group configured for LDAP synchronization.
When global group memberships lock is enabled:
To enable global group memberships lock:
By default, group members with the Owner role can manage LDAP group synchronization settings.
GitLab administrators can remove this permission from group Owners:
When Allow group owners to manage LDAP-related settings is disabled:
Using the external_groups setting allows you to mark all users belonging
to these groups as external users.
Group membership is checked periodically through the LdapGroupSync background
task.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_servers'] = {
'main' => {
'external_groups' => ['interns', 'contractors'],
}
}
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
ldap:
servers:
main:
external_groups: ['interns', 'contractors']
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_servers'] = {
'main' => {
'external_groups' => ['interns', 'contractors'],
}
}
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ldap:
servers:
main:
external_groups: ['interns', 'contractors']
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
The duo_add_on_groups setting automatically manages GitLab Duo add-on seats for users who authenticate through LDAP. This feature helps organizations to streamline their GitLab Duo seat allocation process based on LDAP group memberships.
GitLab Duo seat synchronization occurs in two ways:
To enable add-on seat management for groups, you must configure the duo_add_on_groups setting in your GitLab instance:
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_servers'] = {
'main' => {
'duo_add_on_groups' => ['duo_group_1', 'duo_group_2'],
}
}
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
ldap:
servers:
main:
duo_add_on_groups: ['duo_group_1', 'duo_group_2']
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_servers'] = {
'main' => {
'duo_add_on_groups' => ['duo_group_1', 'duo_group_2'],
}
}
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ldap:
servers:
main:
duo_add_on_groups: ['duo_group_1', 'duo_group_2']
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
This section outlines what LDAP queries are executed and what behavior you can expect from group sync.
If a user's LDAP group membership changes, their group access level may be downgraded. For example, if a user has the Owner role in a group and the next group sync reveals they should only have the Developer role, their access is adjusted accordingly. The only exception is if the user is the last owner in a group. Groups need at least one owner to fulfill administrative duties.
{{< history >}}
bso_minimal_access_fallback. Disabled by default.{{< /history >}}
When restricted access is enabled and no subscription seats are available, users are assigned the Minimal Access role during LDAP group synchronization.
For more information, see Provisioning behavior with SAML, SCIM, and LDAP.
GitLab supports LDAP groups that use member attributes:
membersubmemberuniquemembermemberofmemberuidThis means group sync supports (at least) LDAP groups with the following object classes:
groupOfNamesposixGroupgroupOfUniqueNamesOther object classes should work if members are defined as one of the mentioned attributes.
Active Directory supports nested groups. Group sync recursively resolves
membership if active_directory: true is set in the configuration file.
Nested group memberships are resolved only if the nested group
is found in the configured group_base. For example, if GitLab sees a
nested group with DN cn=nested_group,ou=special_groups,dc=example,dc=com but
the configured group_base is ou=groups,dc=example,dc=com, cn=nested_group
is ignored.
group_base and
filter (cn=<cn_from_group_link>).memberuid attribute, GitLab executes another
LDAP query per member to obtain each user's full DN. These queries are
executed with base base, scope baseObject, and a filter depending on
whether user_filter is set. Filter may be (uid=<uid_from_group>) or a
joining of user_filter.Group sync was written to be as performant as possible. Data is cached, database queries are optimized, and LDAP queries are minimized. The last benchmark run revealed the following metrics:
For 20,000 LDAP users, 11,000 LDAP groups, and 1,000 GitLab groups with 10 LDAP group links each:
These metrics are meant to provide a baseline and performance may vary based on any number of factors. This benchmark was extreme and most instances don't have near this many users or groups. Disk speed, database performance, network and LDAP server response time affects these metrics.
You can change the time and interval when LDAP synchronizes users, groups, and GitLab Duo add-on seats.
By default, GitLab runs a worker once per day at 01:30 AM server time to check and update GitLab users against LDAP.
[!warning] Do not run the sync process too frequently as this could lead to multiple syncs running concurrently. Most installations do not need to modify the sync schedule. For more information, see the LDAP Security documentation.
You can manually configure LDAP user sync times by setting the following configuration values, in cron format. If needed, you can use a crontab generator. The example below shows how to set LDAP user sync to run once every 12 hours at the top of the hour.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
cron_jobs:
ldap_sync_worker:
cron: "0 */12 * * *"
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ee_cron_jobs:
ldap_sync_worker:
cron: "0 */12 * * *"
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
By default, GitLab runs a group sync process every hour, on the hour. The values shown are in cron format. If needed, you can use a crontab generator.
[!warning] Do not start the sync process too frequently as this could lead to multiple syncs running concurrently. Most installations do not need to modify the sync schedule.
You can manually configure LDAP group sync times by setting the following configuration values. The example below shows how to set group sync to run once every two hours at the top of the hour.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_group_sync_worker_cron'] = "0 */2 * * *"
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
cron_jobs:
ldap_group_sync_worker:
cron: "*/30 * * * *"
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_group_sync_worker_cron'] = "0 */2 * * *"
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ee_cron_jobs:
ldap_group_sync_worker:
cron: "*/30 * * * *"
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}
By default, GitLab runs a GitLab Duo add-on seat sync process once per day at 02:00 AM server time to check LDAP group membership and assign or remove GitLab Duo add-on seats accordingly.
[!warning] Do not start the sync process too frequently as this could lead to multiple syncs running concurrently. Most installations do not need to modify the sync schedule.
You can manually configure LDAP GitLab Duo add-on seat sync times by setting configuration values. The following example shows how to set the sync to run once every four hours.
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
Edit /etc/gitlab/gitlab.rb:
gitlab_rails['ldap_add_on_seat_sync_worker_cron'] = "0 */4 * * *"
Save the file and reconfigure GitLab:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
Export the Helm values:
helm get values gitlab > gitlab_values.yaml
Edit gitlab_values.yaml:
global:
appConfig:
cron_jobs:
ldap_add_on_seat_sync_worker:
cron: "0 */4 * * *"
Save the file and apply the new values:
helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
{{< /tab >}}
{{< tab title="Docker" >}}
Edit docker-compose.yml:
version: "3.6"
services:
gitlab:
environment:
GITLAB_OMNIBUS_CONFIG: |
gitlab_rails['ldap_add_on_seat_sync_worker_cron'] = "0 */4 * * *"
Save the file and restart GitLab:
docker compose up -d
{{< /tab >}}
{{< tab title="Self-compiled (source)" >}}
Edit /home/git/gitlab/config/gitlab.yml:
production: &base
ee_cron_jobs:
ldap_add_on_seat_sync_worker:
cron: "0 */4 * * *"
Save the file and restart GitLab:
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
{{< /tab >}}
{{< /tabs >}}