Under the classic Unix philosophy, “everything is a file”.
In Linux, a file descriptor (FD) is not just a pointer to a physical document on an SSD. A file descriptor represents an open configuration file, a temporary scratch buffer, an active database .ibd tablespace, a UNIX domain socket between Nginx and PHP-FPM, and—most importantly—every single incoming TCP connection from a website visitor.
When your website experiences a surge during a marketing flash sale in Pakistan, Nginx opens thousands of simultaneous client TCP connections while opening thousands of upstream connections to PHP-FPM and MariaDB.
If your operating system operates under default resource limits, your server abruptly collapses with the fatal error:
nginx: [alert] 18452#0: *48120 socket() failed (24: Too many open files)
Or in MariaDB’s error.log:
[ERROR] Error in accept: Too many open files
To visitors, your site serves generic 500 Internal Server Error or drops connections completely.
In this deep systems engineering tutorial, we examine the three distinct layers of Linux file descriptor governance, show you how to inspect per-process limits, and explain how to calibrate nofile thresholds across sysctl, limits.conf, and systemd.
Key Takeaways for DevOps & System Administrators
- The 1,024 File Descriptor Default Trap: By default, Linux user sessions inherit a soft
nofilelimit of just 1,024 file descriptors. On a web server handling 500 concurrent connections, each connection using 2 sockets plus static files immediately breaches 1,024, crashing the process. - The Three Governance Layers: File descriptor ceilings are enforced at three distinct layers: 1) System-wide kernel ceiling (
fs.file-max), 2) PAM user session limits (/etc/security/limits.conf), and 3) Modern systemd service unit overrides (LimitNOFILE). Tuning only one layer while ignoring the others leaves the limit restricted. - Modern Systemd Precedence: In Ubuntu 20.04+, Debian 11+, and RHEL/AlmaLinux 8/9, services started via
systemctlignore/etc/security/limits.confentirely! You must configureLimitNOFILEdirectly inside the service override file. - Enterprise Scale Architecture: Extreme concurrency workloads processing over 50,000 requests per second run best on bare-metal Dedicated Servers in Pakistan with dedicated memory bandwidth, zero virtualization limits, and sub-10ms domestic ping.
Step 1: Layer 1 – System-Wide Kernel Ceiling (fs.file-max)
The first layer governs the absolute maximum number of open file handles the entire operating system kernel is permitted to allocate across all running processes combined.
Check your current system ceiling:
sysctl fs.file-max
On typical modern distributions, this value is set to a reasonable number (e.g., 1 to 2 million). However, on smaller cloud VPS instances, it may be restricted to 65,536.
To raise the system-wide ceiling to 2,097,152 (2 Million):
sudo sysctl -w fs.file-max=2097152
Add this to /etc/sysctl.d/99-file-max.conf to persist across reboots:
# Maximum open files system-wide
fs.file-max = 2097152
Step 2: Layer 2 – User Session Limits (/etc/security/limits.conf)
This layer governs shells, scripts, and processes launched directly by specific users (e.g., root, nginx, mysql, www-data).
Edit /etc/security/limits.conf:
sudo nano /etc/security/limits.conf
Add the following lines at the bottom of the file:
* soft nofile 1048576
* hard nofile 1048576
root soft nofile 1048576
root hard nofile 1048576
nginx soft nofile 1048576
nginx hard nofile 1048576
mysql soft nofile 1048576
mysql hard nofile 1048576
(Note: soft is the current effective limit; hard is the maximum ceiling a non-root process can increase its soft limit to).
Step 3: Layer 3 – Systemd Service Unit Overrides (Mandatory for Daemons)
Because modern Linux services (Nginx, MariaDB, PHP-FPM, Redis) are managed by systemd, they bypass PAM session limits and use systemd default units (which often revert to 1,024 or 4,096)!
You must configure systemd drop-in overrides for each critical daemon.
1. Nginx Service Override:
sudo systemctl edit nginx
Paste the following directives:
[Service]
LimitNOFILE=1048576
In your main /etc/nginx/nginx.conf, also ensure worker connections can leverage these descriptors:
events {
worker_connections 65535;
use epoll;
multi_accept on;
}
# Match worker_rlimit_nofile to the systemd limit
worker_rlimit_nofile 1048576;
2. MariaDB / MySQL Service Override:
sudo systemctl edit mariadb
Paste:
[Service]
LimitNOFILE=1048576
In /etc/my.cnf under [mysqld]:
[mysqld]
open_files_limit = 1048576
table_open_cache = 4096
table_definition_cache = 2048
Reload systemd daemon and restart services:
sudo systemctl daemon-reload
sudo systemctl restart nginx
sudo systemctl restart mariadb
Step 4: Verifying Active Runtime Limits on Running Processes
Never assume your settings took effect without verifying the running process’s internal kernel table.
Find the Process ID (PID) of your Nginx master process and MariaDB:
# Check Nginx master PID
ps aux | grep "nginx: master" | grep -v grep
# Query effective limits from the /proc filesystem (e.g. PID 18450)
cat /proc/18450/limits | grep "Max open files"
Expected output:
Limit Soft Limit Hard Limit Units
Max open files 1048576 1048576 files
If both Soft Limit and Hard Limit display 1048576, your web server can now smoothly handle hundreds of thousands of concurrent client sockets, keepalives, and static assets without ever dropping a connection!
Scaling Enterprise Workloads on Dedicated Bare Metal
Tuning file descriptors allows Linux to keep millions of sockets open simultaneously. However, servicing those sockets requires unshared physical memory bandwidth and massive CPU interrupt handling capacity.
When running on virtualized VPS instances, CPU core contention can throttle network interrupt handling (softirqs), causing packet latency even if file descriptors remain available.
Upgrading to high-throughput Dedicated Servers provides unshared multi-core AMD EPYC or Intel Xeon processors capable of servicing heavy I/O workloads with zero throttling.
For Pakistani webmasters, fintech apps, and e-commerce platforms, our Dedicated Servers in Pakistan provide domestic sub-10ms network routes across PTCL, Nayatel, and StormFiber with enterprise hardware firewall protection.
Ready for True Bare-Metal & Enterprise Cloud Power in Pakistan?
Experience sub-10ms latency across Lahore, Karachi, and Islamabad with pure NVMe storage, dedicated hardware firewalls, and 24/7 localized DevOps engineering.
