guest@6admin.io:~$

PAM: limit system resources

PAM (Pluggable Authentication Modules) does not only do authentication: the pam_limits module caps system resources per user and per group. Without limits, a process can eat all the RAM, all the file descriptors, all the process slots: that is the fork bomb, or simply a process that leaks memory.

The limits.conf file

# /etc/security/limits.conf
# <domain>  <type>  <item>  <value>

# Cap processes for all users
*       soft    nproc   2048
*       hard    nproc   4096

# Cap open file descriptors
*       soft    nofile  1024
*       hard    nofile  4096

# Cap memory (in KB)
*       soft    as      1048576
*       hard    as      2097152

# For the backup group: more open files
@backup soft    nofile  8192
@backup hard    nofile  16384

# For root: no limit
root    soft    nproc   unlimited
root    hard    nproc   unlimited
  • soft : the current limit (the process can raise it up to the hard limit)
  • hard : the maximum limit (the process cannot exceed it, even with ulimit -Hn)
  • * : all users
  • @group : a Linux group
  • root : the root user

The limits.conf items

itemwhat it caps
nprocthe number of processes
nofilethe number of open file descriptors
asmemory (address space) in KB
rssresident memory in KB (old, replaced by as)
cpuCPU time in minutes
maxloginsthe number of simultaneous sessions
corethe size of core dumps

Checking the limits

ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
max nice                (-e) 0
file size               (blocks, -f) unlimited
pending signals         (-i) 4096
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files              (-n) 1024
pipe size               (512 bytes, -p) 8
POSIX message queues    (bytes, -q) 8192
stack size              (kbytes, -s) 8192
cpu time                (seconds, -t) unlimited
max user processes      (-u) 2048
virtual memory          (kbytes, -v) unlimited

ulimit -n shows the file descriptor limit: 1024 by default, which is insufficient for a web server or a database. 4096 or 16384 is the minimum for a server.

The nofile case

The nofile is the most commonly hit limit: a web server opens one fd per connection, a database opens several per query and the 1024 cap arrives fast. The fix is in limits.conf:

www-data soft    nofile  8192
www-data hard    nofile  16384

Then the web process (Apache, nginx) must be restarted for the new limit to apply. PAM limits only apply to new sessions (login, ssh, su), not to running processes.

What PAM limits does not do

PAM limits cap resources PER LOGIN SESSION. A process launched by cron, by a daemon (init), or by an orchestrator does not go through PAM: it inherits the limits of the process that launched it. To cap a daemon’s resources, use ulimit in the launch script.

[edit: 2026] PAM limits is still the standard mechanism to cap resources per user at login. systemd has added LimitNOFILE, LimitNPROC, LimitAS in unit files (the modern mechanism for daemons) and cgroups cap at the container or service level. The 1024 default nofile has been raised to 1048576 in modern distributions (systemd default), but PAM limits remain relevant for interactive sessions and SSH connections. The fork bomb remains the most visual demonstration of why limits exist: :(){ :|:& };: and the system is dead if nproc is not capped.