Skip to main content
Overview

SMB Authentication with AD on Linux

Merox
Merox HPC Sysadmin
7 min read
Security Advanced

After days of configuration and research, I couldn’t find a single source that covered everything needed for this setup end to end. My job requires centralized SSSD across all Linux servers, so here’s what I got working on both RHEL 8 and OpenSUSE 15.6.

The stack: Samba for SMB/CIFS, SSSD for AD integration, Kerberos for authentication, and realmd for domain join.

What you need before starting: DNS resolving your domain controllers, NTP/Chrony running and synced, a domain admin account with join privileges, and the following info on hand — domain name (company.com), DC hostname (dc1.company.com).

Step 1: Package Installation

RHEL/CentOS/Rocky Linux

Terminal window
sudo dnf install -y realmd sssd oddjob oddjob-mkhomedir adcli \
samba-common-tools krb5-workstation chrony samba samba-client \
cifs-utils policycoreutils-python-utils
sudo systemctl enable --now chronyd
sudo systemctl enable sssd

Ubuntu/Debian

Terminal window
sudo apt update
sudo apt install -y realmd sssd sssd-tools libnss-sss libpam-sss \
adcli samba-common-bin krb5-user chrony samba smbclient \
cifs-utils
sudo systemctl enable --now chrony
sudo systemctl enable sssd

OpenSUSE Leap / Tumbleweed

Terminal window
sudo zypper install -y realmd sssd sssd-ad adcli \
samba krb5-client chrony samba-client cifs-utils
sudo systemctl enable --now chronyd
sudo systemctl enable sssd
Note

SSSD is only enabled here, not started — it has no configuration yet. realm join (Step 4) will create the initial sssd.conf and start the service automatically.

Note

Ubuntu and OpenSUSE use AppArmor, not SELinux. The policycoreutils-python-utils package and semanage/restorecon commands throughout this guide are RHEL/CentOS-specific. Skip them on Debian-based and OpenSUSE systems.

Step 2: DNS and Time

/etc/resolv.conf

nameserver 192.168.1.10
nameserver 192.168.1.11
search company.com
domain company.com

Verify:

Terminal window
dig company.com
dig _ldap._tcp.company.com SRV

/etc/chrony.conf

server dc1.company.com iburst prefer
server dc2.company.com iburst
Terminal window
# RHEL/CentOS/OpenSUSE
sudo systemctl restart chronyd
# Ubuntu/Debian
sudo systemctl restart chrony
chronyc sources -v
timedatectl status
Note

Kerberos requires time to be within 5 minutes of the domain controllers. If clock skew exceeds this, authentication will fail with KRB5KRB_AP_ERR_SKEW.

Step 3: Kerberos Configuration

/etc/krb5.conf

[libdefaults]
default_realm = COMPANY.COM
dns_lookup_kdc = true
dns_lookup_realm = false
rdns = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
udp_preference_limit = 0
[realms]
COMPANY.COM = {
kdc = dc1.company.com
admin_server = dc1.company.com
default_domain = company.com
}
[domain_realm]
.company.com = COMPANY.COM
company.com = COMPANY.COM
[logging]
default = SYSLOG:NOTICE:DAEMON

Test it:

Terminal window
kinit administrator@COMPANY.COM
klist
kdestroy

Step 4: Domain Join

Terminal window
sudo realm discover company.com
sudo realm join company.com -U administrator \
--client-software=sssd \
--membership-software=samba
sudo realm list
net ads testjoin
Note

realm join --membership-software=samba calls net ads join internally — no need to run it again. It auto-configures /etc/sssd/sssd.conf, /etc/krb5.conf, and /etc/krb5.keytab. The custom sssd.conf in Step 6 intentionally replaces what realm join generated with a production-ready configuration.

Step 5: PAM Configuration

RHEL/CentOS/Rocky Linux

Terminal window
sudo authselect select sssd with-mkhomedir --force
sudo systemctl enable --now oddjobd

OpenSUSE

Terminal window
sudo pam-config --add --sss
sudo pam-config --add --mkhomedir

Ubuntu/Debian

pam-auth-update handles this automatically when libpam-sss is installed. No manual steps needed.

Step 6: SSSD Configuration

/etc/sssd/sssd.conf

[sssd]
enable_files_domain = true
domains = company.com
config_file_version = 2
services = nss, pam
[domain/local]
id_provider = files
[domain/company.com]
ad_domain = company.com
krb5_realm = COMPANY.COM
realmd_tags = manages-system joined-with-samba
cache_credentials = True
id_provider = ad
ad_update_samba_machine_account_password = True
full_name_format = %3$s\%1$s
use_fully_qualified_names = False
fallback_homedir = /home/%u
default_shell = /bin/bash
# Requires POSIX attributes (uidNumber, gidNumber) set in AD
ldap_id_mapping = False
krb5_store_password_if_offline = True
access_provider = simple
simple_allow_groups = linuxadmins@company.com, itstaff@company.com
simple_allow_users = testuser@company.com
enumerate = False
Terminal window
sudo chmod 600 /etc/sssd/sssd.conf
sudo systemctl restart sssd
sudo systemctl enable sssd
Note

ldap_id_mapping = False requires that all AD users and groups have POSIX attributes (uidNumber, gidNumber) configured in Active Directory. If they don’t, user lookups will fail silently. Set to True to let SSSD generate consistent IDs algorithmically instead.

Step 7: NSS Configuration

/etc/nsswitch.conf

passwd: files sss
group: files sss
shadow: files sss
netgroup: sss files
Note

Do not add winbind to passwd or group here. In this setup, SSSD handles all NSS resolution. Winbind runs only as an internal Samba component for ID mapping via the sss backend. Mixing sss and winbind in nsswitch causes duplicate lookups and inconsistent results.

Step 8: Samba Configuration

/etc/samba/smb.conf

[global]
realm = COMPANY.COM
workgroup = COMPANY
security = ads
kerberos method = secrets and keytab
dedicated keytab file = /etc/krb5.keytab
log file = /var/log/samba/log.%m
log level = 2
vfs objects = acl_xattr
map acl inherit = yes
store dos attributes = yes
template homedir = /home/%U
template shell = /bin/bash
idmap config * : backend = tdb
idmap config * : range = 10000-199999
idmap config COMPANY : range = 200000-2147483647
idmap config COMPANY : backend = sss
client signing = mandatory
server signing = mandatory
socket options = TCP_NODELAY IPTOS_LOWDELAY
[shared]
path = /srv/shared
read only = no
browsable = yes
valid users = @linuxadmins, @itstaff
force group = linuxadmins
create mask = 0664
directory mask = 0775
[data]
path = /srv/data
read only = no
browsable = yes
valid users = @dataaccess
force group = dataaccess
create mask = 0660
directory mask = 0770
[homes]
comment = Home Directories
valid users = %S
browsable = no
read only = no
create mask = 0700
directory mask = 0700
Note

idmap config COMPANY : backend = sss tells Samba’s winbind to delegate ID mapping to SSSD for the COMPANY domain. The default tdb backend handles the * (fallback) range. The sss backend is read-only, so a writable fallback is required.

Note

Group names in valid users must match how SSSD exposes them. With use_fully_qualified_names = False, groups resolve as linuxadmins — not linuxadmins@company.com. Using the FQDN form here will silently block all access.

Validate the configuration before starting services:

Terminal window
sudo testparm -s

Create Share Directories

Terminal window
sudo mkdir -p /srv/shared /srv/data
sudo chgrp linuxadmins /srv/shared
sudo chmod 775 /srv/shared
sudo chgrp dataaccess /srv/data
sudo chmod 770 /srv/data
# SELinux (RHEL/CentOS only)
sudo setsebool -P samba_export_all_ro=1 samba_export_all_rw=1
sudo setsebool -P use_samba_home_dirs=on
sudo setsebool -P samba_enable_home_dirs=on
sudo semanage fcontext -a -t samba_share_t "/srv/shared(/.*)?"
sudo semanage fcontext -a -t samba_share_t "/srv/data(/.*)?"
sudo restorecon -R /srv/shared /srv/data

Step 9: Start Services and Test

RHEL/CentOS/Rocky Linux / OpenSUSE

Terminal window
sudo systemctl enable --now smb winbind
sudo systemctl status smb winbind

Ubuntu/Debian

Terminal window
sudo systemctl enable --now smbd winbind
sudo systemctl status smbd winbind

Verify user and group resolution

Terminal window
getent passwd testuser@company.com
id testuser@company.com
getent group linuxadmins@company.com

Test share access

Terminal window
# List shares
smbclient -L localhost -U testuser@company.com
# Test share access
smbclient //localhost/shared -U testuser@company.com

From a Windows client: \\linux-server\shared

Step 10: Firewall

RHEL/CentOS/Rocky Linux / OpenSUSE

Terminal window
# The samba service already includes ports 137/udp, 138/udp, 139/tcp, 445/tcp
sudo firewall-cmd --permanent --add-service=samba
sudo firewall-cmd --reload

Ubuntu/Debian

Terminal window
sudo ufw allow samba
sudo ufw status

Step 11: Troubleshooting

Cache

Terminal window
sudo sss_cache -E
sudo systemctl restart sssd
sudo net cache flush
# If TDB corruption suspected
sudo systemctl stop smb winbind # or smbd on Ubuntu
sudo rm -f /var/lib/samba/*.tdb
sudo systemctl start winbind smb # or smbd on Ubuntu

Logs

Terminal window
sudo tail -f /var/log/sssd/sssd_company.com.log
sudo tail -f /var/log/samba/log.smbd

For deeper SSSD debugging, add debug_level = 9 in the [domain/company.com] section and restart sssd.

AD Connectivity and Auth

Terminal window
sudo net ads info
sudo net ads user info testuser
sudo net ads group info "linuxadmins"
klist -k /etc/krb5.keytab
# Winbind checks
sudo wbinfo -t # verify trust secret
sudo wbinfo -n "COMPANY\testuser" # resolve a specific user (safe)
# Avoid wbinfo -u / wbinfo -g in large AD environments — enumerates all
# domain users/groups and can cause significant load on domain controllers
# Active connections
sudo smbstatus

Common Errors

NT_STATUS_ACCESS_DENIED:

Terminal window
id username@company.com
sudo testparm -s
ls -Z /srv/shared # SELinux context (RHEL only)

Users not resolving:

Terminal window
sudo sss_cache -E
sudo systemctl restart sssd winbind
getent passwd username@company.com

Authentication failures:

Terminal window
klist
kinit username@COMPANY.COM
chronyc sources -v
net ads testjoin

Maintenance Script

Terminal window
sudo nano /usr/local/bin/samba-maintenance.sh
#!/bin/bash
# SSSD manages machine account password rotation automatically via
# ad_update_samba_machine_account_password = True — do not run
# net ads changetrustpw here as it conflicts with SSSD's management.
sss_cache -E
tdbbackup /var/lib/samba/*.tdb 2>/dev/null || true
net ads testjoin
echo "Maintenance completed: $(date)"
Terminal window
sudo chmod +x /usr/local/bin/samba-maintenance.sh
# Weekly cron
echo "0 2 * * 0 /usr/local/bin/samba-maintenance.sh >> /var/log/samba-maintenance.log 2>&1" | sudo crontab -

Share this post

Related Posts

SSH Hardening - Securing Your Linux Servers

Practical SSH hardening for production Linux servers — key-based auth, sshd_config, 2FA, host-based auth, fail2ban, and log monitoring.

9 min read 6 parts

The Axios Supply Chain Attack

A compromised maintainer account pushed two poisoned axios versions that drop a cross-platform RAT. Here's what happened and how I verified this project isn't affected.

5 min read

Tailscale site-to-site pfSense - Linux

How to set up a Tailscale site-to-site L3 connection between a pfSense homelab subnet and a Linux cloud VM subnet.

3 min read
Loading comments...