nsswitch.conf, getent and SSSD: Where User Accounts Come From
/etc/passwd is one possible source of user accounts, not the definition of them. Which sources a system consults, in which order, is decided by a single file most people never open.
The switch
cat /etc/nsswitch.conf
passwd: files systemd sss
group: files systemd sss
shadow: files sss
gshadow: files
hosts: files mdns4_minimal [NOTFOUND=return] dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis sss
automount: files sss
sudoers: files sss
Each line is a database and the ordered list of backends to try.
When something calls getpwnam("alice"), glibc consults this file, tries files first, then systemd, then sss, and returns the first answer. The calling program knows nothing about where the answer came from.
| Backend | Source |
|---|---|
files | /etc/passwd, /etc/group, /etc/hosts |
dns | DNS, for hosts only |
sss | SSSD, so LDAP, Active Directory, FreeIPA |
systemd | Dynamic users from DynamicUser=yes units |
mymachines | Containers and VMs managed by systemd |
mdns4_minimal | Avahi, for .local names |
resolve | systemd-resolved |
ldap | Direct LDAP via nss-ldapd |
db | Compiled Berkeley DB files |
nis | NIS, long obsolete |
files first, always. If a directory server is unreachable and files is second, resolving root waits for a network timeout, and a machine that cannot resolve root quickly is a machine you cannot rescue.
Action syntax
hosts: files mdns4_minimal [NOTFOUND=return] dns
The bracketed part controls what happens on a given status rather than just falling through.
| Status | Meaning |
|---|---|
SUCCESS | Found |
NOTFOUND | Backend answered, no such entry |
UNAVAIL | Backend not available at all |
TRYAGAIN | Temporary failure |
Actions are return to stop, continue to try the next, and merge to combine group memberships.
[NOTFOUND=return] after mdns4_minimal means: if Avahi definitively says no such .local host, stop rather than asking DNS. That avoids sending every .local lookup to a public resolver, which both leaks names and is slow.
merge is worth knowing for groups:
group: files [SUCCESS=merge] sss
Without it, a user in a local group and a directory group gets only the first match. With it, memberships from both combine, which is usually what an administrator intends.
getent
# every user from every source
getent passwd
getent passwd alice
# groups, including directory groups
getent group developers
# hostnames, through the whole chain
getent hosts example.com
# services, protocols
getent services 443
getent is the correct way to ask “does this account exist”. Reading /etc/passwd shows local accounts only, so on a machine joined to a directory the file tells you almost nothing.
# the diagnostic pair
grep '^alice:' /etc/passwd # nothing
getent passwd alice # alice:*:10042:10042:Alice:/home/alice:/bin/bash
That difference is the whole point of the switch.
# which source answered
getent -s files passwd alice
getent -s sss passwd alice
-s restricts to one backend, which is how you find out whether the local files or the directory is providing an account, and that answers “why does this user have the wrong home directory”.
Adding a directory with SSSD
SSSD is the client daemon for LDAP, Active Directory and FreeIPA. It provides the sss backend for nsswitch and a PAM module for authentication, and it caches so that a laptop off the network still works.
sudo apt install sssd sssd-tools libnss-sss libpam-sss
sudo dnf install sssd sssd-tools
Joining Active Directory
sudo apt install realmd adcli sssd samba-common-bin oddjob oddjob-mkhomedir
realm discover example.com
sudo realm join --user=Administrator example.com
realm list
realm join does a great deal: creates the computer account, writes the SSSD config, updates nsswitch and PAM, and configures Kerberos. On a supported setup it genuinely is close to one command.
# verify identity resolution
getent passwd alice@example.com
id alice@example.com
# then authentication
su - alice@example.com
Check getent before su. If identity does not resolve, authentication cannot possibly work, and testing them in that order tells you which half is broken.
LDAP directly
# /etc/sssd/sssd.conf, mode 600
[sssd]
domains = ldap.example.com
services = nss, pam
config_file_version = 2
[domain/ldap.example.com]
id_provider = ldap
auth_provider = ldap
ldap_uri = ldaps://ldap.example.com
ldap_search_base = dc=example,dc=com
ldap_tls_reqcert = demand
ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt
cache_credentials = true
entry_cache_timeout = 600
# what a user gets
override_homedir = /home/%u
default_shell = /bin/bash
# who may log in at all
access_provider = ldap
ldap_access_filter = memberOf=cn=linuxusers,ou=groups,dc=example,dc=com
sudo chmod 600 /etc/sssd/sssd.conf
sudo systemctl enable --now sssd
SSSD refuses to start if the config is not mode 600, which is a deliberate guard since the file can contain a bind password.
ldap_tls_reqcert = demand is not optional. Without certificate verification, anything that can intercept the connection can impersonate your directory, and the directory is what decides who is root.
cache_credentials = true is what makes a laptop usable. Successful logins are cached, so a user can log in without the directory being reachable.
ldap_access_filter is the difference between “every account in the company can log into this server” and “the people who should”. Without an access provider, identity resolution alone grants login.
# home directories, since a directory account has no local one
sudo pam-auth-update --enable mkhomedir
Or configure pam_mkhomedir directly. Without it, users authenticate successfully and land in a directory that does not exist, which presents as a broken shell. Our PAM guide covers the session stack where that belongs.
Identity and authentication are separate
The distinction that causes the most confusion:
nsswitch answers “who is this”: username to UID, GID, home directory, shell.
PAM answers “may they come in”: credentials, account status, access rules.
# identity works
getent passwd alice@example.com # returns a line
id alice@example.com # returns uid and groups
# authentication does not
su - alice@example.com # Permission denied
sudo journalctl -f | grep -i sssd # find out why
An account visible to getent that cannot log in means PAM refused, or the shell is nologin, or the home directory is missing. Three different fixes, and the auth log names which.
When it breaks
# is sssd running and healthy
systemctl status sssd
sudo sssctl domain-status example.com
# is the cache serving stale data
sudo sss_cache -E # expire everything
sudo systemctl stop sssd
sudo rm -f /var/lib/sss/db/*
sudo systemctl start sssd
Clearing the cache is the standard first move when a user’s attributes changed in the directory and the machine has not noticed.
# raise the log level
# in sssd.conf, per section
# debug_level = 6
sudo systemctl restart sssd
sudo tail -f /var/log/sssd/sssd_example.com.log
Slow logins are nearly always an unreachable server the client is waiting on:
# is every server in the config actually up
ldapsearch -x -H ldaps://ldap.example.com -b '' -s base
nc -zv ldap.example.com 636
# time the lookup
time getent passwd alice@example.com
A second address in ldap_uri for a host that no longer exists adds its full timeout to every cache miss. Removing it is usually the entire fix.
# verify files comes first
head -3 /etc/nsswitch.conf
If sss precedes files, local account lookups go to the network first. On a machine whose directory is down, that is the difference between a slow boot and no boot.
Keep local access
The thing to arrange before you need it.
# a local account that does not depend on the directory
sudo useradd -m -G sudo localadmin
sudo passwd localadmin
# confirm it resolves from files alone
getent -s files passwd localadmin
A machine whose only administrative accounts live in the directory is a machine you cannot fix when the directory is unreachable. One local account with sudo, a known password, and files first in nsswitch.
# and check you can still get in single user
# from the GRUB menu, add to the kernel line:
# systemd.unit=rescue.target
Our managing user accounts guide covers the local side, and ssh certificate authority is worth considering as a lighter alternative to a full directory when the requirement is really just centralised ssh access.
Frequently Asked Questions
What does nsswitch.conf do?
It tells the name service switch which sources to consult for each kind of lookup, and in what order. Users, groups, hostnames, services and netgroups each get a line listing backends such as files, systemd, dns or sss. Programs call standard library functions and the switch decides where the answer comes from.
What is the difference between getent passwd and reading /etc/passwd?
Reading the file shows only local accounts. getent passwd goes through the name service switch, so it returns accounts from every configured source including a directory service. If a user can log in but does not appear in the file, that is the difference.
What is the difference between nsswitch and PAM?
nsswitch answers who exists: it resolves a username to a UID, home directory and shell. PAM answers whether they may come in: it checks credentials and account restrictions. A directory setup needs both, which is why an account can be visible to getent and still refuse to authenticate.
Why does a user exist according to getent but cannot log in?
Because identity and authentication are separate. nsswitch found the account, and PAM rejected the login, or the shell is nologin, or the home directory does not exist and nothing creates it. Check the auth log, which names the module that refused.
Should I use SSSD or nslcd for LDAP?
SSSD, in nearly every case. It caches credentials so a laptop works offline, handles Kerberos, and integrates with Active Directory and FreeIPA properly. nslcd is simpler and has no offline cache, which makes it unsuitable for anything that is not always connected.
Why does login take a long time on a machine joined to a directory?
Usually an unreachable directory server that the client is waiting to time out on. Check that every server in the config responds, reduce the timeouts, and make sure the files entry comes first in nsswitch so local accounts resolve without touching the network.