Integrating FreeBSD 15 with FreeIPA: Native Kerberos and LDAP Authentication



Logo

Most FreeIPA documentation assumes you’re running Linux and will use ipa-client-install to join hosts to the realm. FreeBSD doesn’t have this luxury. There’s no official IPA client, and the enrollment scripts expect systemd and other Linux-specific components. But that’s not necessarily a disadvantage.

FreeBSD’s native Kerberos implementation and the lightweight nslcd daemon provide everything needed to integrate with FreeIPA cleanly. The result is arguably more elegant than the Linux approach: pure GSSAPI authentication via SSH, LDAP-backed identity lookups, and zero local user management. No SSSD, no realm daemon, no complexity.

This guide details integrating a FreeBSD 15.0 host into a Red Hat Identity Management (IdM) or FreeIPA realm using only native FreeBSD components.

Design Philosophy

The approach here follows what I call “Clean and Sane Engineering”:

  • Authentication: Pure Kerberos via GSSAPI. Users authenticate with their Kerberos tickets - no passwords transmitted over the network
  • Identity: LDAP via nslcd for user and group lookups. The NSS layer queries FreeIPA’s LDAP directory transparently
  • Management: Stateless. No local users created manually. The host is a pure consumer of central identity services

This separation of concerns mirrors how enterprise authentication should work: the KDC handles cryptographic verification, the directory provides attributes, and the local system just needs to know where to ask.

Why Not SSSD?

The Linux world has largely converged on SSSD (System Security Services Daemon) for this kind of integration. It’s a powerful tool, but it’s also a monolith with a sprawling dependency tree, D-Bus requirements, and complexity that feels foreign on a FreeBSD system.

Following Unix philosophy and KISS principles, we actively avoid such heavyweight solutions. Each component in this setup does one thing well: nslcd handles LDAP lookups, the native krb5 library handles Kerberos, PAM modules handle session setup. These are small, focused tools that compose together.

Yes, the initial setup requires understanding how the pieces fit together. But the result is a solution that’s lighter, more transparent, and equally robust. When something breaks, you can debug each component independently. There’s no opaque daemon trying to be clever on your behalf. The configuration files are human-readable, the logs are straightforward, and the failure modes are predictable.

This trade-off, slightly more upfront complexity for long-term simplicity and maintainability, is at the heart of the FreeBSD philosophy. We’re not fighting the system. We’re working with its native primitives.

Prerequisites and Packages

The package requirements are minimal. Install the LDAP connector and the PAM module for automatic home directory creation:

pkg install nss-pam-ldapd pam_mkhomedir sudo

The nss-pam-ldapd package provides the nslcd daemon, which bridges FreeBSD’s NSS (Name Service Switch) to LDAP. Unlike heavier solutions like SSSD, it does one thing well: translate NSS queries into LDAP lookups.

The pam_mkhomedir module handles a common pain point: Creating home directories on first login. Without it, users would authenticate successfully but fail to get a shell because /home/username doesn’t exist.

Host Identity and Keytab Provisioning

Since there’s no ipa-client-install, we provision the host identity manually. This is actually straightforward: Create the host entry on the IPA server and export a keytab.

On the IPA Server

First, create the host entry. If DNS is integrated with IPA, the --ip-address flag will create the A record automatically:

ipa host-add bsdhost.example.com --ip-address=192.168.1.25

Then generate and export the keytab. The ipa-getkeytab command randomizes the host’s password (just like machine account passwords in Active Directory) and saves the cryptographic key material:

ipa-getkeytab -s idm01.example.com \
    -p host/bsdhost.example.com@EXAMPLE.COM \
    -k /tmp/bsdhost.keytab

On the FreeBSD Host

Transfer the keytab securely (via scp) to /etc/krb5.keytab. The permissions here matter:

chown root:nslcd /etc/krb5.keytab
chmod 640 /etc/krb5.keytab

The nslcd daemon needs read access to this keytab to authenticate its LDAP queries via GSSAPI. Without this, directory lookups will fail when the host’s cached credentials expire.

You also need to ensure, sshd can read the file (or SSH authentication will fail). That can be done either with ACLs or group membership for sshd in the nslcd group.

Kerberos Configuration

The Kerberos configuration is minimal. FreeBSD’s native krb5 implementation needs to know where the KDC is and which realm to use.

/etc/krb5.conf

[libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_kdc = false
    dns_lookup_realm = false

[realms]
    EXAMPLE.COM = {
        kdc = idm01.example.com
        admin_server = idm01.example.com
    }

[domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

I explicitly disable DNS lookups for the KDC. While FreeIPA publishes SRV records, hardcoding the KDC hostname makes the configuration deterministic and easier to debug. In environments with multiple KDCs, you can list them all in the kdc directive.

Verify the configuration works:

klist -k

This should display the host principal from the keytab:

Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   1 host/bsdhost.example.com@EXAMPLE.COM

LDAP Configuration with nslcd

The nslcd daemon handles all LDAP communication. It runs as an unprivileged user, connects to FreeIPA’s LDAP server, and responds to NSS queries over a Unix socket.

The key insight is using SASL/GSSAPI authentication - nslcd authenticates to LDAP using the host’s Kerberos keytab rather than a bind password. This eliminates stored credentials and leverages the existing trust relationship.

/usr/local/etc/nslcd.conf

# Run as unprivileged user
uid nslcd
gid nslcd

# Connection details
uri ldap://idm01.example.com
base dc=example,dc=com

# Authentication: Use the system keytab (Host Principal)
sasl_mech GSSAPI
sasl_realm EXAMPLE.COM

# Mapping: Force all IPA users to use /bin/sh
# IPA typically defaults to /bin/bash, which lives in /usr/local/bin on FreeBSD
map passwd loginShell "/bin/sh"

The loginShell mapping deserves explanation. FreeIPA stores /bin/bash as the default shell, but on FreeBSD, bash (if installed) lives at /usr/local/bin/bash. Rather than requiring every user to update their shell in IPA, we override it locally to /bin/sh, which is guaranteed to exist. Users who need bash can set it explicitly in their profile.

Enable and start the service:

sysrc nslcd_enable="YES"
service nslcd start

NSS Configuration

Tell FreeBSD’s name service switch to query LDAP after local files. The order matters - local accounts (root, system users) take precedence, with LDAP providing everything else.

/etc/nsswitch.conf

group: files ldap
passwd: files ldap
hosts: files dns
networks: files
shells: files
services: compat
protocols: files
rpc: files

We avoid the legacy compat mode for passwd and group - the files ldap ordering is cleaner and more predictable.

Test the integration immediately:

id someuser

This should return UID and GID information from FreeIPA:

uid=1234(someuser) gid=1234(someuser) groups=1234(someuser),5000(admins)

If this fails, check that nslcd is running and can read the keytab. The logs in /var/log/messages usually reveal the problem.

SSH Configuration

Configure SSH to accept Kerberos tickets via GSSAPI. This enables true single sign-on - users with valid Kerberos tickets can SSH without any password prompt.

/etc/ssh/sshd_config

# Disable password authentication entirely
PasswordAuthentication no
KbdInteractiveAuthentication no

# Optional: Disable pubkey if relying purely on Kerberos
# PubkeyAuthentication no

# Kerberos / GSSAPI authentication
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
GSSAPIStrictAcceptorCheck no

The GSSAPIStrictAcceptorCheck no setting relaxes hostname verification. This is sometimes necessary when the SSH server’s hostname doesn’t exactly match the principal in the keytab (e.g., connecting via IP or a CNAME).

Restart SSH:

service sshd restart

PAM Configuration for Home Directories

When a user logs in for the first time, their home directory won’t exist. The pam_mkhomedir module creates it automatically with appropriate permissions.

Edit the SSH PAM configuration to add the module:

/etc/pam.d/sshd

auth            required        pam_unix.so             no_warn try_first_pass

# account
account         required        pam_nologin.so
account         required        pam_login_access.so
account         required        pam_unix.so

# session
session         required        pam_mkhomedir.so        mode=0700
session         required        pam_permit.so

# password
password        required        pam_unix.so             no_warn try_first_pass

The mode=0700 ensures home directories are created with restrictive permissions.

Before this works, verify that /home exists as a symlink to /usr/home (the FreeBSD convention):

ls -la /home

If /home doesn’t exist or isn’t a symlink:

ln -s /usr/home /home

Sudo Configuration

Instead of managing local group membership, leverage FreeIPA’s groups directly. Members of the IPA admins group get sudo access without any local configuration per user.

/usr/local/etc/sudoers (or use visudo)

# Allow members of the LDAP 'admins' group full sudo access
%admins ALL=(ALL:ALL) ALL

The % prefix tells sudo to treat admins as a group name. Since nslcd handles group lookups, this transparently queries FreeIPA.

For more granular control, you can define multiple group-based rules:

%admins ALL=(ALL:ALL) ALL
%developers ALL=(ALL) /usr/local/bin/docker, /usr/local/bin/podman
%dba ALL=(postgres) ALL

Verification

With everything configured, verify each component:

1. Identity Lookups

id admin

Expected output shows UIDs and groups from IPA:

uid=1000(admin) gid=1000(admin) groups=1000(admin),5000(admins)

2. Keytab Status

klist -k

Should list the host principal.

3. SSH Login Test

From another machine with a valid Kerberos ticket:

kinit someuser@EXAMPLE.COM
ssh bsdhost.example.com

The login should succeed without a password prompt. After login:

pwd

Should show /home/someuser (created automatically by pam_mkhomedir).

4. Sudo Test

If the user is in the admins group:

sudo whoami

Should return root without asking for a password (assuming NOPASSWD is configured) or after entering the user’s Kerberos password.

Troubleshooting

nslcd fails to start or lookups fail

Check the keytab permissions:

ls -la /etc/krb5.keytab

The nslcd user (or group) must have read access. Also verify the keytab contains valid keys:

klist -k /etc/krb5.keytab

SSH rejects GSSAPI authentication

Ensure the hostname matches the keytab principal. Check /var/log/auth.log for details. Common issues:

  • Connecting via IP when the keytab has only the FQDN
  • Clock skew between the FreeBSD host and KDC (Kerberos is sensitive to time differences)

Users can authenticate but have no home directory

Verify pam_mkhomedir is in /etc/pam.d/sshd and that /home is a symlink to /usr/home.

Group membership not visible

This usually indicates nslcd isn’t querying group information correctly. Verify the base DN in nslcd.conf includes the container where groups are stored. For IPA, this is typically cn=groups,cn=accounts,dc=example,dc=com, but using just dc=example,dc=com as the base should work with subtree searches.

Conclusion

Integrating FreeBSD with FreeIPA doesn’t require complex third-party tools or Linux-specific software. The combination of native Kerberos, nslcd for LDAP, and standard PAM modules provides a clean, maintainable solution.

The key advantages of this approach:

  • No local user management - users exist only in IPA
  • True SSO - Kerberos tickets authenticate SSH sessions
  • Minimal attack surface - no SSSD, no realm daemon, no Python dependencies
  • Stateless configuration - rebuild the host without losing identity integration

This pattern scales well across a fleet of FreeBSD hosts. Once you’ve configured one system, the configuration files can be templated and deployed with Ansible or similar tools. The only per-host customization is the keytab, which IPA generates automatically.

For environments already invested in FreeIPA for Linux hosts, adding FreeBSD becomes trivial - just another host entry in the directory, with the same users, groups, and policies applying uniformly across the infrastructure.


References