Optimizing Linux File Descriptor Limits: fs.file-max vs ulimit Configuration Guide for High-Performance Servers


5 views

In Linux server administration, file descriptors (FDs) are crucial for applications that handle numerous concurrent connections like databases (HBase, MongoDB), web servers (Nginx, Apache), and big data platforms (Hadoop). The system imposes two types of limits:

  • Kernel-level limit (fs.file-max): Global maximum FDs system-wide
  • User-level limit (ulimit): Per-process and per-user FD constraints

The Linux security model implements a dual-limit system:

# View current limits
ulimit -Sn  # shows soft limit
ulimit -Hn  # shows hard limit

Soft Limit: The effective limit enforced during normal operation. Users can self-adjust up to the hard limit.

Hard Limit: The absolute ceiling that requires root privileges to modify.

For modern Linux distributions (Ubuntu 20.04+, CentOS 7+, RHEL 8+):

1. Kernel-Level Configuration

# Check current global limit
cat /proc/sys/fs/file-max

# Permanent setting (persists across reboots)
echo "fs.file-max = 500000" >> /etc/sysctl.conf
sysctl -p

2. User-Level Configuration

Create a dedicated limits configuration file:

# /etc/security/limits.d/90-nproc.conf
*       soft    nofile      100000
*       hard    nofile      200000
root    soft    nofile      200000
root    hard    nofile      400000

For services started via systemd (common on modern distros):

# Example: Override for MySQL service
sudo mkdir -p /etc/systemd/system/mysql.service.d/
echo '[Service]
LimitNOFILE=200000' | sudo tee /etc/systemd/system/mysql.service.d/limits.conf
systemctl daemon-reload
  • Changes not applying? Check if pam_limits is loaded in /etc/pam.d/system-auth
  • Systemd services ignoring limits? Use 'LimitNOFILE' in service unit files
  • Running into "Too many open files"? Verify with:
    lsof -u username | wc -l
    cat /proc/<pid>/limits

For infrastructure-as-code setups:

#!/bin/bash
# Set kernel FD limit
echo "fs.file-max = 650000" > /etc/sysctl.d/99-file-max.conf

# Configure user limits
cat > /etc/security/limits.d/99-application.conf <

When running server applications like HBase, Hadoop, or high-traffic web servers, properly configuring file descriptor limits is crucial. Linux implements two layers of control:

  • Kernel-level limit (fs.file-max): The absolute maximum file descriptors system-wide
  • User-level limit (ulimit): Per-process and per-user restrictions

In Linux user sessions:

soft limit - The current enforced value (can be increased up to hard limit)
hard limit - The maximum allowed value (requires root privileges to exceed)

To check current kernel limit:

cat /proc/sys/fs/file-max

For persistent configuration on modern Linux distributions (Ubuntu/CentOS/RHEL):

# Create or modify sysctl configuration
echo 'fs.file-max = 65000' > /etc/sysctl.d/60-file-max.conf

# Apply changes immediately
sysctl -p /etc/sysctl.d/60-file-max.conf

For per-user limits, edit /etc/security/limits.conf or create files in /etc/security/limits.d/:

*    soft nofile 65000
*    hard nofile 65000
root soft nofile 65000
root hard nofile 65000

For immediate application in current session:

ulimit -n 65000  # Temporary setting (soft limit)
ulimit -Hn 65000 # Hard limit (requires privileges)

Check currently applied limits:

# System-wide
cat /proc/sys/fs/file-nr

# Per-process
cat /proc/<pid>/limits | grep 'Max open files'

# Current shell
ulimit -n

For database servers and high-performance applications:

  • Calculate required FD count: (active connections × 1.5) + system FDs
  • Monitor usage: watch -n 1 'cat /proc/sys/fs/file-nr'
  • For systemd services: Set LimitNOFILE in unit files

For infrastructure-as-code setups (Ansible/Puppet/Chef):

# Ansible playbook snippet
- name: Configure file descriptors
  hosts: all
  tasks:
    - name: Set kernel file-max
      sysctl:
        name: fs.file-max
        value: "65000"
        state: present
        reload: yes
    
    - name: Configure user limits
      copy:
        dest: /etc/security/limits.d/99-nofile.conf
        content: |
          * soft nofile 65000
          * hard nofile 65000
          root soft nofile 65000
          root hard nofile 65000

Remember to reboot or have users re-login after changing limits configuration.