Why Redis Process Ignores Ulimit File Descriptor Settings on Debian: Debugging and Fixes


7 views

When I recently inspected our Redis instance's file descriptor limits via cat /proc/<redis-pid>/limits, the output showed a puzzling 4016 limit despite our system-wide configurations:

# Current process limits
Limit                     Soft Limit           Hard Limit           
Max open files            4016                 4016

We had properly configured multiple levels of settings:

# /etc/security/limits.conf
* soft nofile 100000
* hard nofile 100000

# /etc/sysctl.conf
fs.file-max = 100000

# /etc/pam.d/sshd
session required pam_limits.so

On Debian systems using systemd (which includes Squeeze and later), services often ignore traditional PAM limits. Redis installed via package manager typically uses systemd for process management. Here's how to verify:

systemctl status redis-server

For systemd-managed services, we need to set limits in the service unit file. Create or modify:

# /etc/systemd/system/redis-server.service.d/limits.conf
[Service]
LimitNOFILE=100000

Then reload and restart:

systemctl daemon-reload
systemctl restart redis-server

After making changes, verify with:

# Check systemd's view
systemctl show redis-server --property LimitNOFILE

# Check actual process
cat /proc/$(pgrep redis-server)/limits | grep "Max open files"

For older systems not using systemd, edit the init script:

# /etc/init.d/redis-server
ulimit -n 100000
# Add this before the actual startup command
  • Always restart the service after changes
  • Check for duplicate configuration files
  • Remember that systemd has separate soft and hard limit settings
  1. System-wide limits in limits.conf
  2. Kernel parameters in sysctl.conf
  3. Systemd service overrides (if applicable)
  4. PAM configuration for SSH sessions

When examining our Redis server's process limits via cat /proc/<redis-pid>/limits, we encountered a puzzling scenario:

Limit                     Soft Limit           Hard Limit           
Max open files            4016                 4016

This persisted despite having proper configurations in:

  • /etc/sysctl.conf: fs.file-max = 100000
  • /etc/security/limits.conf: * soft nofile 100000
  • PAM configuration files

Linux process limits follow strict inheritance rules. The key factors affecting our Redis process:

# Verify system-wide file descriptors
cat /proc/sys/fs/file-max
# Check current user limits (run as redis user)
ulimit -n

Common reasons for limit propagation failures:

  1. Systemd service files overriding limits
  2. Init script spawning processes before PAM applies limits
  3. Containerization breaking traditional limit inheritance

On Debian systems using systemd (since Jessie), Redis typically installs with:

# /lib/systemd/system/redis-server.service
[Service]
Type=forking
User=redis
Group=redis
# Often missing LimitNOFILE directive

Solution (for systemd systems):

# Create override file
sudo mkdir -p /etc/systemd/system/redis-server.service.d
echo '[Service]
LimitNOFILE=100000' | sudo tee /etc/systemd/system/redis-server.service.d/override.conf

# Reload and restart
sudo systemctl daemon-reload
sudo systemctl restart redis-server

For legacy systems like Debian Squeeze:

# Edit init script (typically /etc/init.d/redis-server)
# Add ulimit call before launching server
ulimit -n 100000
exec /usr/local/bin/redis-server /etc/redis.conf

After making changes:

# Check current process
cat /proc/$(pgrep -u redis redis-server)/limits | grep "Max open files"

# Alternative method using prlimit
sudo apt-get install util-linux
prlimit -p $(pgrep redis-server) --nofile

For comprehensive solutions:

# 1. Set in redis.conf directly
# maxclients 100000

# 2. Combine with pam_limits
# /etc/pam.d/common-session
session required pam_limits.so

# 3. Configure security limits
# /etc/security/limits.d/redis.conf
redis soft nofile 100000
redis hard nofile 100000

Remember that the fs.file-max sysctl setting controls the system-wide limit, while per-process limits are controlled via ulimit mechanisms.