Set up GitLab LDAP authentication with Active Directory to centralize user management, enable automatic user provisioning, and implement group-based access control for your GitLab instance.
Prerequisites
- GitLab CE or EE installed and running
- Active Directory domain controller accessible
- Service account with LDAP read permissions
- Network connectivity between GitLab server and domain controller
What this solves
GitLab LDAP authentication with Active Directory integration centralizes user management by allowing users to log into GitLab using their existing AD credentials. This eliminates the need to maintain separate user accounts in GitLab, enables automatic user provisioning, and provides group-based access control that synchronizes with your existing organizational structure.
Step-by-step configuration
Install LDAP client tools
Install the necessary LDAP utilities to test connectivity and debug authentication issues before configuring GitLab.
sudo apt update
sudo apt install -y ldap-utilsTest LDAP connectivity
Verify that your GitLab server can connect to the Active Directory domain controller before configuring GitLab LDAP settings.
ldapsearch -x -H ldap://dc.example.com:389 -D "CN=ldap-reader,OU=Service Accounts,DC=example,DC=com" -W -b "DC=example,DC=com" "(sAMAccountName=testuser)"Replace dc.example.com with your domain controller, and ldap-reader with a service account that has read access to Active Directory.
Create LDAP service account
Create a dedicated service account in Active Directory for GitLab LDAP authentication. This account needs read access to user and group information.
The service account should have:
- Read permissions on the Users and Groups organizational units
- Password set to never expire
- User cannot change password option enabled
- Minimum required privileges (no administrative rights)
Backup GitLab configuration
Create a backup of your current GitLab configuration before making changes to ensure you can restore if needed.
sudo cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab.rb.backup.$(date +%Y%m%d)Configure GitLab LDAP settings
Edit the GitLab configuration file to add LDAP authentication settings that connect to your Active Directory server.
gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = {
'main' => {
'label' => 'Active Directory',
'host' => 'dc.example.com',
'port' => 389,
'uid' => 'sAMAccountName',
'bind_dn' => 'CN=gitlab-ldap,OU=Service Accounts,DC=example,DC=com',
'password' => 'SecureServiceAccountPassword123!',
'encryption' => 'plain',
'verify_certificates' => false,
'active_directory' => true,
'allow_username_or_email_login' => true,
'lowercase_usernames' => true,
'block_auto_created_users' => false,
'base' => 'DC=example,DC=com',
'user_filter' => '(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))',
'attributes' => {
'username' => ['uid', 'userid', 'sAMAccountName'],
'email' => ['mail', 'email', 'userPrincipalName'],
'name' => 'displayName',
'first_name' => 'givenName',
'last_name' => 'sn'
},
'group_base' => 'OU=Groups,DC=example,DC=com',
'admin_group' => 'CN=GitLab-Admins,OU=Groups,DC=example,DC=com',
'external_groups' => ['CN=External-Users,OU=Groups,DC=example,DC=com'],
'sync_ssh_keys' => false
}
}Configure LDAP over SSL (recommended)
For production environments, configure LDAPS (LDAP over SSL) to encrypt authentication traffic between GitLab and Active Directory.
gitlab_rails['ldap_servers'] = {
'main' => {
'label' => 'Active Directory',
'host' => 'dc.example.com',
'port' => 636,
'uid' => 'sAMAccountName',
'bind_dn' => 'CN=gitlab-ldap,OU=Service Accounts,DC=example,DC=com',
'password' => 'SecureServiceAccountPassword123!',
'encryption' => 'simple_tls',
'verify_certificates' => true,
'ca_file' => '/etc/ssl/certs/ad-ca-certificate.pem',
'ssl_version' => 'TLSv1_2',
# ... rest of configuration remains the same
}
}Copy your Active Directory CA certificate to /etc/ssl/certs/ad-ca-certificate.pem and set appropriate permissions.
sudo chmod 644 /etc/ssl/certs/ad-ca-certificate.pem
sudo chown root:root /etc/ssl/certs/ad-ca-certificate.pemConfigure group synchronization
Set up automatic group synchronization to map Active Directory groups to GitLab groups for access control.
gitlab_rails['ldap_group_sync_worker_cron'] = "0 /12 "
gitlab_rails['ldap_sync_worker_cron'] = "0 /6 "
gitlab_rails['ldap_group_sync_enabled'] = trueThis configuration enables group synchronization every 12 hours and user synchronization every 6 hours.
Apply configuration changes
Reconfigure GitLab to apply the LDAP settings and restart all necessary services.
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restartThe reconfigure process may take several minutes to complete as GitLab updates its configuration and restarts services.
Test LDAP authentication
Use GitLab's built-in LDAP check command to verify that the LDAP configuration is working correctly.
sudo gitlab-rake gitlab:ldap:checkThis command will test the LDAP connection, authentication, and user search functionality.
Configure automatic user provisioning
Set up automatic user provisioning to create GitLab accounts when users first authenticate via LDAP.
gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'ldapmain'
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_auto_link_ldap_user'] = true
gitlab_rails['omniauth_auto_link_saml_user'] = falseApply the changes and restart GitLab.
sudo gitlab-ctl reconfigureCreate GitLab groups from AD groups
Map Active Directory groups to GitLab groups using the GitLab interface or API for organized access control.
sudo gitlab-rails consoleIn the Rails console, create group mappings:
group = Group.find_by_full_path('developers')
ldap_group_link = group.ldap_group_links.new(
cn: 'CN=Developers,OU=Groups,DC=example,DC=com',
group_access: Gitlab::Access::DEVELOPER,
provider: 'ldapmain'
)
ldap_group_link.save!
exitVerify your setup
Test the LDAP configuration with multiple verification methods to ensure authentication and user provisioning work correctly.
sudo gitlab-rake gitlab:ldap:check
sudo gitlab-rake gitlab:ldap:group_sync
sudo gitlab-ctl tail gitlab-rails/production.logNavigate to your GitLab instance and verify:
- LDAP login option appears on the sign-in page
- Users can authenticate with AD credentials
- New users are automatically created with correct attributes
- Group membership synchronizes properly
Configure user attribute mapping
Customize user attribute synchronization
Fine-tune how Active Directory user attributes map to GitLab user profiles for better user experience.
gitlab_rails['ldap_servers']['main']['attributes'] = {
'username' => ['sAMAccountName'],
'email' => ['mail', 'userPrincipalName'],
'name' => 'displayName',
'first_name' => 'givenName',
'last_name' => 'sn',
'nickname' => 'sAMAccountName'
}Apply the configuration changes:
sudo gitlab-ctl reconfigureTroubleshoot LDAP issues
Enable detailed LDAP logging
Configure verbose logging to troubleshoot authentication and synchronization issues.
gitlab_rails['ldap_servers']['main']['debug_level'] = 1
gitlab_rails['log_level'] = 'debug'Apply changes and monitor logs:
sudo gitlab-ctl reconfigure
sudo gitlab-ctl tail gitlab-rails/production.logTest specific user authentication
Test LDAP authentication for a specific user to diagnose login issues.
sudo gitlab-rake gitlab:ldap:check RAILS_ENV=productionFor testing a specific user:
ldapsearch -x -H ldap://dc.example.com:389 -D "CN=gitlab-ldap,OU=Service Accounts,DC=example,DC=com" -W -b "DC=example,DC=com" "(sAMAccountName=username)" displayName mail sAMAccountNameVerify your setup
sudo gitlab-rake gitlab:ldap:check
sudo gitlab-ctl status
curl -I https://gitlab.example.com
sudo gitlab-rails console -e productionIn the Rails console, verify LDAP configuration:
Gitlab::Auth::Ldap::Config.providers
Gitlab::Auth::Ldap::Config.new('ldapmain').options
exitCommon issues
| Symptom | Cause | Fix |
|---|---|---|
| LDAP tab missing on login | LDAP not enabled or misconfigured | Check gitlab_rails['ldap_enabled'] = true and run gitlab-ctl reconfigure |
| Authentication fails with correct password | Wrong bind DN or service account permissions | Test bind DN with ldapsearch and verify service account has read permissions |
| Users not auto-created | Auto-creation disabled or user filter too restrictive | Set block_auto_created_users to false and check user_filter |
| SSL certificate errors | Missing CA certificate or wrong SSL configuration | Install AD CA certificate and set correct ca_file path |
| Group synchronization not working | Wrong group base DN or insufficient permissions | Verify group_base path and ensure service account can read group membership |
| Timeout errors during authentication | Network connectivity or DNS issues | Test connectivity with telnet dc.example.com 389 and verify DNS resolution |
Next steps
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# GitLab LDAP/Active Directory Integration Setup Script
# Production-ready installation and configuration
# Color codes for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Configuration variables
LDAP_HOST=""
LDAP_BIND_DN=""
LDAP_PASSWORD=""
LDAP_BASE_DN=""
GROUP_BASE_DN=""
USE_SSL=false
LDAP_PORT=389
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Usage function
usage() {
cat << EOF
Usage: $0 -h <ldap_host> -d <bind_dn> -p <password> -b <base_dn> [OPTIONS]
Required arguments:
-h <host> LDAP/AD server hostname or IP
-d <bind_dn> Service account DN (e.g., CN=gitlab-ldap,OU=Service Accounts,DC=example,DC=com)
-p <password> Service account password
-b <base_dn> LDAP base DN (e.g., DC=example,DC=com)
Optional arguments:
-g <group_base> Group base DN (defaults to OU=Groups,<base_dn>)
-s Use LDAPS (SSL) on port 636
--port <port> Custom LDAP port (default: 389, or 636 with -s)
Example:
$0 -h dc.example.com -d "CN=gitlab-ldap,OU=Service Accounts,DC=example,DC=com" \\
-p "SecurePassword123!" -b "DC=example,DC=com" -s
EOF
exit 1
}
# Cleanup function for rollback
cleanup() {
if [[ $? -ne 0 ]]; then
print_error "Script failed. Rolling back changes..."
if [[ -f /etc/gitlab/gitlab.rb.backup.$(date +%Y%m%d) ]]; then
cp /etc/gitlab/gitlab.rb.backup.$(date +%Y%m%d) /etc/gitlab/gitlab.rb
print_status "GitLab configuration restored from backup"
fi
fi
}
trap cleanup ERR
# Check if running as root or with sudo
check_privileges() {
if [[ $EUID -ne 0 ]]; then
print_error "This script must be run as root or with sudo"
exit 1
fi
}
# Auto-detect distribution
detect_distro() {
if [[ ! -f /etc/os-release ]]; then
print_error "Cannot detect Linux distribution"
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
LDAP_UTILS="ldap-utils"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
LDAP_UTILS="openldap-clients"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
LDAP_UTILS="openldap-clients"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
print_status "Detected distribution: $PRETTY_NAME"
print_status "Using package manager: $PKG_MGR"
}
# Parse command line arguments
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
-h)
LDAP_HOST="$2"
shift 2
;;
-d)
LDAP_BIND_DN="$2"
shift 2
;;
-p)
LDAP_PASSWORD="$2"
shift 2
;;
-b)
LDAP_BASE_DN="$2"
shift 2
;;
-g)
GROUP_BASE_DN="$2"
shift 2
;;
-s)
USE_SSL=true
LDAP_PORT=636
shift
;;
--port)
LDAP_PORT="$2"
shift 2
;;
*)
usage
;;
esac
done
# Validate required arguments
if [[ -z "$LDAP_HOST" || -z "$LDAP_BIND_DN" || -z "$LDAP_PASSWORD" || -z "$LDAP_BASE_DN" ]]; then
print_error "Missing required arguments"
usage
fi
# Set default group base DN if not provided
if [[ -z "$GROUP_BASE_DN" ]]; then
GROUP_BASE_DN="OU=Groups,$LDAP_BASE_DN"
fi
}
# Install LDAP client tools
install_ldap_tools() {
print_status "[1/6] Installing LDAP client tools..."
$PKG_UPDATE > /dev/null 2>&1
$PKG_INSTALL $LDAP_UTILS
print_status "LDAP client tools installed successfully"
}
# Test LDAP connectivity
test_ldap_connectivity() {
print_status "[2/6] Testing LDAP connectivity..."
local protocol="ldap"
if [[ "$USE_SSL" == true ]]; then
protocol="ldaps"
fi
if ! ldapsearch -x -H "${protocol}://${LDAP_HOST}:${LDAP_PORT}" \
-D "$LDAP_BIND_DN" -w "$LDAP_PASSWORD" \
-b "$LDAP_BASE_DN" -s base > /dev/null 2>&1; then
print_error "Failed to connect to LDAP server. Please verify credentials and network connectivity"
exit 1
fi
print_status "LDAP connectivity test successful"
}
# Check GitLab installation
check_gitlab() {
print_status "[3/6] Checking GitLab installation..."
if [[ ! -f /etc/gitlab/gitlab.rb ]]; then
print_error "GitLab configuration file not found. Please install GitLab first"
exit 1
fi
if ! command -v gitlab-ctl >/dev/null 2>&1; then
print_error "gitlab-ctl command not found. Please install GitLab first"
exit 1
fi
print_status "GitLab installation verified"
}
# Backup GitLab configuration
backup_config() {
print_status "[4/6] Backing up GitLab configuration..."
local backup_file="/etc/gitlab/gitlab.rb.backup.$(date +%Y%m%d_%H%M%S)"
cp /etc/gitlab/gitlab.rb "$backup_file"
chmod 600 "$backup_file"
print_status "Configuration backed up to: $backup_file"
}
# Configure GitLab LDAP settings
configure_ldap() {
print_status "[5/6] Configuring GitLab LDAP settings..."
local encryption="plain"
local verify_certs="false"
if [[ "$USE_SSL" == true ]]; then
encryption="simple_tls"
verify_certs="true"
fi
# Create LDAP configuration
cat >> /etc/gitlab/gitlab.rb << EOF
# LDAP Configuration - Added by GitLab LDAP setup script
gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = {
'main' => {
'label' => 'Active Directory',
'host' => '$LDAP_HOST',
'port' => $LDAP_PORT,
'uid' => 'sAMAccountName',
'bind_dn' => '$LDAP_BIND_DN',
'password' => '$LDAP_PASSWORD',
'encryption' => '$encryption',
'verify_certificates' => $verify_certs,
'active_directory' => true,
'allow_username_or_email_login' => true,
'lowercase_usernames' => true,
'block_auto_created_users' => false,
'base' => '$LDAP_BASE_DN',
'user_filter' => '(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))',
'attributes' => {
'username' => ['uid', 'userid', 'sAMAccountName'],
'email' => ['mail', 'email', 'userPrincipalName'],
'name' => 'displayName',
'first_name' => 'givenName',
'last_name' => 'sn'
},
'group_base' => '$GROUP_BASE_DN',
'sync_ssh_keys' => false
}
}
EOF
# Set secure permissions on configuration file
chmod 600 /etc/gitlab/gitlab.rb
chown root:root /etc/gitlab/gitlab.rb
print_status "LDAP configuration added to gitlab.rb"
}
# Apply configuration and restart GitLab
apply_config() {
print_status "[6/6] Applying configuration and restarting GitLab..."
print_warning "This may take several minutes..."
if ! gitlab-ctl reconfigure; then
print_error "Failed to reconfigure GitLab"
exit 1
fi
if ! gitlab-ctl restart; then
print_error "Failed to restart GitLab services"
exit 1
fi
print_status "GitLab configuration applied and services restarted"
}
# Verify LDAP configuration
verify_config() {
print_status "Verifying LDAP configuration..."
# Wait for GitLab to fully start
sleep 30
if ! gitlab-rake gitlab:ldap:check > /dev/null 2>&1; then
print_warning "LDAP verification check returned warnings. Please review the configuration"
else
print_status "LDAP configuration verification successful"
fi
}
# Main execution
main() {
print_status "Starting GitLab LDAP/Active Directory integration setup"
check_privileges
detect_distro
parse_args "$@"
install_ldap_tools
test_ldap_connectivity
check_gitlab
backup_config
configure_ldap
apply_config
verify_config
print_status "GitLab LDAP integration setup completed successfully!"
echo
print_status "Next steps:"
echo "1. Test LDAP login with an AD user account"
echo "2. Configure group-based access control if needed"
echo "3. Review GitLab LDAP logs: gitlab-ctl tail gitlab-rails"
echo "4. For SSL setup, install your AD CA certificate and update verify_certificates setting"
}
main "$@"
Review the script before running. Execute with: bash install.sh