Shared Home Directory and Centralized Identity¶
"Everyone's $HOME lives on the NAS, and ssh alice@anynode Just Works" — the classic multi-node Linux pattern. It's actually two problems solved together:
- Storage: a shared filesystem exports
/home; all compute nodes mount it. - Identity: a directory service distributes users, groups, UIDs, and credentials so every node sees the same
alicewith the same UID 10042.
Miss either and you get file-permission chaos or duplicate useradd across 50 nodes.
Reference architecture¶
flowchart LR
user["User"] -->|ssh alice@node42| sshd["sshd (PAM)"]
sshd -->|nsswitch lookup| sssd["SSSD on node42"]
sshd -->|auth| sssd
sssd -->|"LDAP (TLS)"| ipa["FreeIPA / 389ds"]
sssd -->|Kerberos| ipa
sshd -->|pam_mkhomedir / autofs| mount["/home/alice"]
mount -.->|"NFSv4 / BeeGFS / CephFS"| nas["NAS server"]
ipa -.->|"Kerberos ticket (sec=krb5p)"| nas
Flow:
aliceSSHes tonode42.- PAM on
node42asks SSSD to authenticate her. - SSSD talks LDAP (for directory lookup) and Kerberos (for password/ticket) to the FreeIPA server.
- PAM's
pam_mkhomedirensures her home directory exists;autofsor a static mount attaches it from the NAS. - If NFSv4 is running with
sec=krb5p, the mount uses her Kerberos ticket to prove identity to the NAS.
Components¶
Identity / directory service¶
| Option | License | What you get | Best for |
|---|---|---|---|
| FreeIPA | GPLv3 | 389ds LDAP + MIT Kerberos + DNS + Dogtag PKI + web UI + CLI (ipa) + replication |
Turnkey Linux fleet identity |
| 389 Directory Server | GPLv3 | LDAPv3 server (standalone) | You want only LDAP, handle Kerberos separately |
| OpenLDAP | OpenLDAP License | LDAPv3 (slapd) + tooling |
Classic, manual, Unix-y |
| Samba AD DC | GPLv3 | Windows-compatible Active Directory | Mixed Windows + Linux + Mac |
| Microsoft Active Directory | Commercial | The enterprise Windows standard | You have Windows infrastructure |
| Keycloak | Apache 2.0 | OIDC / SAML IdP | Modern web apps; not POSIX user identity |
| Authentik | MIT | OIDC / SAML IdP | Lighter alternative to Keycloak |
| JumpCloud / Okta / Entra ID | SaaS | Cloud directory; LDAP/RADIUS gateways | Cloud-first orgs |
For the "Linux cluster with shared /home" use case, FreeIPA is the pragmatic default. It bundles all the moving parts, has a usable web UI, handles replication, and integrates cleanly with SSSD.
Client-side resolver¶
SSSD (System Security Services Daemon) sits on every compute node:
- Talks LDAP + Kerberos to the directory.
- Caches lookups (works offline after first auth).
- Plugs into
nsswitch.conf(forgetent passwd alice) and PAM (for login / sudo). - Handles
sudorules via LDAP schema if you store them centrally.
On macOS there's a corresponding opendirectoryd binding via dsconfigldap or MDM profile, but the UX is rougher than Linux. Mac users on a shared-home Linux cluster typically keep their local macOS account and only bind to the cluster when SSHing in.
Shared /home storage¶
See shared-storage.md for the full comparison. For shared home specifically:
- NFSv4 — simplest; pair with
autofsfor on-demand per-user mount. Usesec=krb5pfor security on untrusted networks. - BeeGFS — strong if you're also running an HPC workload against the same storage.
- CephFS — if you already run Ceph for K8s/object.
- Single ZFS server + NFS — fine for 5-50 users; ZFS snapshots give you Dropbox-style "previous versions."
Home mount mechanism¶
Two idioms:
- Static mount —
/etc/fstabmounts/homeat boot. Simple; uses RAM while empty; all users' homes visible. - autofs on-demand — each
/home/<user>mounts when first accessed, unmounts after timeout. Standard in multi-node clusters; reduces unnecessary NFS traffic.
See shared-storage.md#client-mount-recipes for autofs config.
pam_mkhomedir (on the PAM stack) creates the home directory on first login if it doesn't exist. Typically used on compute nodes where homes are provisioned lazily.
UID/GID conventions¶
Consistency of UID across all nodes is non-negotiable when /home is shared. File permissions are stored as UID numbers on disk; if alice is 10042 on node A and 10043 on node B, her files look like they belong to bob from node B.
Conventions that scale:
| Range | Use |
|---|---|
| 0-999 | System accounts (root, daemons) — distro-managed |
| 1000-9999 | Local users (the one-off adduser on a single box) |
| 10000-99999 | Directory users (FreeIPA / LDAP) — give these their own reserved range |
| 100000+ | Subordinate UIDs (for user namespaces, rootless containers, per /etc/subuid) |
FreeIPA by default assigns UIDs in a random range (e.g. 1234xxxxxx) to avoid collision with local users. Override via ipa-server-install --idstart=10000 --idmax=99999 if you want the clean 10000+ convention.
Never recycle UIDs across directories (e.g. old AD + new FreeIPA). Keep a single source of truth.
Kubernetes pods that write to shared home¶
If a pod's /home/alice is an NFS/CephFS mount and the pod needs to write to it as alice, the pod's container user must match UID 10042:
spec:
securityContext:
runAsUser: 10042
runAsGroup: 10042
fsGroup: 10042
containers:
- name: notebook
image: jupyter/base-notebook
volumeMounts:
- name: home
mountPath: /home/alice
volumes:
- name: home
nfs:
server: nas.example.com
path: /home/alice
Kubeflow and JupyterHub spawners handle this through KubeSpawner profiles that inject the right UID per user. Look up the UID from the directory at spawn time rather than hard-coding.
Realistic stack recipes¶
Small Linux team (5-20 users)¶
- 1 NAS server: Ubuntu + ZFS +
nfs-kernel-serverexports/export/home - 1 IPA server: Rocky Linux or Ubuntu +
ipa-server-install(FreeIPA master) - Each workstation:
ipa-client-install(registers the machine, configures SSSD + Kerberos + NFSv4 + PAM in one shot) autofsmounts/home/<user>on demand
Cost: two always-on VMs + the NAS box. Time: a weekend.
HPC / ML lab (50-500 users, GPU cluster)¶
- Head node + 1-2 IPA replicas (redundancy)
- BeeGFS or Lustre storage cluster for
/scratch - NFS or BeeGFS for
/home - SLURM controller + accounting DB (see compute-scheduling.md)
- Open OnDemand for web portal
- All compute nodes enroll via
ipa-client-install;pam_mkhomedirfor lazy home creation
K8s-native (cloud-native product team)¶
- Identity: OIDC (Keycloak / Dex / Okta) — users don't need POSIX UIDs in the cluster itself
- Compute: Kubernetes + Kueue/Volcano for batch
- Storage: Rook-Ceph with CephFS for RWX volumes
- "Home" is per-user PVCs or notebook images; not a shared filesystem in the classic Linux sense
- Only JupyterHub / Kubeflow spawners need POSIX UID mapping, and they typically inject via ConfigMap
In this setup you don't really run FreeIPA — the K8s RBAC + OIDC stack replaces it.
Operations checklist¶
A shared-home cluster working correctly means:
- [ ]
getent passwd alicereturns identical output on every node - [ ]
id alicereturns identical UID/GID on every node - [ ]
ssh alice@anynodeworks with either password or key - [ ]
ls -la /home/aliceshowsalice alice(not a UID number) after login - [ ] Files created on node A are owned by
alicewhen viewed on node B - [ ]
klistshows a Kerberos ticket after login - [ ]
kinit alicesucceeds after the ticket expires - [ ] Removing a user from IPA deactivates login on all nodes within cache TTL
- [ ]
sudo -lenforces LDAP-stored sudo rules (if centralized)
Gotchas¶
- UID collisions: always reserve a range for directory users and never let local
adduserdip into it. - NFS without Kerberos: UIDs are trusted wire-side. Fine on an isolated management network, dangerous on anything bigger.
- Case sensitivity: LDAP usernames are case-insensitive by default; POSIX is not. Enforce lowercase-only usernames.
- Home directory permissions:
chmod 700 /home/aliceis the safe default;umask 077in profile to match. - SSSD cache staleness: after an IPA password change, the old password may work until cache invalidates. Use
sss_cache -u aliceto force refresh. - macOS clients: don't assume binding macOS to FreeIPA gives the same UX as Linux. Most teams keep Mac users local and only sync SSH keys through IPA.
Related¶
- shared-storage.md — the NAS layer underneath
/home - compute-scheduling.md — same identity layer is used by SLURM accounts and K8s RBAC
- virtualization.md — IPA / LDAP servers typically run as VMs on Proxmox / ESXi
- docs/tools/infrastructure-as-code.md — Terraform providers for FreeIPA, LDAP