How to Increase nproc and nofile Limits for Systemd Services in CentOS 7


2 views

When managing system resources in CentOS 7, many administrators encounter situations where process limits (nproc) and file descriptors (nofile) set in /etc/security/limits.conf don't properly apply to systemd-managed services. This is particularly noticeable with services like MariaDB, Apache, or custom daemons.

The standard Unix PAM limits mechanism doesn't work for systemd services because:

1. Systemd doesn't use PAM for service processes by default
2. Services often run as non-login accounts (like mysql)
3. The systemd process manager implements its own resource control

For MariaDB specifically, you need a multi-pronged approach:

Method 1: Systemd Service Unit Override

# Create override directory if needed
sudo mkdir -p /etc/systemd/system/mariadb.service.d/

# Create override file
sudo tee /etc/systemd/system/mariadb.service.d/limits.conf > /dev/null <

Method 2: Global Systemd Configuration

# Edit /etc/systemd/system.conf
sudo sed -i '/^#DefaultLimitNOFILE=/s/^#//' /etc/systemd/system.conf
sudo sed -i '/^DefaultLimitNOFILE=/s/[0-9]*$/102400/' /etc/systemd/system.conf

# Similarly for nproc
sudo sed -i '/^#DefaultLimitNPROC=/s/^#//' /etc/systemd/system.conf
sudo sed -i '/^DefaultLimitNPROC=/s/[0-9]*$/10240/' /etc/systemd/system.conf

sudo systemctl daemon-reload

After making changes, verify with:

# Check service limits
cat /proc/$(pgrep -f mariadbd)/limits

# Alternative method for running services
systemctl show mariadb --property LimitNOFILE,LimitNPROC

# System-wide settings check
systemctl show --property DefaultLimitNOFILE
systemctl show --property DefaultLimitNPROC

Even with systemd limits set, MariaDB has its own configuration parameters that may need adjustment in /etc/my.cnf.d/server.cnf:

[server]
open_files_limit = 102400
table_open_cache = 2000
max_connections = 500

If limits still aren't applying:

  1. Check if SELinux is enforcing: getenforce
  2. Verify the service isn't being started through an init script
  3. Ensure no conflicting settings in /etc/security/limits.d/
  4. Check for user-specific overrides: systemctl show user@$(id -u).service

When increasing these limits:

  • Monitor kernel memory usage (cat /proc/meminfo | grep Slab)
  • Adjust kernel parameters if needed: sysctl -w fs.file-max=2097152
  • For high-connection services, consider TCP stack tuning

When working with systemd-managed services on CentOS 7, you'll notice that traditional methods like /etc/security/limits.conf don't affect daemon processes. This occurs because systemd implements its own resource control mechanism through service unit files.


# Traditional limits.conf won't work for systemd services
* soft nofile 102400
* hard nofile 102400

For services managed by systemd (like MariaDB, Apache, or Postfix), you need to modify their service unit files or create drop-in configurations:


# For MariaDB example
sudo systemctl edit mariadb.service

[Service]
LimitNOFILE=102400
LimitNPROC=10240

To check actual limits applied to running processes:


cat /proc/$(pgrep -f mysqld)/limits | grep "Max open files"
cat /proc/$(pgrep -f httpd)/limits | grep "Max processes"

For different services, here are specific implementation examples:


# Apache httpd example
sudo mkdir -p /etc/systemd/system/httpd.service.d/
sudo tee /etc/systemd/system/httpd.service.d/limits.conf <<EOF
[Service]
LimitNOFILE=102400
LimitNPROC=10240
EOF

# Postfix example (using override.conf)
sudo systemctl edit postfix

[Service]
LimitNOFILE=40960
LimitNPROC=20480

For global defaults affecting all systemd services:


# Create system-wide configuration
sudo tee /etc/systemd/system.conf.d/limits.conf <<EOF
[Manager]
DefaultLimitNOFILE=102400:102400
DefaultLimitNPROC=10240:10240
EOF

After making changes, always remember to:


sudo systemctl daemon-reload
sudo systemctl restart mariadb
sudo systemctl restart httpd

When encountering issues, check these diagnostic commands:


# Check applied limits
systemctl show mariadb | grep -i limit

# Verify kernel parameters
sysctl fs.file-max
sysctl fs.nr_open

# Compare with process limits
grep -i "max open files" /proc/$(pgrep -f mysqld)/limits