Updated: 18 October 2026 · Applies to: systemd 259 and Linux-PAM 1.7.0 on Ubuntu 26.04, systemd 257 and Linux-PAM 1.6.1 on AlmaLinux 10.2, Linux kernel 6.12 (the same settings work on Debian 13, Ubuntu 24.04 and Rocky Linux 9 and 10)

The open files limit in Linux is set per process. Check it with ulimit -n (soft limit) and ulimit -Hn (hard limit). For a service, raise it with LimitNOFILE=65535 in a systemd override and restart the service. For SSH and console logins, add nofile lines to a file in /etc/security/limits.d/ and log in again. Above both sit two kernel settings: fs.nr_open, the highest limit any single process may get (1048576 by default), and fs.file-max, the total for the whole system.

When a process reaches its limit, opening a file, socket or connection fails with Too many open files (EMFILE). Busy web servers, databases and Node.js apps are the usual victims.

1. Check the current limits

ulimit -Sn                      # soft limit of this shell
ulimit -Hn                      # hard limit of this shell
cat /proc/PID/limits | grep "open files"   # a running process
ls /proc/PID/fd | wc -l         # files it has open now
sysctl fs.nr_open fs.file-max fs.file-nr

Typical values: services and logins on a systemd server get soft 1024 and hard 524288 (the documented systemd default 1024:524288; a normal user logging in on our Ubuntu 26.04 lab showed soft 1024 hard 524288). A kernel booted without systemd gave processes 1024 and 4096. fs.file-max depends on memory and the distribution: 24546 on a 256 MB test kernel, but 9223372036854775807 on our AlmaLinux 9 test host, so it is rarely the bottleneck. In file-nr the first number is the handles in use and the last is the maximum.

2. Fix "ulimit: open files: cannot modify limit: Operation not permitted"

A normal user can move the soft limit anywhere up to the hard limit, and can lower the hard limit, but cannot raise it. We got this error in four situations (lab output):

  1. Going above the hard limit as a normal user. With a hard limit of 65535:
    $ ulimit -n 70000
    -bash: ulimit: open files: cannot modify limit: Operation not permitted
    Fix: raise the hard limit for that user (step 5) or service (step 3), log in again, then run ulimit -n.
  2. An earlier ulimit -n lowered the hard limit. ulimit -n 2048 sets the soft and the hard limit, so a later ulimit -n 4096 in the same shell fails. Use ulimit -Sn 2048 to change only the soft limit, and check .bashrc, .profile and start scripts for such lines.
  3. Root asking for more than fs.nr_open. Even root gets the error for ulimit -Hn 2000000 or ulimit -n unlimited while fs.nr_open is 1048576. After sysctl -w fs.nr_open=2097152 the same command worked (soft and hard 2000000).
  4. Root inside a container. Containers normally run without the CAP_SYS_RESOURCE capability, so root cannot raise the hard limit there. Set the limit when the container starts (step 8).

A soft limit above the hard limit gives a different message: ulimit -Sn 5000 with a hard limit of 4096 printed cannot modify limit: Invalid argument.

3. Raise the limit for a service (the usual fix)

  1. Open an override for the service, for example Nginx: systemctl edit nginx
  2. Add these lines and save:
    [Service]
    LimitNOFILE=65535
    Without the editor, create the same file yourself and reload:
    mkdir -p /etc/systemd/system/nginx.service.d
    printf '[Service]\nLimitNOFILE=65535\n' > /etc/systemd/system/nginx.service.d/override.conf
    systemctl daemon-reload
  3. Restart the service. A reload is not enough: in our test the running process kept its old limit until the restart.
    systemctl restart nginx
  4. Check both the setting and the real process (lab output from a test service):
    $ systemctl show nginx -p LimitNOFILE -p LimitNOFILESoft
    LimitNOFILE=65535
    LimitNOFILESoft=65535
    $ grep "open files" /proc/$(systemctl show -p MainPID --value nginx)/limits
    Max open files            65535                65535                files

LimitNOFILE=8192:65535 sets the soft and hard limit separately (we saw 8192 and 65535 in /proc). The systemd manual warns that select() cannot use file descriptors above 1023, so it suggests a high hard limit and lets programs raise their own soft limit. Some programs have their own setting too: Nginx has worker_rlimit_nofile, and for MySQL and MariaDB see how to raise ulimit open files and MySQL open_files_limit.

4. Change the default for all services (DefaultLimitNOFILE)

  1. Create a drop-in instead of editing the main file (on AlmaLinux 10.2 the file is /usr/lib/systemd/system.conf and there is no copy in /etc/systemd/):
    mkdir -p /etc/systemd/system.conf.d
    printf '[Manager]\nDefaultLimitNOFILE=4096:524288\n' > /etc/systemd/system.conf.d/90-nofile.conf
  2. Run systemctl daemon-reexec, then check with systemctl show -p DefaultLimitNOFILE -p DefaultLimitNOFILESoft (our lab showed 524288 and 4096; systemctl daemon-reload alone already showed the new values).
  3. Restart the services, or reboot. A restarted service got 4096 and 524288; services with their own LimitNOFILE keep that value.

User services (systemctl --user) use DefaultLimitNOFILE in /etc/systemd/user.conf instead.

5. Raise the limit for users (SSH and console logins)

  1. Create /etc/security/limits.d/90-nofile.conf:
    appuser  soft  nofile  65535
    appuser  hard  nofile  65535
    Use * for all users. The wildcard does not apply to root: in our test * gave appuser 32768 while root stayed at 1024, until we added lines with the user name root.
  2. Log in again and check: before the change su - appuser showed soft 1024 hard 524288, afterwards soft 65535 hard 65535.

These files are read by the pam_limits module at login. On Ubuntu 26.04 it is in the PAM files for sshd, login, su, sudo and runuser; on AlmaLinux 10.2 it is in system-auth and password-auth, which su and sshd include. systemd services do not log in through PAM, so limits.conf never changes a service. A typing mistake is only logged, for example pam_limits(su-l:session): unknown limit item 'nofiles', and a value the kernel refuses is logged as Could not set limit for 'nofile' ... Operation not permitted while the login keeps its old limits. More on the file format in understanding /etc/security/limits.conf.

6. Raise the kernel limits (fs.nr_open and fs.file-max)

Only needed for limits above 1048576 per process, or when the system total is reached. To allow up to 2097152 per process:

$ printf 'fs.nr_open = 2097152\n' > /etc/sysctl.d/90-nofile.conf
$ sysctl -p /etc/sysctl.d/90-nofile.conf
fs.nr_open = 2097152

Check sysctl fs.file-max before touching it. Only if it is lower than you need, add a line such as fs.file-max = 2097152 to the same file; never set it lower than the current value.

The two limits give different errors. In our tests a process at its own limit printed bash: /dev/null: Too many open files, while a full system printed Too many open files in system and the kernel logged VFS: file-max limit 3000 reached (we had set file-max to 3000 for the test).

7. Change a running process without a restart

$ prlimit --pid 1234 --nofile=4096:65535
$ grep "open files" /proc/1234/limits
Max open files            4096                 65535                files

Run it as root. The change is lost when the process restarts, so also add the permanent setting from step 3 or 5.

8. Containers

Pass the limit when the container starts: --ulimit nofile=65535:65535. With podman 5.8 a container showed soft 65535 hard 65535 with the flag; Docker uses the same flag, and according to Docker, Compose files take ulimits: with nofile: soft: and hard: under the service.

If the limit is right but errors continue, the program may leak descriptors: watch ls /proc/PID/fd | wc -l over time, and if it only grows, the application needs fixing.

Official documentation: systemd.exec (LimitNOFILE), systemd-system.conf (DefaultLimitNOFILE), limits.conf and kernel fs sysctl documentation.

Related services

KVM VPS hosting

NVMe SSD and full root access, with Free Basic Managed Support.

Unmanaged dedicated servers

full root access and free IPMI KVM, with Free Basic Managed Support.

Managed dedicated servers

our engineers look after the server for you, from $135 a month.

Was this answer helpful?

Still stuck? Open a ticket