When modifying system resource limits through /etc/security/limits.conf
, many administrators encounter a persistent issue: changes don't take effect for existing SSH sessions without a full system reboot. This becomes particularly problematic when implementing memory restrictions like:
* soft rss 64000000
* hard nofile 50000
* soft nofile 1024
While su - user
properly reloads limits, SSH sessions mysteriously resist changes. This occurs because PAM (Pluggable Authentication Modules) only applies these limits during the initial authentication phase. The SSH daemon maintains existing sessions without reapplying the updated limits.
Here are proven methods to enforce new limits for SSH users:
# Method 1: Restart SSHD service (preserves existing connections)
sudo systemctl restart sshd
# Method 2: Kill all existing SSH sessions
sudo pkill -9 sshd && sudo systemctl start sshd
After applying changes, test with:
# For memory limits verification
ulimit -S -v
ulimit -H -v
# For file descriptor verification
ulimit -S -n
ulimit -H -n
For more granular control, create files in /etc/security/limits.d/
:
# /etc/security/limits.d/90-developers.conf
@developers hard nofile 65000
@developers soft rss 128000000
Ensure your PAM stack includes these critical elements:
# /etc/pam.d/sshd should contain:
session required pam_limits.so
session required pam_env.so
# Verify SSHD config contains:
UsePAM yes
When modifying /etc/security/limits.conf
to implement memory and file descriptor controls, the changes don't automatically apply to existing sessions. The behavior differs between local logins (su - user
) and SSH connections, even with proper PAM configuration.
# Typical working PAM stack for su:
auth required pam_env.so
auth required pam_limits.so # Critical for session-init
# Common SSH PAM caveat:
session required pam_limits.so # Often appears too late in the stack
SSH sessions initialize limits differently because of two factors:
- The PAM module ordering in
/etc/pam.d/sshd
- SSH's own internal limit handling that may override PAM
1. Force PAM Reinitialization
For existing SSH sessions, execute:
# As root:
pam_exec -v -d5 /etc/security/limits.conf
# Alternative method:
service sshd reload && pkill -PAM sshd
2. Verify PAM Configuration
Ensure your /etc/pam.d/sshd
contains:
# Place this early in the file
session required pam_limits.so
session optional pam_exec.so /etc/security/limits.d/refresh.sh
3. Immediate Testing Methodology
To verify without reboot:
# Test sequence:
ssh user@localhost -t "ulimit -a; grep 'Max open files' /proc/self/limits"
# Expected output matching your limits.conf:
Max open files 1024 50000
For granular control, create /etc/security/limits.d/90-custom.conf
:
# Memory limits
* soft rss 64000000
@powerusers hard rss unlimited
# File descriptors
* soft nofile 1024
* hard nofile 50000
@devteam hard nofile 100000
grep pam_limits /etc/pam.d/*
for module presencessh -vvv user@localhost
to trace PAM initializationcat /proc/$(pgrep sshd)/limits
for daemon-level limits
For systemd systems, create /etc/systemd/system/ssh-refresh.service
:
[Unit]
Description=SSH limits refresh
After=network.target
[Service]
ExecStart=/bin/bash -c "sysctl -p /etc/sysctl.d/*.conf && /sbin/pam_limits"
[Install]
WantedBy=multi-user.target