Central Linux logins: LDAP or SSH CA
Centralize Linux logins so one change reaches every server. Compare a directory with SSSD, an SSH certificate authority, and Ansible-managed keys.
What you actually want when you centralize Linux logins
Most people who set out to centralize Linux logins want one thing: add a person once, remove them once, and have every server agree. A directory gives you that. On a fleet of six VPS instances it is also the most fragile way to get it, because an unreachable directory can refuse logins on every machine at the same moment.
Three approaches deliver "change it once, every host obeys". You can run a directory such as OpenLDAP or FreeIPA with SSSD (system security services daemon) on each host. You can issue short-lived SSH certificates from your own certificate authority (CA). You can write user accounts and authorized_keys files from configuration management. This post scores each one on revocation speed, behaviour during an outage, sudo policy, audit trail and setup cost, then recommends by fleet size instead of naming a single winner.
Interrogate the premise before you install OpenLDAP
LDAP (lightweight directory access protocol) centralizes identity: user names, numeric user IDs, group membership, and usually passwords. That is what it does. It does not distribute SSH public keys, it does not decide who may run sudo, and it does not record who logged in where. Each of those is a separate piece of configuration layered on top. Teams install OpenLDAP expecting a complete access control system and get a database with a schema, an access control syntax, and a replication topology to maintain.
So write down the real requirement before choosing. It is usually some mix of these: a leaver loses access the same day, a joiner gets access to the right subset of hosts rather than to all of them, and you can still answer "who logged into that box on Tuesday" three months later. Rank them. The ranking picks the tool.
One thing is out of scope here. Central management does not fix bad key practice, and one leaked private key defeats all three options below. Solid SSH key management covers passphrases, key types and rotation, and that groundwork should be in place before you build anything central on top of it.
Option one: a directory with SSSD on every host
The shape is simple. One LDAP server, or two if you want logins to survive a reboot, holds the users. Every host runs SSSD, which plugs into NSS (name service switch) so id alice resolves, and into PAM (pluggable authentication modules) so authentication works. When getent passwd alice returns a user who has no line in /etc/passwd, the pieces are connected.
Your realistic choices, as of August 2026:
- OpenLDAP: the bare directory. You design the tree, load schemas, configure TLS (transport layer security), write access control lists and set up replication yourself. The OpenLDAP 2.6 Administrator's Guide is the reference, and it is long for a reason.
- FreeIPA: 389 Directory Server, MIT Kerberos, a certificate authority, DNS and host-based access control in one install. It answers much more of the problem out of the box. It also wants its own DNS records and a stable fully qualified hostname, and its natural home is the RHEL family. See freeipa.org.
- An SSO (single sign-on) product with an LDAP interface. Authentik's LDAP provider serves its user database over LDAP and documents SSSD as a client, so web applications and shell logins can share one user list. Keycloak federates from an existing LDAP directory rather than serving one, which is the detail that surprises people. The comparison of self-hosted SSO servers covers that split, and running Authentik on your own server covers the deployment.
Two pieces are easy to miss. First, SSH public keys can live in the directory: set ldap_user_ssh_public_key and point sshd's AuthorizedKeysCommand at sss_ssh_authorizedkeys. Skip that and you have centralized passwords while keys stay scattered across home directories. Second, access_provider defaults to permit, which means every user in the directory may log into every host you join to it. Joining a new server therefore grants shell access to everyone, silently, until you set a real access provider.
[domain/example.com]
cache_credentials = true
access_provider = simple
simple_allow_groups = linux-admins
[pam]
offline_credentials_expiration = 7Option two: an SSH certificate authority
One key pair signs certificates. Each server trusts the CA public key through two lines in sshd_config. There is no package to install, no daemon to run, and no per-user file to push. OpenSSH has supported certificates since version 5.4, so every current distribution already has this.
TrustedUserCAKeys /etc/ssh/user_ca.pub
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%uA certificate is a signed statement about a public key. It carries a key ID that names the human, a list of principals (the account names that key may log in as), a validity window, and options such as force-command or source-address. The per host AuthorizedPrincipalsFile decides which principals may become which local user, so the same certificate can be an admin on one box and nothing on another. The CERTIFICATES section of the ssh-keygen manual is worth reading in full before you build tooling around it.
ssh-keygen -s /etc/ssh/user_ca -I alice@example.com -n deploy -V +8h -z 1042 id_ed25519.pubThe single most important flag there is -V. The manual is blunt about the default: certificates are valid from the Unix epoch to the distant future. Forget -V and you have not issued a login, you have issued a permanent credential that no server will ever stop trusting. Inspect what your signing script actually produced with ssh-keygen -L -f id_ed25519-cert.pub and read the validity line before you trust the script.
Sign the host keys too. HostCertificate on each server, plus one @cert-authority line in your local known_hosts, removes the "authenticity of host can't be established" prompt for every server you will ever build, and with it the habit of typing yes without looking. That habit is the real risk once you manage more Linux servers than you can name.
The catch is important: a certificate authorizes a login, it does not create a Unix account. The local account must already exist, created by configuration management, by a directory, or as a shared role account such as deploy that several people may become. For tooling beyond a signing script, HashiCorp Vault's signed SSH certificates engine and step-ca both issue short-lived certificates after an SSO login.
Option three: accounts and keys from configuration management
Ansible, Salt or Puppet creates the account, renders authorized_keys, and drops a file in /etc/sudoers.d. The source of truth is a git repository. Removing a person is a commit and a run.
Do not treat this as the beginner option. Git history is a reviewable record of who granted what, when, and who approved it, which neither other option gives you for free. Nothing runs at login time, so authentication never depends on a network service being up. Small teams often reach past this and regret it.
Its weakness is exact, and worth stating plainly: correctness depends on the last run reaching the host. A server that was powered off, or behind a broken network path, keeps the key you just deleted, and the run reports it as unreachable rather than failed. That is why the way Ansible handles unreachable hosts matters more than it first sounds. During an offboarding run, an unreachable host is an open task, not a warning to scroll past.
How fast can you really remove a person?
None of the three ends a session that is already open. All of them stop the next login. To end current access you kill the sessions with pkill -u alice or reboot the box. Everything below assumes that.
A directory is fast in theory and slower in practice, because SSSD caches. entry_cache_timeout defaults to 5400 seconds, so a group membership change can take ninety minutes to be visible on a host unless you run sss_cache -E. Worse, cache_credentials stores the user's password hash on every host where they have logged in, and offline_credentials_expiration defaults to 0, which means no limit. Those two defaults together let a disabled user keep logging in offline on any host that has cached them, with no end date. Set the expiration to a number of days, as in the configuration above.
An SSH CA is slower in theory and faster in practice. You do not revoke, you let the certificate expire. An eight hour certificate is gone within eight hours with no host contacted and no host missed. When you need access gone now, generate a key revocation list (KRL) with ssh-keygen -k, distribute it to every host, and name it in RevokedKeys. That is a push to every host again, which is the problem you were avoiding, so treat the KRL as the emergency path rather than the routine one.
Configuration management is as fast as one run across the hosts that answer. Minutes, on a small fleet. The number that decides whether the removal worked is not the run time. It is how many hosts were unreachable.
What breaks when the central service is unreachable?
This question decides the choice for small fleets, so answer it first.
A directory outage is the dangerous one. Hosts that depend on it for user lookups can refuse or stall logins, and because every host points at the same server, they fail together. One broken virtual machine can block logins everywhere at once. Three things are therefore not optional. Set cache_credentials = true so people who have logged into a host before can log in again during the outage. Run a second directory server and list both in ldap_uri. Keep a local break-glass account on every host with its own key, and know how to reach your provider's console as the last resort.
Understand the limit of that cache before you rely on it. It is per host and per user. Somebody who has never logged into that particular box has nothing cached there, and a freshly built host has an empty cache, so during a directory outage the newest server is the one nobody can enter. On the host, sssctl domain-status reports whether SSSD currently considers the domain online.
Then test it deliberately. Block the directory port with a firewall rule on one host, keep a second terminal open, and try to log in. If you have not tested the cache and the break-glass account, you do not know that they work. This is the same discipline as the rest of a routine Linux server maintenance checklist: the recovery path you never exercise is the one that fails.
An SSH CA fails softly. If the signing service is down, nobody can get a new certificate, but every certificate already issued keeps working until it expires. People notice at the start of the next working day rather than in the middle of an incident. The severe CA failure is a different one: the CA private key is the whole fleet, so it belongs offline, on a hardware token, or inside a service that logs every signature it makes.
Configuration management has nothing to be down. After the run, each host authenticates entirely on its own.
Where does sudo policy live?
A directory can carry sudo rules. Sudoers entries can be stored in LDAP and read through SSSD's sudo responder, with sudoers: files sss in /etc/nsswitch.conf. FreeIPA treats sudo rules as first class objects. With plain OpenLDAP you load the sudo schema and hand-write sudoRole entries, and many teams that get this far still keep /etc/sudoers.d on the host, because it is easier to read and it keeps working during an outage.
An SSH certificate says nothing about privilege. It grants a login as a principal, and everything after that is ordinary local sudo policy. If you want the certificate itself to constrain behaviour, force-command and source-address are the available tools, and they are blunt instruments.
Configuration management templates files into /etc/sudoers.d/ and validates them with visudo -cf before installing them. That stays true whichever option you pick for identity, because sudo policy is per host by nature. Decide who gets what before you centralize anything: designing least privilege user accounts on a VPS is work none of these three tools will do for you.
What can you prove afterwards?
The audit question is where the SSH CA wins outright. When sshd accepts a certificate, it logs the certificate's key ID and serial number next to the accepted login. A login to a shared deploy account therefore still names the individual who signed in, in the host's own authentication log. Shared accounts stop being anonymous. Issue serials with -z and every certificate is individually identifiable later, in a revocation list or in a log search.
A directory gives you a central record of authentication attempts in the directory's own log, plus the per host journal. What it does not give you is any link between a shared account and a person.
Configuration management gives you the best record of authorization and the weakest record of authentication. Git says exactly who granted access and when. The login itself is just an account name in journalctl -u ssh.
All three depend on shipping logs off the box, because root on a host can edit that host's logs. An audit trail that lives only on the machine being audited is not evidence.
What each option costs to stand up
OpenLDAP from scratch is measured in days, then in ongoing maintenance: schema, TLS certificates, access control lists, replication, directory backups, SSSD configuration on every host, and a plan for SSH keys. FreeIPA is measured in hours if you are already on the RHEL family with DNS under control, and it is heavy for a handful of small VPS instances. Authentik with the LDAP provider is cheap if you already run Authentik for web applications, and it still leaves SSSD, the outage question and the sudo question on your desk.
An SSH CA is an afternoon for a working version: generate the CA key, add two lines to sshd_config, write one principals file per host, and write the signing script. The remaining work is protecting the CA key and automating issuance so that nobody is signing certificates by hand every morning. That is the part Vault and step-ca exist to solve.
Configuration management costs about an hour if you already run it. If you do not, you will want it anyway, for hardening SSH on every VPS and for everything else that has to be identical across hosts.
Which one for your fleet size
Under about ten servers, with one or two admins: configuration management. Nothing central can fail, git is the record, and the revocation gap stays small because you can see all of your hosts. A directory at this size creates a single point of failure that is far more likely to lock you out than an attacker is to break in. Put the first ten minutes of a new VPS into the same playbook and every host starts consistent.
Ten to about fifty servers, several people, real staff churn: an SSH certificate authority. Revocation becomes automatic instead of a chore, host certificates end the fingerprint prompt, per person audit survives shared accounts, and anyone already holding a certificate is unaffected by an outage of your signing service. Keep creating the local accounts from configuration management. The two fit together well.
Above that, or when the same people need one identity for web applications and for shells, or when somebody else owns the joiner and leaver process: a directory. At that size the operational cost is justified, and the failure mode is manageable because you will run replicas and you will have tested them. FreeIPA if you are on the RHEL family, an SSO product with an LDAP provider if your web stack already lives there.
One pairing deserves its own line, because it is what large environments actually run. The directory owns accounts, groups and sudo rules. The SSH CA owns the login path and the audit trail. Neither replaces the other. And whichever you choose, the local break-glass account and the tested outage path stay.
FAQ
Do I need OpenLDAP to centralize Linux logins?
No. OpenLDAP centralizes identity, and identity is only part of what you want. If the goal is "remove a person once and have every server agree", then configuration management writing authorized_keys and /etc/sudoers.d achieves that on a small fleet with no runtime dependency, and an SSH certificate authority achieves it through automatic expiry. A directory earns its cost when you have dozens of hosts, regular staff turnover, or a requirement that shell logins and web applications share one user list.
What happens to Linux logins when the LDAP server goes down?
Hosts that use it for user lookups can refuse or stall logins, and because they all point at the same server, they fail at the same time. Setting cache_credentials = true lets people who have logged into that host before authenticate from the local cache, but a user who has never logged into that box, or a host built after the outage began, has nothing cached. Run a second directory server, set cache_credentials with a sane offline_credentials_expiration, keep a local break-glass account with its own key on every host, and test all of it by blocking the directory port on one machine.
How do I revoke SSH access immediately with a certificate authority?
Normal revocation is expiry: sign with a short window such as -V +8h and access ends by itself. For immediate revocation, build a key revocation list with ssh-keygen -k, distribute it to every host, and point RevokedKeys in sshd_config at it. That is a push to every host, so keep it as the emergency path. Neither method ends sessions that are already open, so end those with pkill -u alice when it matters.
Can I use Keycloak or Authentik for Linux SSH logins?
Authentik yes, Keycloak not directly. Linux authentication runs through NSS and PAM, which speak LDAP rather than OIDC (OpenID Connect). Authentik ships an LDAP provider that serves its user database over LDAP and documents SSSD as a client, so a Linux host can bind to it like any other directory. Keycloak federates from an existing LDAP directory instead of serving one, so it does not remove the need for a directory. The other route is an SSH certificate authority that signs a short-lived certificate after an SSO login, which is what step-ca and similar products do.