Home / Alt manpages / pam_mkhomedir(8)

  • pam_mkhomedir(8)
  • Admin command
  • linux

Create Missing Network User Home Directories with pam_mkhomedir

Nothing kills a first login from a network account faster than a missing home directory, and pam_mkhomedir builds one on the fly. It copies the selected skeleton files, applies a predictable directory mode, and leaves the directory in place after logout. These examples use Linux-PAM from Ubuntu package libpam-modules version 1.5.3-5ubuntu5.7.

Allow about 15 minutes, plus one test login. You need root access, a readable skeleton directory, and a PAM service your users actually use, such as SSH or a display manager. This changes authentication-session configuration, so keep an existing root shell or console session open while testing.

Safety warning

A malformed PAM file can prevent logins. Back up the service file before editing it, change one service at a time, and do not close your working administrative session until a new login has succeeded.

1. Confirm the module and choose the PAM service

Check that the package and module are installed:

$ dpkg-query -W -f='\${Package} \${Version}\n' libpam-modules:amd64
libpam-modules:amd64 1.5.3-5ubuntu5.7
$ test -r /usr/lib/x86_64-linux-gnu/security/pam_mkhomedir.so && echo 'module present'
module present

The PAM service file controls when the module runs. For SSH that is normally /etc/pam.d/sshd; for a text console it may be /etc/pam.d/login. Inspect the file you intend to change and confirm it has a session section:

$ sudo sed -n '1,220p' /etc/pam.d/sshd

Replace sshd in the command with the service used by your central-login path. Do not add this line to an unrelated service and assume it will affect every login.

2. Inspect the skeleton and permission defaults

Files in /etc/skel are copied into a newly created home directory. Review them before enabling the module, because a skeleton can contain shell startup files and other user-visible defaults:

$ sudo find /etc/skel -maxdepth 2 -printf '%M %u:%g %p\n'
$ grep -E '^(HOME_MODE|UMASK)[[:space:]]' /etc/login.defs

On this machine, HOME_MODE 0750 and UMASK 022 are present. Without an explicit umask= option, the installed module uses HOME_MODE when it is available. If it is absent, it computes a mode from UMASK; if neither setting exists, the documented fallback is 0755.

This is a directory permission decision, not just a formatting option. A mode such as 0750 keeps unrelated users from reading the home directory, but it may not suit every shared-group arrangement. Decide the policy before touching PAM.

3. Back up the service file

Run this as root, substituting the service you selected:

$ sudo cp --preserve=mode,ownership,timestamps /etc/pam.d/sshd /etc/pam.d/sshd.before-pam_mkhomedir
$ sudo ls -l /etc/pam.d/sshd /etc/pam.d/sshd.before-pam_mkhomedir

The backup gives you a direct recovery path. If a later login test fails, restore it from the still-open administrative session with:

$ sudo cp --preserve=mode,ownership,timestamps /etc/pam.d/sshd.before-pam_mkhomedir /etc/pam.d/sshd

4. Add the session rule

Edit the chosen PAM file as root and add one line in its existing session section:

session required pam_mkhomedir.so skel=/etc/skel/ umask=0022

The session module type is the only one pam_mkhomedir provides. The required control means failure is reported as a PAM failure, although PAM may still run later session modules before returning. This example makes the creation mask explicit and uses the normal skeleton directory. If you want the service to follow HOME_MODE and UMASK instead, omit umask=0022:

session required pam_mkhomedir.so skel=/etc/skel/

Use an alternative skeleton only when you have deliberately created and reviewed it, for example skel=/srv/login-skel/. The path must be readable by the session process.

Warning

Do not put passwords, private keys or machine-specific secrets in any skeleton directory. Everything in it gets copied into every new home.

Checkpoint

Inspect the finished session section before testing. Look for a single correctly spelt pam_mkhomedir.so line, the intended control flag, and a skeleton path that exists.

5. Test with a user whose home is missing

Start a new login through the service you changed, using a real centrally managed account whose home directory does not already exist. If you have a disposable test account, confirm its home path first:

$ getent passwd EXAMPLE_USER
EXAMPLE_USER:x:20001:20001:Example User:/home/EXAMPLE_USER:/bin/bash
$ sudo test ! -e /home/EXAMPLE_USER && echo 'home is absent'
home is absent

Warning

Do not delete an existing home directory just to force a test. That destroys user data.

After the new session opens, check the result from the retained administrative session:

$ sudo stat -c '%A %a %U:%G %n' /home/EXAMPLE_USER
drwxr-x--- 750 EXAMPLE_USER:EXAMPLE_USER /home/EXAMPLE_USER
$ sudo find /home/EXAMPLE_USER -maxdepth 1 -mindepth 1 -printf '%f\n' | sort
.bash_logout
.bashrc
.profile

The exact skeleton file list depends on your host. What matters is that the directory owner and group match the account, its mode matches your policy, and the expected skeleton files were copied. The module does not remove the directory when the user logs out.

6. Diagnose a failed session

If the login fails with a PAM error, restore the backup first, then investigate. Check without changing anything:

$ getent passwd EXAMPLE_USER
$ sudo namei -l /home/EXAMPLE_USER
$ sudo test -r /etc/skel/.profile && echo 'skeleton readable'
$ sudo journalctl -b --no-pager | grep -iE 'pam_mkhomedir|pam|EXAMPLE_USER' | tail -n 40
  • PAM_PERM_DENIED means the module could not create the home directory or read the skeleton. Check the parent directory, the selected skeleton, and the account's home path.
  • PAM_USER_UNKNOWN means the underlying authentication stack does not know the user at the point this session module runs. Fix identity lookup and account ordering rather than creating a directory by hand.

A home that already exists is not recreated; check its ownership and permissions separately. The optional silent argument suppresses informative messages. The optional debug argument sends diagnostic information to syslog: use it briefly when your logging policy permits it, then remove it after diagnosis. It does not repair permissions or create a home outside the PAM session.

Done means

  • Module confirmed. The installed pam_mkhomedir.so module and package version were checked.
  • Service correct. The right PAM service has one reviewed session rule.
  • Policy matched. The skeleton directory and home-directory mode match your access policy.
  • Test login succeeded with the right owner, group and permissions on the new home.
  • Backup kept until the change has been observed in normal use.