Sometimes, I want to prevent regular users from logging into the system to perform more complex operations.
To achieve that, I am using Pluggable Authentication Modules for Linux to temporarily disable user logins.

Basic usage

Disable user logins without providing a reason.

$ sudo touch /run/nologin

Example of a failed login attempt (as regular user).

$ ssh milosz@remote_server
milosz@remote_server's password:
Connection closed by remote_server

Disable user logins providing an additional reason.

$ echo "System maintenance in progress" | sudo tee /run/nologin

Example of a failed login attempt (as regular user).

$ ssh milosz@remote_server
milosz@remote_server's password:
System maintenance in progress
Connection closed by remote_server

Notice that /var/run is a link to /run directory, so I have used shorter version.

Pluggable Authentication Modules configuration

Set of rules that determines behavior of pam_nologin module for the Shadow login service is defined in /etc/pam.d/login Pluggable Authentication Modules configuration file.

By default only root user can login if /run/nologin file exists.

# Disallows other than root logins when /etc/nologin exists
# (Replaces the `NOLOGINS_FILE' option from login.defs)
auth       requisite  pam_nologin.so

Use pam_succeed_if module once to bypass that restriction for users in the admins group.

# Disallows other than root logins when /etc/nologin exists
# (Replaces the `NOLOGINS_FILE' option from login.defs)
# ignore rule if user is in admins group
  auth [default=1 success=ignore] pam_succeed_if.so quiet user notingroup admins
  auth requisite  pam_nologin.so

Set of rules that determines behavior of pam_nologin module for the Secure Shell service is defined in /etc/pam.d/sshd Pluggable Authentication Modules configuration file.

By default no one can login over SSH protocol if /run/nologin file exists [assuming that PermitRootLogin SSH configuration directive is not enabled].

# Disallow non-root logins when /etc/nologin exists.
account    required     pam_nologin.so

Use pam_succeed_if module multiple times to bypass that restriction for users in admins group and milosz username.

# Disallow non-root logins when /etc/nologin exists.
account [default=2 success=ignore] pam_succeed_if.so quiet user != milosz
account [default=1 success=ignore] pam_succeed_if.so quiet user notingroup admins
account required pam_nologin.so

You can use user, uid, gid, shell, home, ruser, rhost, tty, service fields to build a condition which consist of three words: field, test and a value to test for.

In above-mentioned examples pam_succeed_if module will skip execution of given number of rules on condition failure.
To explain and illustrate this behavior I have prepared the following real world examples based upon previous configuration.

Situation in which user name and group differs. Access will be denied as pam_nologin module is executed.

Sep  7 05:52:11 debian sshd[6728]: pam_succeed_if(sshd:account): 'user' resolves to 'pawel'
Sep  7 05:52:11 debian sshd[6728]: pam_succeed_if(sshd:account): requirement "user != milosz" was met by user "pawel"
Sep  7 05:52:11 debian sshd[6728]: pam_succeed_if(sshd:account): 'user' resolves to 'pawel'
Sep  7 05:52:11 debian sshd[6728]: pam_succeed_if(sshd:account): requirement "user notingroup admins" was met by user "pawel"
Sep  7 05:52:11 debian sshd[6728]: Failed password for pawel from ::1 port 57219 ssh2
Sep  7 05:52:11 debian sshd[6728]: fatal: Access denied for user pawel by PAM account configuration [preauth]

Situation in which user name differs, group matches. Access will be granted as pam_nologin module is not executed.

Sep  7 05:53:31 debian sshd[6740]: pam_succeed_if(sshd:account): 'user' resolves to 'michael'
Sep  7 05:53:31 debian sshd[6740]: pam_succeed_if(sshd:account): requirement "user != milosz" was met by user "michael"
Sep  7 05:53:31 debian sshd[6740]: pam_succeed_if(sshd:account): 'user' resolves to 'michael'
Sep  7 05:53:31 debian sshd[6740]: pam_succeed_if(sshd:account): requirement "user notingroup admins" not met by user "michael"
Sep  7 05:53:31 debian sshd[6740]: Accepted password for michael from ::1 port 57220 ssh2
Sep  7 05:53:31 debian sshd[6740]: pam_unix(sshd:session): session opened for user michael by (uid=0)

Situation in which user name matches. Access will be granted as group condition is not evaluated and pam_nologin module is not executed.

Sep  7 05:54:11 debian sshd[6755]: pam_succeed_if(sshd:account): 'user' resolves to 'milosz'
Sep  7 05:54:11 debian sshd[6755]: pam_succeed_if(sshd:account): requirement "user != milosz" not met by user "milosz"
Sep  7 05:54:11 debian sshd[6755]: Accepted password for milosz from ::1 port 57221 ssh2
Sep  7 05:54:11 debian sshd[6755]: pam_unix(sshd:session): session opened for user milosz by (uid=0)

References

Read pam_nologin and pam_succeed_if manual pages to get detailed information.

ko-fi