diff --git a/files/gitlab-ldap-sync.py b/files/gitlab-ldap-sync.py
index 1e3539121feb69242450c4eb9f42f6e0b941b65c..30f09b8001ee43af6222900aa9c3d770db69f025 100644
--- a/files/gitlab-ldap-sync.py
+++ b/files/gitlab-ldap-sync.py
@@ -37,6 +37,7 @@ import ssl
 import secrets
 import json
 import logging
+import re
 
 import ldap3
 import gitlab
@@ -62,14 +63,41 @@ def connect_ldap(host, port, encryption, ca_file, bind_dn, bind_passwd):
 	conn.search = search
 	return conn
 
+def sanitize_username(username):
+	# Gitlab's algorithm as of Gitlab v17.5
+	# Gitlab::Slug::Path.generate
+	#  EXTRACT_LOCAL_EMAIL_PART
+	username = re.sub(r'@.*$', '', username)
+	#  FORBIDDEN_CHARACTERS
+	username = re.sub(r'[^a-zA-Z0-9_.-]', '', username)
+	#  PATH_TRAILING_VIOLATIONS
+	for word in ('.atom', '.git', '.'):
+		if username.endswith(word):
+			username = username[:-len(word)]
+	#  LEADING_DASHES
+	username = username.lstrip('-')
+	#  DEFAULT_SLUG
+	username = username or 'blank'
+
+	# Gitlab::Auth::ExternalUsernameSanitizer.sanitize
+	#  remove leading - , _ , or . characters
+	#  remove trailing - , _ or . characters
+	username = username.strip('.-_')
+	#  remove consecutive - , _ , or . characters
+	username = re.sub(r'([_.-])[_.-]+', r'\1', username)
+	return username
+
 def sync_user(gl, dn, username, name, email, is_admin=False, ldap_provider='ldapmain', dry_run=True):
 	logging.debug('Synchronizing user %s', dn)
 	user = (gl.users.list(provider=ldap_provider, extern_uid=dn) or [None])[0]
 	if user is None:
 		logging.debug('No corresponding Gitlab user found')
 		logging.info('Creating user %s', dn)
+		sanitized_username = sanitize_username(username)
+		if sanitized_username != username:
+			logging.debug('Changing username "%s" to "%s" to meet Gitlab\'s requirements'%(username, sanitized_username))
 		attrs = {'provider': ldap_provider, 'extern_uid': dn}
-		attrs['username'] = username
+		attrs['username'] = sanitized_username
 		attrs['name'] = name
 		attrs['email'] = email
 		attrs['admin'] = is_admin
@@ -89,7 +117,7 @@ def sync_user(gl, dn, username, name, email, is_admin=False, ldap_provider='ldap
 					logging.debug('User creation with username "%s" failed: %s', attrs['username'], e.error_message)
 				else:
 					logging.exception('User creation with username "%s" failed', attrs['username'])
-			attrs['username'] = username + '%d'%(i + 1)
+			attrs['username'] = sanitized_username + '%d'%(i + 1)
 		logging.debug('Giving up user creation')
 		return
 	logging.debug('Found corresponding Gitlab user "%s", synchronizing attributes', user.username)