Active Directory Login on Linux with SSSD: A Step-by-Step Tutorial
sudo realm join --user=svc-join corp.example.com
By the end of this tutorial a Linux server will be a member of your Windows Active Directory (AD) domain. People will log in to it
(console, SSH, sudo) with their normal domain username and password, and you will control who may log in and who gets sudo
through AD groups, so accounts are managed in ONE place instead of on every server.
It uses SSSD (System Security Services Daemon), the standard Linux client for AD, with realmd to make the join easy.
Steps are given for Ubuntu/Debian and RHEL family systems (RHEL, Rocky, Alma, Fedora). Nothing here changes your AD schema.
Use a test VM first. Mistakes in login configuration can lock you out of a server.
What you will build
Windows side: A domain controller (DC) for the domain corp.example.com (Kerberos realm CORP.EXAMPLE.COM)
An OU for Linux servers, a service account that may join computers, and security groups: linux-users and linux-admins
Linux side: A server named server01.corp.example.com that authenticates AD users through SSSD, creates home directories on first login,
lets members of linux-users log in, and gives members of linux-admins sudo
Replace corp.example.com, CORP.EXAMPLE.COM, dc01 and the group names with your own. The realm name is the domain name in UPPER CASE.
How the pieces fit together
Active Directory The directory: users, groups, computers, and a Kerberos and LDAP server (the domain controller)
Kerberos Proves who you are (password checks, tickets, single sign-on). Needs correct DNS and clocks
LDAP Looks up who exists: user names, group memberships, IDs
SSSD The Linux service that talks to AD, caches the answers, and works for logins even if the DC is briefly unreachable
NSS and PAM The Linux hooks: NSS answers "who is this user?" (id, getent, ls -l) and PAM decides "may they log in?" (ssh, su, sudo, console)
realmd The helper that discovers the domain, joins it, and writes a working SSSD configuration
adcli / net The tools that create the computer account in AD and its Kerberos keytab (/etc/krb5.keytab)
A login: you type user@corp.example.com and a password > PAM asks SSSD > SSSD asks a domain controller (Kerberos) > success > your groups and UID come via NSS.
Before you start: prerequisites checklist
[ ] A working domain controller you can reach, and a domain admin (or a delegated account) to join computers
[ ] The Linux server has a FULLY QUALIFIED hostname, and a DNS record can be created for it (AD DNS can do this automatically)
[ ] DNS: the Linux server uses the domain controller (or a DNS server that forwards AD zones) as its resolver. This is the #1 cause of failed joins
[ ] Time: the clocks of the server and the DC differ by less than 5 minutes (Kerberos rejects larger differences)
[ ] Network: these ports open from the server to the DC(s):
DNS 53 (tcp/udp) Kerberos 88 (tcp/udp) Kerberos password change 464 (tcp/udp) LDAP 389 (tcp/udp) LDAPS 636 (tcp)
Global Catalog 3268 and 3269 (tcp) NTP 123 (udp) SMB 445 (tcp) and RPC 135 (tcp) if you join with the Samba tools
[ ] Console or hypervisor access to the server, so a mistake does not lock you out. Take a snapshot before you begin
[ ] A second SSH session kept open as root while you change login settings (do not close it until you have tested)
On the Windows side (do once)
1. In "Active Directory Users and Computers":
- Create an OU for Linux servers: OU=Linux,OU=Servers,DC=corp,DC=example,DC=com
- Create security groups: linux-users (may log in) linux-admins (may use sudo)
- Create a join account (for example svc-join) with a strong password, and delegate to it, on the Linux OU:
"Create, delete and manage computer accounts" (right-click the OU > Delegate Control...)
This is safer than using Domain Admins for every join
2. Add test users to the groups
3. Make sure the DC's DNS zone allows dynamic updates (secure only is fine), so servers can register their names
4. Note the DC name (dc01.corp.example.com) and IP address
Step 1: Set the hostname and check the basics on Linux
sudo hostnamectl set-hostname server01.corp.example.com
hostnamectl # confirm the static hostname
hostname -f # should print server01.corp.example.com
cat /etc/hosts # make sure 127.0.1.1 (Debian/Ubuntu) or the server's IP maps to the FQDN too:
# 192.168.56.20 server01.corp.example.com server01
Keep the hostname short enough: AD computer names (the part before the first dot) are limited to 15 characters. Longer names are shortened, and that can cause surprises.
Step 2: Point DNS at the domain controller
Check what the server uses now:
resolvectl status # systemd-resolved (Ubuntu). Look at "DNS Servers" and "DNS Domain"
cat /etc/resolv.conf
Set it. Choose the method your system uses:
Netplan (Ubuntu), in /etc/netplan/*.yaml under your interface, then sudo netplan apply :
nameservers:
addresses: [192.168.56.10]
search: [corp.example.com]
NetworkManager (RHEL family):
nmcli con mod "System eth0" ipv4.dns 192.168.56.10 ipv4.dns-search corp.example.com ipv4.ignore-auto-dns yes
nmcli con up "System eth0"
Test that AD's special DNS records resolve. If this fails, STOP and fix DNS before you go on:
dig +short corp.example.com # the IP addresses of the DCs
dig +short -t SRV _ldap._tcp.dc._msdcs.corp.example.com # should list your domain controllers
dig +short -t SRV _kerberos._tcp.corp.example.com
nslookup dc01.corp.example.com
ping -c2 dc01.corp.example.com
Step 3: Synchronize the clock
sudo apt install -y chrony # Ubuntu/Debian (RHEL family: chrony is normally installed: sudo dnf install -y chrony)
sudo nano /etc/chrony/chrony.conf # RHEL: /etc/chrony.conf replace the pool lines with: server dc01.corp.example.com iburst
sudo systemctl enable --now chrony # RHEL: the service is chronyd
chronyc tracking # "System time" should be within a fraction of a second
chronyc sources -v
timedatectl # "System clock synchronized: yes"
Windows domain controllers are time servers for the domain, so syncing to a DC (or the same source it uses) keeps you within Kerberos' 5-minute limit.
Step 4: Install the packages
Ubuntu/Debian:
sudo apt update
sudo apt install -y realmd sssd sssd-tools sssd-ad libnss-sss libpam-sss adcli samba-common-bin oddjob oddjob-mkhomedir packagekit krb5-user
(krb5-user asks for a default realm: type CORP.EXAMPLE.COM in UPPER case. Servers can be left blank. Press Enter for the others)
RHEL / Rocky / Alma / Fedora:
sudo dnf install -y realmd sssd sssd-tools sssd-ad adcli oddjob oddjob-mkhomedir samba-common-tools krb5-workstation authselect
sudo systemctl enable --now oddjobd
Check that realmd will use SSSD (the default): cat /etc/realmd.conf (usually absent. If present, default-client should be sssd)
Step 5: Discover the domain
realm discover corp.example.com
Expected output (names will match your domain):
corp.example.com
type: kerberos
realm-name: CORP.EXAMPLE.COM
domain-name: corp.example.com
configured: no
server-software: active-directory
client-software: sssd
required-package: sssd-tools ...
If it says "No such realm found", go back to Step 2 (DNS). "server-software: active-directory" means it found AD.
Get more detail while troubleshooting: realm discover --verbose corp.example.com
Step 6: Join the domain
sudo realm join --user=svc-join corp.example.com
(you are asked for the password of svc-join)
Useful options:
--computer-ou="OU=Linux,OU=Servers,DC=corp,DC=example,DC=com" Put the computer account in the right OU (recommended)
--os-name="Ubuntu" --os-version="24.04" Record the OS in the computer object
--computer-name=SERVER01 Choose the computer name
--verbose Show what is happening (very helpful when it fails)
--unattended Do not prompt (with the password piped: echo 'Secret' | sudo realm join --user=svc-join --unattended corp.example.com)
Do not leave passwords in shell history: use the prompt, or a protected file and a redirect.
Check that it worked:
realm list # shows configured: kerberos-member, login-formats, login-policy
sudo klist -k # the machine keytab /etc/krb5.keytab, with SERVER01$@CORP.EXAMPLE.COM entries
sudo systemctl status sssd # active (running)
In AD Users and Computers you should now see SERVER01 in the Linux OU. The join also created /etc/sssd/sssd.conf and enabled the services.
Step 7: Test that users can be looked up
id jsmith@corp.example.com
uid=1234567890(jsmith@corp.example.com) gid=1234567890(domain users@corp.example.com) groups=...(linux-users@corp.example.com),...
getent passwd jsmith@corp.example.com
getent group linux-admins@corp.example.com
getent group "domain users@corp.example.com" # quote names that contain spaces
The long numeric IDs are normal: with the default "ID mapping", SSSD computes a UID from the user's Windows SID. The same user gets the SAME UID on every SSSD server in the domain.
If id says "no such user": check spelling (user@domain), then wait a few seconds, then see Troubleshooting. Do NOT expect "getent passwd" to list everyone. SSSD does not enumerate by default.
Step 8: Enable home directory creation and check PAM
A user's home directory must exist on first login. Turn on automatic creation:
Ubuntu/Debian:
sudo pam-auth-update --enable mkhomedir # or: sudo pam-auth-update and tick "Create home directory on login"
grep -R "pam_mkhomedir" /etc/pam.d/ | head
RHEL family (authselect manages PAM and NSS):
sudo authselect select sssd with-mkhomedir --force
sudo authselect current # profile: sssd, features: with-mkhomedir
Also make sure NSS uses sss (realmd normally does this):
grep -E '^(passwd|group|shadow)' /etc/nsswitch.conf # should include "sss", for example: passwd: files systemd sss
Test a real login from the same machine (keep your root session open):
su - jsmith@corp.example.com
pwd; id; exit
Then test SSH from another computer:
ssh jsmith@corp.example.com@server01.corp.example.com # username@domain@host or: ssh -l jsmith@corp.example.com server01.corp.example.com
SSH must allow password logins and PAM (the defaults on most systems): grep -Ei '^(UsePAM|PasswordAuthentication|KbdInteractiveAuthentication)' /etc/ssh/sshd_config*
Since /etc/ssh/sshd_config.d/ can override the main file, check that folder too, and reload after a change: sudo systemctl reload ssh (RHEL: sshd)
Step 9: Decide who may log in (access control)
By default, realmd allows ALL domain users to log in. That is rarely what you want on a server. Pick ONE method below.
Method A: realm permit (simple, and easy to read)
sudo realm deny --all # nobody from the domain (root and local users still work)
sudo realm permit -g linux-admins@corp.example.com # allow a group
sudo realm permit -g linux-users@corp.example.com
sudo realm permit jsmith@corp.example.com # or one user
realm list # shows login-policy: allow-permitted-logins and the permitted groups
This sets access_provider = simple with simple_allow_groups in /etc/sssd/sssd.conf. Names containing spaces need quotes.
Method B: an AD filter (LDAP rule evaluated live)
Edit /etc/sssd/sssd.conf and, in the [domain/...] section, set:
access_provider = ad
ad_access_filter = (|(memberOf=CN=linux-users,OU=Groups,DC=corp,DC=example,DC=com)(memberOf=CN=linux-admins,OU=Groups,DC=corp,DC=example,DC=com))
It uses each group's full distinguished name (DN). It only sees DIRECT membership unless you use the nested-group matching rule (1.2.840.113556.1.4.1941).
Nested example: ad_access_filter = (memberOf:1.2.840.113556.1.4.1941:=CN=linux-users,OU=Groups,DC=corp,DC=example,DC=com)
Method C: Group Policy (GPO) rules
SSSD can enforce the Windows policies "Allow log on locally" (console) and "Allow log on through Remote Desktop Services" (remote services like SSH), applied per Linux service.
ad_gpo_access_control = enforcing # or permissive (log denials only) or disabled
Careful: an enforcing GPO that does not list your users will lock everyone out. Test with "permissive" first and read the logs. Also see ad_gpo_map_* options for PAM services.
Apply and reload after any change:
sudo systemctl restart sssd
sudo sss_cache -E # clear cached data so the new rules apply now
Test: a member of the permitted group can log in, and someone outside it is refused ("Permission denied").
Step 10: Give AD groups sudo
Create a sudoers file (ALWAYS use visudo so a typo cannot break sudo):
sudo visudo -f /etc/sudoers.d/linux-admins
Add:
%linux-admins@corp.example.com ALL=(ALL) ALL
For a group name that contains spaces, escape each space with a backslash: %domain\ admins@corp.example.com ALL=(ALL) ALL
Passwordless sudo is convenient and risky: use "NOPASSWD:" only where needed: %linux-ops@corp.example.com ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
sudo chmod 440 /etc/sudoers.d/linux-admins
sudo visudo -c # check syntax
sudo -l -U jsmith@corp.example.com # what may this user do?
Alternative: store sudo rules IN Active Directory (requires extending the AD schema with sudoRole). Add "sudo" to services in sssd.conf and "sudoers: files sss" in /etc/nsswitch.conf. Most teams use local sudoers files that reference AD groups, as above.
Step 11: Choose friendlier names (optional)
By default users are "user@corp.example.com". To allow the short name "user", edit /etc/sssd/sssd.conf in the [domain/corp.example.com] section:
use_fully_qualified_names = False
fallback_homedir = /home/%u
Then: sudo systemctl restart sssd sudo sss_cache -E
Trade-offs: short names are nicer but ambiguous if you trust several domains or have a local user with the same name. Home directories change too (/home/%u instead of /home/%u@%d).
Existing files and homes belong to the old name/ID mapping: choose your scheme BEFORE users start working.
Other useful settings:
default_shell = /bin/bash
override_homedir = /home/%d/%u # a fixed layout (overrides AD's homeDirectory attribute)
ldap_id_mapping = False # use the uidNumber/gidNumber attributes stored in AD (POSIX attributes) instead of SID-based IDs
Step 12: Keep user IDs consistent (important for NFS and shared files)
Two ways to get UIDs and GIDs:
ID mapping (the default, ldap_id_mapping = True) SSSD computes IDs from the SID. Same on every SSSD host, no AD changes needed. But they are large numbers, and differ from other systems (Samba/winbind, macOS, Solaris)
POSIX attributes (ldap_id_mapping = False) AD stores uidNumber, gidNumber, unixHomeDirectory and loginShell on each user and group (set them in AD Users and Computers > Attribute Editor, or with tooling). You control exact IDs, which suits shared NFS storage
Do not switch later: files would have the wrong owners. After changing, clear the cache and (if needed) the SSSD database:
sudo systemctl stop sssd
sudo rm -f /var/lib/sss/db/* /var/lib/sss/mc/*
sudo systemctl start sssd
Step 13: Kerberos single sign-on (optional)
Get a ticket and use SSH without typing the password again:
kinit jsmith@CORP.EXAMPLE.COM # the realm is UPPER case
klist # shows your ticket (TGT) and expiry
ssh -o GSSAPIAuthentication=yes -o GSSAPIDelegateCredentials=yes server02.corp.example.com
kdestroy # throw the tickets away
Server side (in /etc/ssh/sshd_config): GSSAPIAuthentication yes then reload sshd. Client side: GSSAPIAuthentication yes in ~/.ssh/config
SSSD gets a ticket automatically when a domain user logs in with a password, so klist works right after login.
You can keep SSH public keys in AD and let sshd read them:
In sssd.conf ([domain/...]): ldap_user_ssh_public_key = altSecurityIdentities (AD has no SSH key attribute by default: pick one that stores the key. See man sssd-ldap and man sss_ssh_authorizedkeys)
In sshd_config: AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys AuthorizedKeysCommandUser nobody
The configuration file explained (/etc/sssd/sssd.conf)
Permissions must be exactly: sudo chmod 600 /etc/sssd/sssd.conf ; sudo chown root:root /etc/sssd/sssd.conf (SSSD refuses to start otherwise)
[sssd]
domains = corp.example.com
config_file_version = 2
services = nss, pam # the services to run (add "sudo" or "ssh" if you use them)
[domain/corp.example.com]
id_provider = ad # look up users and groups in Active Directory
access_provider = ad # (or simple, when you used realm permit)
auth_provider = ad # (default: same as id_provider) Kerberos password checks
ad_domain = corp.example.com
krb5_realm = CORP.EXAMPLE.COM
realmd_tags = manages-system joined-with-adcli
default_shell = /bin/bash
use_fully_qualified_names = True
fallback_homedir = /home/%u@%d
ldap_id_mapping = True
cache_credentials = True # let people log in when the DC is unreachable (uses a cached password hash)
krb5_store_password_if_offline = True # hold the password to get a ticket once the DC is back
Settings you may want to add:
offline_credentials_expiration = 7 # days a cached login stays valid while offline (0 = never expires)
entry_cache_timeout = 5400 # how long a lookup is cached, in seconds
ad_maximum_machine_account_password_age = 30 # rotate the machine password every 30 days
dyndns_update = True # register the server's IP in AD DNS
ad_hostname = server01.corp.example.com # if the local hostname differs from the AD name
ad_site = Default-First-Site-Name # prefer the DCs of this AD site
ad_server = dc01.corp.example.com # (optional) a fixed list of DCs, instead of automatic discovery through DNS
case_sensitive = False # default for AD is case-insensitive names
Check the file: sudo sssctl config-check After every edit: sudo systemctl restart sssd
On modern systems SSSD can also read extra drop-in files from /etc/sssd/conf.d/*.conf (each ending in .conf, mode 600).
Day-to-day commands
realm list # what domain am I in, and the login policy?
sudo sssctl domain-list sudo sssctl domain-status corp.example.com # online or offline, and which DC is used
sudo sssctl user-checks jsmith@corp.example.com # full check: lookup, groups, and whether PAM would allow the login
sudo sssctl user-show jsmith@corp.example.com # what SSSD has cached for this user
id jsmith@corp.example.com getent passwd jsmith@corp.example.com groups jsmith@corp.example.com
sudo sss_cache -u jsmith@corp.example.com # refresh one user sudo sss_cache -E everything (do this after changing groups in AD)
sudo journalctl -u sssd -f # follow the SSSD service log
ls /var/log/sssd/ # detailed logs per component (sssd_corp.example.com.log, sssd_pam.log, sssd_nss.log)
sudo adcli info corp.example.com # domain and DC information sudo adcli testjoin verify this machine's account works
sudo klist -k /etc/krb5.keytab # the machine's keys
realm permit --all / realm deny --all # open or close domain logins
Password expiry, lockouts and account status come from AD: users change passwords at the console with passwd (Kerberos), or on Windows. A locked or disabled AD account cannot log in.
Troubleshooting
First, turn on detail. In sssd.conf add debug_level = 6 to the [domain/corp.example.com], [nss] and [pam] sections, restart sssd, reproduce the problem, then read /var/log/sssd/*.log
(remove debug_level again afterwards: logs get large and can contain sensitive data).
sudo systemctl restart sssd ; tail -f /var/log/sssd/sssd_pam.log /var/log/sssd/sssd_corp.example.com.log
Work through the layers in order: 1 DNS, 2 time, 3 network, 4 Kerberos, 5 SSSD lookups, 6 PAM/SSH.
"Couldn't find domain" / discover fails DNS is not pointing at AD. Fix Step 2 (dig the SRV records)
"Insufficient permissions to join the domain" The account cannot create computer objects in that OU. Delegate control, or use --computer-ou with an OU it may write to
"Computer account already exists" / "Already joined" Delete the old computer object in AD (or reuse it with adcli --domain-ou), and remove leftovers: sudo realm leave ; sudo rm /etc/krb5.keytab
"Clock skew too great" Time differs more than 5 minutes. Fix chrony (Step 3), and check the timezone
"Cannot find KDC for realm" / "Cannot contact any KDC" DNS or a firewall problem (port 88). Test: nc -zv dc01.corp.example.com 88
"Preauthentication failed" / "Password incorrect" Wrong password, or the user's password expired. Test with kinit user@CORP.EXAMPLE.COM
"KDC has no support for encryption type" The DC and Linux disagree on encryption types (often AD accounts limited to RC4 vs modern crypto policies). Enable AES on the AD accounts, or on RHEL 8/9 as a last resort: sudo update-crypto-policies --set DEFAULT:AD-SUPPORT
"Server not found in Kerberos database" The server name does not match its AD account (SPNs). Check hostname -f, DNS, ad_hostname, and reverse DNS. Run sudo adcli testjoin
id shows the user but login is "Permission denied" Access control: realm permit, ad_access_filter or GPO (Step 9). Use sssctl user-checks, and read sssd_pam.log
Login works, but the user's groups are missing Cache, nesting, or a group lookup limit. Run sudo sss_cache -E and check ldapsearch results. Log out and in again
"su" works but SSH fails (or reverse) Check /etc/ssh/sshd_config (UsePAM yes, PasswordAuthentication yes), files in /etc/ssh/sshd_config.d/, and /var/log/auth.log or journalctl -u ssh
"No such user" after a change sudo systemctl restart sssd ; sudo sss_cache -E ; check the spelling and the name format (user@domain)
Home directory is not created mkhomedir is not enabled: Step 8. On RHEL check oddjobd is running: systemctl status oddjobd
"Failed to start SSSD" / config errors sssd.conf permissions must be 600 owned by root. Run sudo sssctl config-check and journalctl -u sssd
sssd goes offline Domain controller unreachable: sudo sssctl domain-status corp.example.com. Check DNS, firewall and the ad_server setting
Very slow logins DNS or DC discovery timeouts, an unreachable DC in the list, or GPO/large group lookups. Set ad_server or ad_site, lower timeouts, and read the logs
Machine password expired / "Server not found" after weeks The computer account password rotates. Ensure sssd is running (it rotates it), keep the clock right, and run sudo adcli testjoin
Users found with wrong or different UIDs on two servers Different ID mapping settings between servers, or POSIX attributes changed. Use the same sssd.conf approach everywhere, and clear caches
Cache is stale or corrupt sudo systemctl stop sssd ; sudo rm -f /var/lib/sss/db/* /var/lib/sss/mc/* ; sudo systemctl start sssd (cached passwords are lost: users must log in online)
Locked out of the server Log in as a LOCAL admin user or use the console. If PAM is broken, boot to rescue mode, then restore /etc/pam.d/ and /etc/nsswitch.conf from backup (or run authselect select sssd --force on RHEL)
Security best practices
- Use a DEDICATED join account with delegated rights on one OU, not Domain Admins. Protect and rotate its password (or disable it after joining)
- Restrict who can log in: use realm permit or a group filter. Do not leave "all domain users" allowed on servers
- Give sudo through AD groups (linux-admins) and review the membership regularly. Prefer commands allowed by name over ALL
- Keep the machine keytab safe (/etc/krb5.keytab is readable only by root). Anyone with it can act as the server
- SSSD to AD uses Kerberos and LDAP with signing and encryption (SASL GSSAPI). Use LDAPS or StartTLS only for extra LDAP lookups you configure yourself
- Require strong passwords and lockout rules in AD, and consider MFA for SSH (for example a PAM module that adds a second factor, or smart cards and FreeIPA-style tools)
- cache_credentials = True lets people log in offline. Set offline_credentials_expiration to a reasonable number of days, or turn caching off for highly sensitive servers
- Keep the servers patched, keep root SSH disabled (PermitRootLogin no), and log to a central place: watch /var/log/auth.log (Debian) or /var/log/secure (RHEL) for failed logins
- Put Linux servers in a separate OU with its own GPOs, and disable computer accounts for servers you retire (or use realm leave)
- Back up /etc/sssd/, /etc/krb5.conf, /etc/nsswitch.conf and /etc/pam.d before you change them
Leaving the domain, or starting over
sudo realm leave corp.example.com # stop using AD on this machine
sudo realm leave --remove -U svc-join corp.example.com # also delete the computer object in AD (needs rights)
sudo realm list # should now be empty
sudo systemctl disable --now sssd # optional
Then delete the stale computer account in AD if it is still there, and clean local files: sudo rm -f /etc/krb5.keytab
Ubuntu: sudo pam-auth-update (untick SSS) RHEL: sudo authselect select minimal --force (only if you need to return to local-only logins)
Home directories of domain users under /home/ are NOT removed. Delete them yourself when they are no longer needed.
Multiple servers: keep them consistent
Put your steps in a script or an Ansible playbook so every server is joined and configured the same way (packages, /etc/sssd/sssd.conf, realm join with --computer-ou, sudoers file, mkhomedir).
Use the same ID mapping choice everywhere. Manage sssd.conf from one template, and test changes on one machine first. Roll changes out gradually.
Ansible modules to know: ansible.builtin.package, template (for sssd.conf), command (for realm join), lineinfile and service. See the Ansible sheet.
Compare: other ways to join Linux to AD
SSSD + realmd (this tutorial) The standard, best supported. Group-based access control, offline caching, Kerberos SSO, works on all major distributions
winbind (Samba) Older alternative. Needed mainly when the machine ALSO serves Windows file shares with Samba and you need its ID mapping. Configure smb.conf and nsswitch with winbind
pam_ldap / nslcd Old and limited: no Kerberos, no offline caching. Avoid for new setups
FreeIPA / Red Hat IdM A Linux-native identity system that can trust AD (cross-realm). Good when you have many Linux hosts and want Linux-side sudo, HBAC and SSH key management
Azure AD / Entra ID Cloud identity. Linux logins use different tools (for example Azure's AADSSHLoginForLinux VM extension). Not the same as AD DS
Samba as a domain controller Runs AD itself on Linux. A different project entirely
Quick reference
realm discover corp.example.com Can I find the domain?
sudo realm join --user=svc-join --computer-ou="OU=Linux,OU=Servers,DC=corp,DC=example,DC=com" corp.example.com Join
realm list Am I joined?
id user@corp.example.com Is a user visible?
sudo pam-auth-update --enable mkhomedir | sudo authselect select sssd with-mkhomedir --force Home directories on first login
sudo realm deny --all ; sudo realm permit -g linux-users@corp.example.com Who may log in
/etc/sudoers.d/linux-admins: %linux-admins@corp.example.com ALL=(ALL) ALL Who gets sudo
sudo sssctl user-checks user@corp.example.com Diagnose a login
sudo sss_cache -E ; sudo systemctl restart sssd Refresh after AD or config changes
sudo journalctl -u sssd ; /var/log/sssd/ Where to look when it breaks
sudo realm leave corp.example.com Leave the domain
Tips
Fix DNS and time first. Almost every failed join or login comes down to DNS not pointing at AD, or a clock more than 5 minutes off.
Test on a VM with a snapshot, and keep a root session open until you have proved that a new login works.
Use realmd to join, and let it write the first sssd.conf. Then tune a few settings instead of hand-writing everything.
Do not leave "all domain users" allowed on servers. Permit specific AD groups with realm permit or an access filter.
Give sudo to AD groups through a file in /etc/sudoers.d/ edited with visudo, and review the group membership regularly.
Decide on ID mapping and name format (fully qualified or short) before users start, because changing them later changes file ownership.
Use sssctl (user-checks, domain-status) and the logs in /var/log/sssd/ instead of guessing. Turn debug_level off again afterward.
After changing groups in AD, run sudo sss_cache -E, and have users log out and back in.
Use a delegated join account, protect the machine keytab, and consider MFA for SSH.
Script or automate the setup (Ansible) so every server is configured the same way, and document your OU and group layout.