Configure OpenLDAP Client with SSSD on RHEL-Based Linux

Configure OpenLDAP client authentication with SSSD, authselect, StartTLS, and automatic home directories on RHEL, Rocky Linux, AlmaLinux, Oracle Linux, and CentOS Stream.

Published

Updated

Read time 15 min read

Reviewed byDeepak Prasad

OpenLDAP client authentication with SSSD on RHEL-based Linux

This walkthrough wires LDAP login on a separate RHEL-family client through SSSD—getent and id for NSS lookup, password checks through PAM, StartTLS to OpenLDAP, the lab CA in the system trust store, and a home directory created on first login. You will set up sssd.conf, /etc/openldap/ldap.conf, authselect with with-mkhomedir, and confirm an LDAP user can SSH in, not only run ldapsearch.

Part of the OpenLDAP tutorial series.

Complete these lessons first:

Tested on: Rocky Linux 10.2; ldap-server.example.com at 192.168.56.108; ldap-client.example.com at 192.168.56.109; SSSD 2.12.0; OpenLDAP 2.6.10 client utilities.

IMPORTANT
Keep an existing root shell open while changing authentication settings. A malformed SSSD or PAM configuration can prevent new login sessions.

What This Guide Configures

The finished client stack looks like this:

text
RHEL-family client
    ├── NSS → SSSD → LDAP identity lookup
    ├── PAM → SSSD → LDAP password authentication
    └── oddjobd → creates /home/jdoe after first login

SSSD
    └── StartTLS → OpenLDAP server:389
Component Configuration
Client OS RHEL-family 9 or 10
Identity and authentication daemon SSSD
PAM/NSS configuration authselect
LDAP transport StartTLS on port 389
Certificate validation Required (ldap_tls_reqcert = hard)
LDAP server ldap-server.example.com
Search base dc=example,dc=com
User OU ou=people,dc=example,dc=com
Group OU ou=groups,dc=example,dc=com
Test user jdoe
Home-directory creation oddjob-mkhomedir
Related topic Owned elsewhere
Server install, suffix, schemas, DIT Install and configure OpenLDAP on RHEL-based Linux
Server certificates and olcTLS* Configure OpenLDAP TLS on RHEL-based Linux
LDAP sudo rules, automount, SSH keys in LDAP Store Linux sudo rules in OpenLDAP with SSSD for sudo; NFS home directories with autofs for automount maps

Prerequisites and Lab Environment

The server should already expose POSIX entries under ou=people and ou=groups, ship the lab CA on the client, resolve ldap-server.example.com from /etc/hosts or DNS, and accept StartTLS on port 389. If DN, suffix, or schema terms are unclear, read LDAP and OpenLDAP basics first.

Setting Value
LDAP server hostname ldap-server.example.com (ldap-server)
LDAP server IP 192.168.56.108 (host-only adapter)
Client hostname ldap-client.example.com (ldap-client)
Client IP 192.168.56.109 (host-only adapter)
Base DN dc=example,dc=com
Test user DN uid=jdoe,ou=people,dc=example,dc=com
Test group DN cn=developers,ou=groups,dc=example,dc=com
CA file example-ldap-ca.crt

Set the client hostname with hostnamectl and map both lab hosts on the host-only adapter in /etc/hosts on the client—not on the NAT interface:

bash
sudo hostnamectl set-hostname ldap-client.example.com
text
192.168.56.108 ldap-server.example.com ldap-server
192.168.56.109 ldap-client.example.com ldap-client

Confirm the client FQDN before you install packages:

bash
hostname -f

Sample output:

output
ldap-client.example.com

Verify the client can resolve the LDAP server hostname:

bash
getent hosts ldap-server.example.com

Sample output:

output
192.168.56.108    ldap-server.example.com ldap-server

Check that port 389 is reachable. Install nmap-ncat when nc is not already available:

bash
command -v nc >/dev/null || sudo dnf install -y nmap-ncat
bash
nc -vz ldap-server.example.com 389

Sample output:

output
Ncat: Connected to 192.168.56.108:389.

LDAP password authentication is not Kerberos, so you do not need sub-second clock sync. Grossly wrong system time can still break TLS certificate validation—check with timedatectl:

bash
timedatectl

Sample output:

output
Local time: Tue 2026-07-14 06:58:44 IST
           Universal time: Tue 2026-07-14 01:28:44 UTC
                Time zone: Asia/Kolkata (IST, +0530)
System clock synchronized: no
              NTP service: active

Install SSSD and OpenLDAP Client Packages

Install the client stack with sudo and dnf. This guide uses SSSD and authselect—not legacy authconfig, nslcd, or pam_ldap.

bash
sudo dnf install -y \
  openldap-clients \
  openssl \
  sssd \
  sssd-ldap \
  sssd-tools \
  authselect \
  oddjob \
  oddjob-mkhomedir

Confirm the expected packages are present with rpm -q; the rpm command covers -qa and other RPM queries on this host:

bash
rpm -q \
  openldap-clients \
  openssl \
  sssd \
  sssd-ldap \
  sssd-tools \
  authselect \
  oddjob-mkhomedir

Sample output:

output
openldap-clients-2.6.10-1.el10.x86_64
openssl-3.5.5-4.el10_2.x86_64
sssd-2.12.0-3.el10_2.x86_64
sssd-ldap-2.12.0-3.el10_2.x86_64
sssd-tools-2.12.0-3.el10_2.x86_64
authselect-1.5.2-1.el10.x86_64
oddjob-mkhomedir-0.34.7-14.el10.x86_64

Do not install openldap-servers on the client—that package belongs on the directory server host.


Install the OpenLDAP CA Certificate

Copy only the public CA certificate from the LDAP server with scp over SSH; the ssh command covers secure copy and remote login options. Run this on the client:

bash
scp [email protected]:/etc/openldap/certs/example-ldap-ca.crt /tmp/

Place the CA in a stable path under /etc/openldap/certs/. Both ldap.conf and sssd.conf in this guide point at that file for StartTLS validation. Use install so ownership and permissions are set in one step—mode 0644 keeps the public certificate world-readable; only the CA certificate belongs here, not server or CA private keys.

bash
sudo install -o root -g root -m 0644 /tmp/example-ldap-ca.crt /etc/openldap/certs/example-ldap-ca.crt

The openldap-clients package normally creates /etc/openldap/certs/. Create it first with sudo install -d -m 0755 /etc/openldap/certs when the directory is missing.

Inspect the certificate dates and subject:

bash
openssl x509 -in /etc/openldap/certs/example-ldap-ca.crt -noout -subject -issuer -dates

Sample output:

output
subject=CN=Example Lab LDAP CA, O=Example Organization
issuer=CN=Example Lab LDAP CA, O=Example Organization
notBefore=Jul 13 16:57:49 2026 GMT
notAfter=Jul 10 16:57:49 2036 GMT

Test StartTLS and CA trust with OpenSSL before you configure SSSD. If this step fails, SSSD will not fix a broken CA path, SAN mismatch, or DNS problem:

bash
openssl s_client \
  -starttls ldap \
  -connect ldap-server.example.com:389 \
  -servername ldap-server.example.com \
  -CAfile /etc/openldap/certs/example-ldap-ca.crt \
  -verify_return_error

After confirming Verify return code: 0 (ok), press Ctrl+C to close openssl s_client.

Sample output:

output
Verify return code: 0 (ok)

Do not use TLS_REQCERT never in ldap.conf or ldap_tls_reqcert = never in SSSD. RHEL-family systems expect strict validation—hard and demand are equivalent strict modes.


Configure the LDAP Command-Line Client

Edit /etc/openldap/ldap.conf for command-line LDAP tools. This file affects ldapsearch, ldapwhoami, ldapadd, and ldapmodify; it does not replace /etc/sssd/sssd.conf.

text
URI ldap://ldap-server.example.com/
BASE dc=example,dc=com

TLS_CACERT /etc/openldap/certs/example-ldap-ca.crt
TLS_REQCERT demand

TLS_REQCERT demand matches the strict validation SSSD uses later with ldap_tls_reqcert = hard. Pass -ZZ on ldapsearch so the client negotiates StartTLS before LDAP traffic leaves the host—the same transport model as ldap_id_use_start_tls = true in sssd.conf.

Test that StartTLS works and read the server root DSE:

bash
ldapsearch -x -ZZ -H ldap://ldap-server.example.com -b "" -s base -LLL namingContexts supportedLDAPVersion

Sample output:

output
dn:
namingContexts: dc=example,dc=com
supportedLDAPVersion: 3

Search for the test user under the people OU:

bash
ldapsearch -x -ZZ \
  -H ldap://ldap-server.example.com \
  -b "ou=people,dc=example,dc=com" \
  -LLL "(uid=jdoe)" \
  dn uid uidNumber gidNumber homeDirectory loginShell

Sample output:

output
dn: uid=jdoe,ou=people,dc=example,dc=com
uid: jdoe
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/jdoe
loginShell: /bin/bash

If anonymous searches are blocked by server ACLs, repeat the search with a dedicated read-only service account that has search access through olcAccess. Do not use cn=admin,dc=example,dc=com as the permanent SSSD search identity. Create the account and matching rules in OpenLDAP ACL Configuration with Practical Examples.


Configure SSSD for OpenLDAP

SSSD reads /etc/sssd/sssd.conf separately from ldap.conf. The CA path appears in both files because command-line LDAP tools and SSSD do not share one configuration file.

Create /etc/sssd/sssd.conf for anonymous identity searches when server ACLs allow them:

text
[sssd]
services = nss, pam
domains = example.com

[domain/example.com]
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
access_provider = permit

ldap_uri = ldap://ldap-server.example.com
ldap_search_base = dc=example,dc=com
ldap_user_search_base = ou=people,dc=example,dc=com
ldap_group_search_base = ou=groups,dc=example,dc=com

ldap_schema = rfc2307

ldap_id_use_start_tls = true
ldap_tls_cacert = /etc/openldap/certs/example-ldap-ca.crt
ldap_tls_reqcert = hard

cache_credentials = true
enumerate = false

use_fully_qualified_names = false
fallback_homedir = /home/%u
default_shell = /bin/bash

[pam]
offline_credentials_expiration = 3
WARNING
access_provider = permit is suitable for this initial lab because it allows every LDAP user that can resolve and authenticate. For production clients, replace it with an explicit allow-list such as access_provider = simple and simple_allow_groups, or with an appropriate LDAP access policy.

Current SSSD releases on RHEL 10 reject config_file_version in the [sssd] section during sssctl config-check. Omit that legacy option.

The [pam] section sets how long cached authentication remains valid when LDAP is unavailable. offline_credentials_expiration = 3 permits cached authentication for three days after the user's last successful online login. The value is measured in days. SSSD stores a password hash for offline use, not the plaintext password. Choose a value that matches your availability and security requirements.

Setting Purpose
id_provider = ldap Reads user and group identity from LDAP
auth_provider = ldap Validates LDAP user passwords
chpass_provider = ldap Allows password-change requests through LDAP; not required merely to look up or authenticate a user
access_provider = permit Allows any successfully resolved LDAP user (lab only—see warning above)
ldap_id_use_start_tls = true Requires StartTLS for identity traffic on ldap://
ldap_tls_reqcert = hard Rejects invalid or untrusted server certificates
ldap_schema = rfc2307 Matches posixAccount, posixGroup, and memberUid from the install guide
cache_credentials = true Caches credentials after successful online login
enumerate = false Avoids downloading the entire directory
fallback_homedir Supplies a home path when LDAP omits homeDirectory

Password changes also require suitable server ACLs and password-policy configuration. Remove chpass_provider = ldap when this client should authenticate users but must not initiate LDAP password changes.

Short names such as jdoe are convenient in this single-domain lab because use_fully_qualified_names = false. Before using that setting in production, confirm that LDAP usernames and groups do not conflict with local accounts. Keep fully qualified names such as [email protected] when multiple identity domains may contain the same short name.

Alternative when anonymous searches are blocked

Add these lines inside [domain/example.com] when ACLs require a bind DN for reads:

text
ldap_default_bind_dn = uid=sssd-reader,ou=service-accounts,dc=example,dc=com
ldap_default_authtok_type = password
ldap_default_authtok = REPLACE_WITH_READER_PASSWORD

The bind account needs read-only access to identity attributes. It must not be an OpenLDAP administrator. Protect /etc/sssd/sssd.conf because the password is stored in plain text. User password authentication still occurs as each individual user.

Create the service account and matching olcAccess rules on the server in OpenLDAP ACL Configuration with Practical Examples—not on this client page.

LDAPS alternative

To use LDAPS instead of StartTLS, change the URI and disable StartTLS:

text
ldap_uri = ldaps://ldap-server.example.com
ldap_id_use_start_tls = false

Do not combine ldaps:// with ldap_id_use_start_tls = true.


Enable SSSD Authentication with authselect

SSSD refuses to use a world-readable configuration file. Set ownership with chown and permissions before validation and startup—use mode 600 even when no bind password is stored in the file.

bash
sudo chown root:root /etc/sssd/sssd.conf
bash
sudo chmod 600 /etc/sssd/sssd.conf
bash
sudo restorecon -v /etc/sssd/sssd.conf

restorecon applies the SELinux file context the sssd service expects on its configuration path.

Validate the configuration file before enabling services:

bash
sudo sssctl config-check

Sample output:

output
Issues identified by validators: 0

A non-zero issue count means SSSD may refuse to start or behave unpredictably—fix the reported options before continuing.

Inspect the current authentication profile:

bash
authselect current

Sample output on a fresh system:

output
Profile ID: local
Enabled features: None

Select the SSSD profile with automatic home-directory creation. with-mkhomedir wires PAM to oddjobd so the first successful login can create /home/username; SSSD alone does not create home directories. Save an authselect backup first:

bash
sudo authselect select sssd with-mkhomedir \
  --backup=before-openldap-client

If authselect reports unexpected manual changes and requests --force, inspect the existing PAM and NSS configuration before proceeding. Do not add --force blindly. authselect supports named backups and can restore them with authselect backup-restore; --force overwrites non-authselect configuration.

Sample output:

output
Profile "sssd" was selected.

Confirm the profile and generated files are consistent:

bash
authselect current

Sample output:

output
Profile ID: sssd
Enabled features:
- with-mkhomedir
bash
authselect check

Sample output:

output
Current configuration is valid.

authselect manages PAM and NSS snippets. Do not manually append sss entries to /etc/nsswitch.conf or edit generated system-auth files by hand on RHEL-family systems.

Enable and start SSSD and oddjobd with systemctl:

bash
sudo systemctl enable --now sssd oddjobd

Check that both units are active:

bash
sudo systemctl status sssd oddjobd --no-pager

The Active: active (running) lines for sssd.service and oddjobd.service confirm the identity stack is up.


Verify LDAP User Lookup and Login

Work through these checks in order. Each layer isolates a different failure mode.

Verify the SSSD domain

List configured SSSD domains:

bash
sudo sssctl domain-list

Sample output:

output
example.com

Check online status and discovered LDAP servers:

bash
sudo sssctl domain-status example.com

Sample output:

output
Online status: Online

Active servers:
LDAP: ldap-server.example.com

Discovered LDAP servers:
- ldap-server.example.com

Verify NSS identity lookup

A successful ldapsearch does not prove NSS is configured. getent and id exercise the SSSD path:

bash
getent passwd jdoe

Sample output:

output
jdoe:*:10001:10001:John Doe:/home/jdoe:/bin/bash
bash
id jdoe

Sample output:

output
uid=10001(jdoe) gid=10001(developers) groups=10001(developers)
bash
getent group developers

Sample output:

output
developers:*:10001:jdoe

Verify PAM authorization

Evaluate account checks for the default PAM stack:

bash
sudo sssctl user-checks jdoe

Sample output:

output
pam_acct_mgmt: Success

For SSH-specific account checks:

bash
sudo sssctl user-checks -a acct -s sshd jdoe

Sample output:

output
pam_acct_mgmt: Success

sssctl user-checks is useful when id works but interactive login fails.

Test the actual password

Do not use sudo su - jdoe as your primary password test. Root can switch users without validating the LDAP password.

This SSH test assumes sshd uses PAM and accepts at least one password-capable authentication method. A hardened key-only SSH configuration can reject the test even when SSSD and LDAP are working correctly:

bash
sudo sshd -T | grep -E \
  '^(usepam|passwordauthentication|kbdinteractiveauthentication)'

Sample output:

output
usepam yes
passwordauthentication yes
kbdinteractiveauthentication no

usepam must be enabled. At least one password-capable SSH authentication method must also be available for this password test. Do not enable password authentication globally without considering your security policy—the check above only clarifies the assumption behind the SSH login test.

From another terminal or a second lab host (for example the LDAP server), test SSH with the LDAP user's password:

bash

Keep your existing root session open until this succeeds.

Verify the home directory

After the first successful authenticated login, confirm the home path and directory exist:

bash
getent passwd jdoe
bash
ls -ld /home/jdoe

Sample output:

output
drwx------. 2 jdoe developers 4096 Jul 14 06:59 /home/jdoe

with-mkhomedir configures PAM to call oddjobd, which creates the home directory during the first authenticated login—not during getent or id.


Restrict Which LDAP Users Can Log In

The basic configuration uses access_provider = permit, which allows every LDAP user SSSD can resolve and authenticate.

To allow only members of one POSIX group, switch to the simple access provider:

text
access_provider = simple
simple_allow_groups = developers

Restart SSSD and clear cached entries so the new access rule is not masked by an older permit decision:

bash
sudo systemctl restart sssd
sudo sss_cache -E

Re-run the SSH account check:

bash
sudo sssctl user-checks -a acct -s sshd jdoe

This is client-side login authorization—not OpenLDAP olcAccess configuration. Complex LDAP filters, host-based rules, and sudo policies belong in separate lessons.


Troubleshoot OpenLDAP and SSSD Authentication

Symptom Likely layer What to check
ldapsearch -ZZ fails DNS, network, TLS, or CA trust getent hosts, nc, openssl s_client -starttls ldap
ldapsearch works but id jdoe fails SSSD identity configuration sssctl config-check, domain status, /var/log/sssd/
id jdoe works but password login fails PAM or LDAP authentication authselect current, sssctl user-checks, journalctl -u sshd, /var/log/secure
id jdoe and sssctl user-checks succeed but SSH never prompts for a password SSH authentication policy sshd -T, UsePAM, password/keyboard-interactive policy, journalctl -u sshd
su - jdoe works but SSH login fails Root bypassed password auth or SSH PAM failing Test SSH with the LDAP password; inspect SSH logs
Could not start TLS encryption StartTLS unsupported, wrong URI, or server TLS problem openssl s_client -starttls ldap
Certificate hostname mismatch Client URI absent from certificate SAN Connect using the SAN hostname or reissue the certificate
Works only with ldap_tls_reqcert = never Broken CA trust or certificate identity Fix CA and SAN; do not disable verification
SSSD refuses to start Syntax, ownership, or permissions sssctl config-check, chmod 600, journalctl -u sssd
User appears but groups are missing RFC2307 schema or membership mismatch ldap_schema, posixGroup, gidNumber, memberUid
Home directory missing with-mkhomedir or oddjobd inactive authselect current, systemctl status oddjobd
Stale LDAP values visible SSSD cache sss_cache -E and repeat the lookup
Offline login fails No cached credentials or expired cache Confirm cache_credentials = true, offline_credentials_expiration, and one successful online login first

Essential diagnostic commands—start with journalctl on the sssd, oddjobd, and sshd units, then read /var/log/secure:

bash
sudo journalctl -u sssd -n 100 --no-pager

Recent SSSD identity and authentication errors appear here when getent or login fails.

bash
sudo journalctl -u oddjobd -n 50 --no-pager

Check this when LDAP lookup works but the home directory is not created.

bash
sudo journalctl -u sshd -n 100 --no-pager

Use after id jdoe succeeds to see whether SSH rejected the password or PAM phase.

bash
sudo tail -n 100 /var/log/secure

PAM and session messages on RHEL-family systems when the journal alone is not enough.

bash
sudo sssctl config-check

Catches syntax, ownership, and permission problems that stop SSSD from starting.

bash
sudo sssctl domain-status example.com

Shows offline state and the last successful LDAP contact for the domain.

bash
sudo sssctl user-checks -a acct -s sshd jdoe

Separates identity lookup from account authorization for SSH.

bash
sudo grep -RiE 'error|failed|offline|tls|certificate' /var/log/sssd/

Quick scan for TLS, offline, and certificate errors in SSSD component logs.

bash
sudo sss_cache -E

Expire stale NSS entries after LDAP user or group changes.

On minimal systems the journal may be the primary log source; keep journalctl and /var/log/secure in the troubleshooting path.

Do not leave debug_level = 9 in production sssd.conf. Add it temporarily only while diagnosing a problem, then remove it—verbose SSSD logs grow quickly and may contain sensitive data.


References


Summary

On ldap-client.example.com, you installed SSSD and OpenLDAP client packages, copied the lab CA from ldap-server.example.com, verified StartTLS with OpenSSL and ldapsearch, configured /etc/openldap/ldap.conf and /etc/sssd/sssd.conf, enabled the SSSD authselect profile with with-mkhomedir, and validated identity lookup with getent, id, and sssctl before confirming SSH login and /home/jdoe creation for the LDAP user.


Frequently Asked Questions

1. Why does ldapsearch work but id username does not?

ldapsearch uses the OpenLDAP client library and settings such as /etc/openldap/ldap.conf, while id and getent use NSS. On this system, authselect routes NSS lookups through SSSD. Command-line parameters, environment variables, and user-specific LDAP configuration can override ldap.conf. If SSSD is misconfigured, stopped, or the domain name does not match, ldapsearch can succeed while NSS lookups fail.

2. Why does id username work but SSH login fails?

id exercises NSS identity lookup. SSH login also runs PAM authentication and account checks for the sshd service. A user can resolve in NSS while password authentication, access_provider rules, SSH authentication policy, or SSH-specific PAM checks still fail. Test with sssctl user-checks -a acct -s sshd, journalctl -u sshd, and /var/log/secure.

3. Should SSSD use StartTLS or LDAPS?

Use one encrypted transport method. For ldap:// on port 389, set ldap_id_use_start_tls = true. For ldaps:// on port 636, set ldap_id_use_start_tls = false. Do not combine ldaps:// with StartTLS enabled.

4. Does SSSD require an LDAP bind account?

Not always. When the server ACLs permit anonymous identity searches, SSSD can resolve users without a default bind DN. If anonymous searches are blocked, add ldap_default_bind_dn and ldap_default_authtok for a read-only service account and grant that identity search access through server olcAccess rules under cn=config.

5. Why is the LDAP user home directory not created?

Home directories are not created by SSSD alone. The authselect profile must include with-mkhomedir, oddjobd must be running, and the user must complete a successful authenticated login that triggers pam_oddjob_mkhomedir.

6. Can LDAP users log in when the LDAP server is offline?

Only after a successful online login with cache_credentials = true, and only within the configured offline_credentials_expiration period. SSSD stores a password hash for offline use, not the plaintext password. Offline login is not a substitute for LDAP availability or replication.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …