PAM maxlogins limit not working

Since upgrading from CentOS 7 to Rocky Linux 8 our PAM maxlogins limit is no longer being enforced for SFTP sessions.

SFTP users belong to the sftp group and we have this in /etc/security/limits.d/10-maxlogins.conf

@sftp        -       maxlogins       1

We use internal-sftp for SFTP sessions and have this in /etc/ssh/sshd_config

Subsystem sftp  internal-sftp -l INFO

Match Group sftp
        ChrootDirectory %h
        ForceCommand internal-sftp
        AllowTcpForwarding no

However, users are still managing to open > 1 concurrent SFTP sessions. Should we be doing anything different in EL8 to enforce these limits?

PAM debug logs below show it’s reading the relevant config files. However, the limit is not enforced.

Apr 10 16:13:04 sftp-test sshd[40955]: Accepted password for sftptest from 10.3.200.146 port 60976 ssh2
Apr 10 16:13:04 sftp-test sshd[40955]: pam_limits(sshd:session): reading settings from '/etc/security/limits.conf'
Apr 10 16:13:04 sftp-test sshd[40955]: pam_limits(sshd:session): reading settings from '/etc/security/limits.d/10-max-logins.conf'
Apr 10 16:13:04 sftp-test sshd[40955]: pam_limits(sshd:session): checking if sftptest is in group sftp
Apr 10 16:13:04 sftp-test sshd[40955]: pam_limits(sshd:session): process_limit: processing - maxlogins 1 for GROUP
Apr 10 16:13:04 sftp-test sshd[40955]: pam_limits(sshd:session): checking logins for 'sftptest' (maximum of 1)
Apr 10 16:13:04 sftp-test systemd[40960]: pam_unix(systemd-user:session): session opened for user sftptest(uid=1000) by sftptest(uid=0)
Apr 10 16:13:04 sftp-test sshd[40955]: pam_unix(sshd:session): session opened for user sftptest(uid=1000) by sftptest(uid=0)
Apr 10 16:13:26 sftp-test sshd[40986]: Accepted password for sftptest from 10.3.200.146 port 52110 ssh2
Apr 10 16:13:26 sftp-test sshd[40986]: pam_limits(sshd:session): reading settings from '/etc/security/limits.conf'
Apr 10 16:13:26 sftp-test sshd[40986]: pam_limits(sshd:session): reading settings from '/etc/security/limits.d/10-max-logins.conf'
Apr 10 16:13:26 sftp-test sshd[40986]: pam_limits(sshd:session): checking if sftptest is in group sftp
Apr 10 16:13:26 sftp-test sshd[40986]: pam_limits(sshd:session): process_limit: processing - maxlogins 1 for GROUP
Apr 10 16:13:26 sftp-test sshd[40986]: pam_limits(sshd:session): checking logins for 'sftptest' (maximum of 1)
Apr 10 16:13:26 sftp-test sshd[40986]: pam_unix(sshd:session): session opened for user sftptest(uid=1000) by sftptest(uid=0)

What about MaxSessions 1 in the Match block …

I do not believe MaxSessions will work in this case. Here’s what it boils down to:

  • MaxSessions works only the amount of sessions that are multiplexed over a single connection, so no that will not help
  • maxlogins only applies to interactive shells - sftp is not an interactive shell.

The right way to do this is to use nproc in your limits. The reason why you need to use nproc is because sftp uses two processes by design. In EL8 and 9, the systemd user manager also consumes two processes per user.

@sftp hard nproc 4

To calculate that number: 2 * X + 2. The variable here will be how many sessions you wish to limit. In this case, you want 1. The answer then is 4.

This is easy to verify. Below I am already logged into my machine.

[label@cm02 ~]$ who
label    pts/0        2025-04-08 23:09 (router)
[label@cm02 ~]$ cat /etc/security/limits.d/label.conf
label hard nproc 6
[label@cm02 ~]$

Let’s try to login again.

[label@sani ~]$ ssh -q label@cm02
Last login: Sat Apr 12 19:22:30 2025 from 10.100.0.140
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: Resource temporarily unavailable
-bash-5.1$ clear
-bash: fork: retry: Resource temporarily unavailable

With sftp, it will just hang until it eventually gives up.

[label@sani ~]$ sftp -q cm02
Connection closed

If I logout while it’s hanging, it will eventually give me a prompt.

[label@sani ~]$ sftp -q cm02
sftp> ls
sftp>
1 Like

Many thanks, @nazunalika! Setting nproc limit does indeed work.

I could have sworn maxlogins worked for internal-sftp in CentOS 7, but will have to double check.