Joining AlmaLinux 9 to an Active Directory domain with SSSD
Complete guide to joining an AlmaLinux 9 server to an Active Directory domain — LDAP/Kerberos authentication, AD-based sudo, automatic home directories.
Table of Contents
Joining a Linux server to an Active Directory domain lets domain users log in with their AD credentials and benefit from centralized policies. Here is how to do it cleanly on AlmaLinux 9 with SSSD and realmd.
Prerequisites
- An up-to-date AlmaLinux 9
- Network access to the domain controller (ports 88, 389, 636, 3268, 3269)
- An AD account allowed to join machines to the domain
- DNS set up to resolve the AD domain
Checking the network
# Check DNS resolution of the AD domain
dig +short domain.local _ldap._tcp.domain.local SRV
# → must return the DC's IP and LDAP port
# Ping the DC
ping dc1.domain.local
# Check the required ports
for port in 88 389 636; do
nc -zv dc1.domain.local $port && echo "Port $port OK" || echo "Port $port CLOSED"
done
DNS must resolve the AD domain and its SRV records. Set the DCs as DNS servers in /etc/resolv.conf before you start.
Configuring DNS
# /etc/resolv.conf
search domain.local
nameserver 192.168.x.10 # DC1
nameserver 192.168.x.11 # DC2
# Check
nslookup domain.local
nslookup dc1.domain.local
Installing the packages
dnf install -y \
realmd \
sssd \
sssd-ad \
sssd-tools \
oddjob \
oddjob-mkhomedir \
adcli \
samba-common-tools \
krb5-workstation \
openldap-clients
Joining the domain
# Discover the domain (without joining)
realm discover domain.local
# Join the domain
realm join -U administrator domain.local
# Enter the AD account password when prompted
# Check the join
realm list
Expected output:
root@alma9:~# realm list
domain.local
type: kerberos
realm-name: DOMAIN.LOCAL
domain-name: domain.local
configured: kerberos-member
server-software: active-directory
client-software: sssd
required-package: oddjob
required-package: oddjob-mkhomedir
required-package: sssd
required-package: adcli
required-package: samba-common-tools
login-formats: %U@domain.local
login-policy: allow-realm-logins
SSSD configuration
/etc/sssd/sssd.conf is generated automatically by realm join, but a few adjustments are recommended:
# /etc/sssd/sssd.conf
[sssd]
domains = domain.local
config_file_version = 2
services = nss, pam
[domain/domain.local]
default_shell = /bin/bash
krb5_store_password_if_offline = True
cache_credentials = True
krb5_realm = DOMAIN.LOCAL
realmd_tags = manages-system joined-with-adcli
id_provider = ad
fallback_homedir = /home/%u@%d
ad_domain = domain.local
use_fully_qualified_names = False # ← log in without @domain.local
ldap_id_mapping = True
access_provider = ad
# Performance
ad_gpo_access_control = disabled # Disable Linux GPO enforcement (optional)
ldap_referrals = false
# Cache
cache_credentials = true
offline_credentials_expiration = 7
# Timeouts
ldap_network_timeout = 3
ldap_opt_timeout = 3
Without this option, users must log in as user@domain.local. With False, ‘user’ is enough — much more convenient.
# Apply the permissions (mandatory)
chmod 600 /etc/sssd/sssd.conf
# Restart SSSD
systemctl restart sssd
systemctl enable sssd
Automatic home directory creation
# Create the home directory automatically on first login
authselect select sssd with-mkhomedir --force
# Enable the oddjobd service
systemctl enable --now oddjobd
Testing authentication
# Check that an AD user is visible
id user@domain.local
# With use_fully_qualified_names = False:
id user
# Test Kerberos authentication
kinit administrator@DOMAIN.LOCAL
klist # Shows the Kerberos ticket
# Test an SSH login with an AD account
ssh user@localhost
Allowing only some AD groups
By default, every AD user can log in. Restrict access:
# Allow only the "Linux-Admins" AD group
realm permit -g 'Linux-Admins@domain.local'
# Deny everyone except the allowed groups
realm deny --all
realm permit -g 'Linux-Admins@domain.local'
realm permit -g 'Linux-Users@domain.local'
# Check
realm list
Sudo through Active Directory groups
Create a sudoers file for your AD groups:
# /etc/sudoers.d/ad-admins
# Full sudo for the "Linux-Admins" AD group
%Linux-Admins@domain.local ALL=(ALL) ALL
# Passwordless sudo for infrastructure admins
%Linux-Infra-Admins@domain.local ALL=(ALL) NOPASSWD: ALL
# Check the syntax
visudo -c -f /etc/sudoers.d/ad-admins
# Test
su - admin-user@domain.local
sudo whoami # → root
admin-user@alma9:~$ sudo whoami
root
Common problems
SSSD won’t start
journalctl -u sssd -n 50 --no-pager
# Frequent culprit: sssd.conf permissions
chmod 600 /etc/sssd/sssd.conf
chown root:root /etc/sssd/sssd.conf
# Clear the SSSD cache (for "ghost" users)
sss_cache -E
systemctl restart sssd
AD user not found
# Test the LDAP connection directly
ldapsearch -H ldap://dc1.domain.local \
-D "CN=svc-linux,OU=Services,DC=domain,DC=local" \
-w PASS \
-b "DC=domain,DC=local" \
"(sAMAccountName=user)"
# Force a refresh
sss_cache -u user
id user
Expired or invalid Kerberos ticket
# Check the ticket
klist
# Renew it manually
kinit user@DOMAIN.LOCAL
# Sync the clock (Kerberos is sensitive to drift)
timedatectl status
chronyc tracking
# If the drift is > 5 min → Kerberos fails
chronyc makestep
Leaving the domain
realm leave domain.local
# The computer account is removed from AD
Final check
# Full test
getent passwd user # The user is visible
getent group 'Linux-Admins' # The AD group is visible
su - user # Login → home created automatically
sudo -l # Correct sudo rights
AD users can now SSH into the Linux server with their domain credentials. Their home directory is created automatically on first login.
Special case — authentication without joining (simple LDAP bind)
If you can’t join the machine to the domain (restricted environments), an alternative is a simple LDAP bind with nslcd:
dnf install -y nss-pam-ldapd nslcd
# /etc/nslcd.conf
uri ldap://dc1.domain.local
base dc=domain,dc=local
binddn CN=svc-linux,OU=Services,DC=domain,DC=local
bindpw YOUR_PASSWORD
ssl start_tls
tls_reqcert never
scope sub
filter passwd (&(objectClass=user)(memberOf=CN=Linux-Users,OU=Groups,DC=domain,DC=local))
map passwd uid sAMAccountName
map passwd homeDirectory unixHomeDirectory
map passwd gecos displayName
This method is less integrated (no Kerberos, no SSO) but works in constrained environments.
Comments