Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk14 min

How to Tune ulimit on a Linux Server

Tune Linux resource limits at the layer that launches the workload: use ulimit for tests, PAM for login sessions, and systemd Limit* settings for services. This guide shows how to measure effective limits, apply changes, diagnose permission errors, and avoid select() compatibility failures.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set the limit where the workload is launched: use ulimit for a temporary shell test, PAM limits for login sessions, and systemd Limit* directives for services. Check the effective limit on the actual process, because an interactive terminal and a systemd daemon can have different values. New settings take effect only when a new session or service process starts, and a soft limit can never exceed its hard limit or the kernel ceiling.

What ulimit controls

Linux resource limits are attached to each process. The shell’s ulimit command displays or changes the limits inherited by programs that the shell starts. A child created with fork() inherits its parent’s limits, and those limits remain in place when the child replaces its program image with execve(). This is why the command used to launch a process matters more than a system-wide setting.

As an Amazon Associate I earn from qualifying purchases.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Inheritance also explains why a limit can appear correct in one process and wrong in another. If a shell starts a wrapper, and the wrapper starts the server, the server normally receives the wrapper’s limits. If a supervisor starts the server independently, it receives the supervisor’s launch context instead. A limit is therefore part of the process startup contract, not a property that the kernel automatically synchronizes across all processes owned by an account.

Soft and hard limits

  • Soft limit: the value the process currently enforces for a resource. A process can usually lower its soft limit, and an unprivileged process can raise it only up to its hard limit.
  • Hard limit: the upper bound for the soft limit. Raising a hard limit requires the appropriate privilege and must also fit within any kernel ceiling.

For open files, ulimit -n addresses RLIMIT_NOFILE. The limit is a per-process allowance, not a promise that the kernel has already opened that many files or that every process on the server receives the same value. A higher allowance does not allocate file descriptors in advance; it only permits the process to acquire more when its workload needs them.

Keep the distinction visible while troubleshooting. A configuration may raise the hard limit while leaving the soft limit lower, or a process may have inherited a lower hard limit before it reached the application. Always inspect both values in the context that launches the workload.

Measure the limit that actually applies

Measure before changing anything. Run these commands in the shell that will launch the workload:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
ulimit -a
ulimit -Sn   # soft open-file limit
ulimit -Hn   # hard open-file limit

The two open-file values tell you whether the requested change is possible in that shell. If the soft value is already at the hard value, a non-privileged shell cannot raise it further. Save the output before making a change so you can distinguish an effective increase from a merely edited configuration file.

Inspect a running daemon

A terminal’s value does not prove that a daemon has the same limit. For a running process, inspect the kernel’s view:

cat /proc/<pid>/limits

Read the Max open files row and compare it with the service manager’s configuration. This check is decisive when a service is started by systemd, a supervisor, a container entrypoint, or another account rather than from your terminal.

Use the process ID of the workload that is actually accepting connections or doing the constrained work. Looking at a short-lived launcher, a parent shell, or an old main PID can give a misleading result. After a restart, obtain the new PID again and repeat the check.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the launch layer

Use one layer for the workload instead of changing unrelated global settings. The following distinctions prevent the most common “my limit.conf change did nothing” failures.

Method Scope Persistence What must be restarted Privilege Inheritance
Shell ulimit Current shell and programs it launches Temporary Launch the program from the modified shell Soft limit can be raised only up to the existing hard limit Children inherit the shell’s limits across fork() and execve()
PAM limits files Login sessions Persistent configuration for future sessions Log out and start a new login session Root access is needed to edit the files; the PAM stack must load pam_limits.so Programs launched in that session inherit the session limits
systemd Limit* directives The service process and its descendants Persistent unit configuration Reload systemd and restart the service Root access is normally needed to install the drop-in and restart the unit Service children inherit the unit’s limits

The table’s scope is the practical decision rule. A shell command is ideal for an isolated experiment, PAM is appropriate when users start programs through login sessions, and a systemd directive is the authoritative setting for a systemd unit. Applying a correct setting at the wrong layer still produces no change in the target process.

Test a higher limit temporarily in a shell

A temporary change is the safest way to determine whether an application benefits from a larger limit before making it persistent.

  1. Check the current values and record them: ulimit -Sn and ulimit -Hn.
  2. Set a test soft limit no higher than the hard limit:
ulimit -n 65536
  1. Verify the result with ulimit -Sn. If the shell reports “operation not permitted,” inspect the hard limit and kernel ceiling before trying a larger number.
  2. Start the server from that same shell, or replace the shell with it:
exec ./your-server

The exec form ensures that the tested process occupies the shell’s process slot and receives its limits. Closing the shell, opening another terminal, or starting the program through a different supervisor does not carry this temporary setting over.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This test changes the shell and its descendants only. It does not rewrite the login-session defaults, the systemd unit, or processes that were already started. If the server forks workers after launch, those workers inherit the tested value from their parent.

Set limits for login sessions with PAM

/etc/security/limits.conf and files in /etc/security/limits.d/ are read by the PAM pam_limits module when a login session is created. These values are per-session; they are not global kernel settings and do not rewrite processes that are already running.

Create a focused limits file

Put an application-specific rule in a separate file so it can be audited and changed without editing the main file. For example, create /etc/security/limits.d/90-example.conf with:

appuser soft nofile 65536
appuser hard nofile 65536

Each line follows the format <domain> <type> <item> <value>:

  • domain identifies the account or other login domain to which the rule applies.
  • type is soft or hard.
  • item names the resource, such as nofile.
  • value is the numeric limit.

Use the narrowest account or group scope that meets the requirement. Giving every login the same high limit makes capacity and compatibility problems harder to see. Set both soft and hard values deliberately: setting only a hard value can leave applications running at a lower soft value until they raise it themselves.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Confirm PAM is using the module

The relevant login stack must include pam_limits.so. Check the PAM configuration used by the login method, for example:

grep -R "pam_limits.so" /etc/pam.d

Different login paths can use different PAM stacks, so verify the one that creates the session in question. A rule in limits.d cannot affect a service that never enters that PAM login path.

Start a new session before verifying

Log out and log back in as the affected account, then run:

ulimit -Sn
ulimit -Hn

An existing terminal retains the limits with which it was created. Restarting a shell inside that same session does not make PAM recalculate the session’s limits; create a genuinely new login session. If a graphical login, SSH login, or another route is involved, verify that route specifically rather than assuming all sessions use identical PAM configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set limits for a systemd service

A daemon launched by systemd does not inherit the limits shown by your terminal. Configure the unit itself, preferably with a drop-in so package updates do not overwrite the change.

Create the drop-in

Open the service’s drop-in editor:

sudo systemctl edit your-service.service

Add the resource-specific directive under [Service]:

[Service]
LimitNOFILE=65536

LimitNOFILE= corresponds to the open-file limit exposed by ulimit -n. Other resources use their own directives, including LimitNPROC= for process count, LimitSTACK= for stack size, LimitCORE= for core dumps, and LimitMEMLOCK= for locked memory.

Put the directive in the service section, not in a shell profile. A profile affects an interactive login; the unit drop-in travels with the service definition and is applied whenever systemd creates a new service process.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Apply and verify the unit setting

  1. Reload unit configuration:
sudo systemctl daemon-reload
  1. Restart the service so a new process receives the limit:
sudo systemctl restart your-service.service
  1. Find the service’s main process and inspect its effective limit:
pid=$(systemctl show -p MainPID --value your-service.service)
cat /proc/$pid/limits | grep -i 'open files'

Always verify the process after the restart. A syntactically valid drop-in can still target the wrong unit, be superseded by another configuration layer, or be irrelevant if the workload forks a separate process under a different manager. If the service has restarted again, repeat the PID lookup before drawing a conclusion.

Why “operation not permitted” appears

When a command such as ulimit -n 1000000 fails, check both limits and the kernel ceiling:

ulimit -Hn
cat /proc/sys/fs/nr_open
  • If the requested soft value is above the shell’s hard value, an unprivileged process cannot raise it.
  • If the requested value is above /proc/sys/fs/nr_open, it exceeds the kernel’s maximum for RLIMIT_NOFILE, even when the caller has privilege.
  • If both checks allow the value, make sure the process is being launched through the layer you changed. A PAM rule does not alter a systemd service, and a shell change does not alter an already-running daemon.

Changing the hard limit also requires privilege at the point where the process is launched. Do not treat a larger number in a configuration file as proof that the daemon received it; confirm the value in /proc/<pid>/limits. The kernel ceiling is separate from the service’s configured value, so a unit can be configured with a number that still cannot be granted if it exceeds fs.nr_open.

High nofile values and select(2) compatibility

Raising the soft open-file limit above 1024 can expose an application compatibility problem. On Linux, select(2) cannot operate on descriptors above 1023. A service that still uses select() may fail or behave incorrectly when it receives file descriptors in that range, even though the higher resource limit itself was accepted.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Before adopting a high value, confirm that the application and its libraries use descriptor APIs that support the expected range. This warning is about descriptor numbers, not only the count of simultaneously open files: an application can encounter a descriptor above 1023 once the process has opened and closed enough files. Consequently, a low descriptor count at the instant you inspect it does not by itself prove that a high soft limit is safe for code based on select().

Systemd documentation describes 524288 as a modern historical default hard nofile value in its documentation, but that figure is not a universal recommendation for every distribution or workload. Treat it as documentation context, not a target. Test the application at the proposed value and watch for descriptor-related errors before making the change permanent.

Tune other resources with the same method

The workflow is the same for process counts, stack size, core dumps, and locked memory:

  1. Measure the effective soft and hard values in the actual launch context.
  2. Identify the resource-specific name, such as nproc, stack, core, or memlock.
  3. Change the shell, PAM rule, or systemd directive that launches the workload.
  4. Start a new session or restart the service.
  5. Inspect the resulting process rather than relying on the configuration file alone.

For example, a systemd service can use LimitNPROC= when process creation is constrained, while a login-session rule would use the corresponding resource item in the limits-file syntax. Raise only the resource that is demonstrably constraining the workload. Increasing unrelated limits expands the failure surface without fixing the observed bottleneck.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to choose a value without guessing

There is no universal “correct” server value for nofile or nproc. Size a limit from the workload’s observed behavior:

  • Measure the descriptors and processes used during normal and peak concurrency.
  • Allow headroom for connection bursts, log rotation, sockets, pipes, and other descriptors the application opens in addition to its primary data files.
  • Compare the proposed value with the application’s descriptor APIs, especially if it may use select().
  • Keep the hard limit high enough for the intended soft value, but avoid setting every resource to unlimited; that can hide a capacity leak or remove a useful failure boundary.
  • Document which account, unit, and launch path owns the setting so a later operator does not test the wrong process.

Use a staged change: record the baseline, apply a temporary value where possible, exercise normal and peak behavior, then persist the smallest value that covers the measured need. Recheck after deployment because wrappers, service managers, and worker processes can each create a different launch context.

A limit should prevent avoidable exhaustion without masking an application that leaks descriptors or creates unbounded processes. Monitoring and application-level limits remain necessary after the kernel limit is raised. A larger ceiling is not a substitute for finding why descriptors or processes continue to grow.

Operational checklist

  1. Identify the exact process and the component that launches it.
  2. Read its effective limits from /proc/<pid>/limits, and record the shell’s soft and hard values when testing interactively.
  3. Choose only the matching layer: shell, PAM, or systemd.
  4. Check the hard limit and /proc/sys/fs/nr_open before requesting a larger nofile value.
  5. Apply the change, create a new login session or restart the service, and obtain the new process ID.
  6. Verify the effective value and exercise the workload, including descriptor-heavy and peak-concurrency paths.
  7. Document the account, unit, value, and compatibility decision, especially whether the application can safely handle descriptors above 1023.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common failure modes and fixes

“I edited limits.conf, but ulimit -n is unchanged.”

The terminal may predate the edit, the login stack may not load pam_limits.so, or the process may not be a PAM login at all. Create a new login session, verify the PAM module, and inspect the actual daemon if a service manager launches it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“My terminal shows 65536, but the daemon still shows a small value.”

The daemon was launched by systemd or another supervisor. Set the unit’s LimitNOFILE=, reload systemd, restart the service, and read /proc/$pid/limits for the new process.

“The service did not change after I edited the unit.”

Editing a drop-in does not alter an existing process. Run systemctl daemon-reload followed by systemctl restart, then verify the new main PID’s limits.

“The shell refuses a value below the kernel ceiling.”

Compare the requested value with ulimit -Hn. If the hard limit is lower, the shell lacks permission to raise it. If the hard limit is high but the request exceeds /proc/sys/fs/nr_open, the kernel ceiling is the blocker.

“The application breaks after increasing nofile.”

Check whether it relies on select(2). Descriptors above 1023 are outside Linux select()‘s supported range. Roll back the high soft limit for that application or move it to compatible descriptor APIs before raising the limit again.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently asked questions

How do I increase ulimit just for one test?

In the shell that will launch the program, run ulimit -n 65536, verify with ulimit -Sn, and start the program from that same shell. The setting ends with the shell and does not affect other terminals or services.

Why does limits.conf not work for my service?

PAM limits apply to login sessions. A systemd service normally needs a unit drop-in with LimitNOFILE= or the relevant Limit* directive. Restart the service and inspect its process rather than checking an unrelated login shell.

Best Value
Sale
UNIX and Linux System Administration Handbook, 4th Edition
  • New
  • Mint Condition
  • Dispatch same day for order received before 12 noon
  • Guaranteed packaging
  • No quibbles returns

How do I set the open-file limit for a systemd service?

Run sudo systemctl edit your-service.service, add LimitNOFILE=65536 under [Service], run sudo systemctl daemon-reload, and restart the service. Confirm the new value in /proc/<pid>/limits.

Why does ulimit -n say “operation not permitted”?

The requested soft value may exceed the current hard limit, or it may exceed /proc/sys/fs/nr_open. An unprivileged process cannot raise its hard limit. Check both values and ensure the change is made in the launch layer that controls the target process.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does changing a limit update already-running processes?

No. Limits are inherited when a process is created. Log out and back in for PAM changes, or reload and restart a systemd service. Existing shells and daemons retain their original values.

Is 65536, or 524288, the correct value for every server?

No. Those are examples and documentation figures, not universal recommendations. Measure descriptor and process usage, add workload headroom, check application compatibility, and choose the smallest value that covers normal and peak behavior.

Can I set every resource to unlimited?

You can remove useful capacity boundaries by doing so, and you may conceal descriptor leaks or unbounded process creation. Raise only the constrained resource and keep an intentional hard limit.

What should I check after a successful change?

Verify the effective soft and hard values on the actual process, confirm the process is the new post-restart PID, and exercise the workload at realistic concurrency. For high nofile values, specifically confirm that the application does not depend on Linux select() with descriptors above 1023.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reference manuals

The process-inheritance rules are documented in the Linux man-pages getrlimit(2) manual. Login-session syntax and scope are documented in Linux-PAM’s limits.conf(5). Service-level resource directives and the select(2) warning are documented in systemd’s systemd.exec(5). Consult the versions installed for your distribution when directive names or defaults differ.

Frequently Asked Questions

How do I increase ulimit for a one-time test?

Set the soft value in the launching shell, verify it, and start the application from that same shell. The change is temporary and affects only that shell and its children.

Why did editing limits.conf not change my daemon?

PAM limits apply to newly created login sessions. A daemon started by systemd needs a unit-level LimitNOFILE= or another appropriate Limit* directive, followed by daemon-reload and a service restart.

How can I verify the limit a service really received?

Find the service’s current PID and read /proc//limits. Check the Max open files row instead of relying on an interactive terminal’s ulimit output.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What causes ulimit -n to return operation not permitted?

The requested value may exceed the process’s hard limit or the kernel’s /proc/sys/fs/nr_open ceiling. Raising a hard limit also requires the appropriate privilege.

Why can a high nofile value break an application?

Linux select(2) cannot operate on descriptors above 1023. Applications that still use select() must be tested or moved to compatible descriptor APIs before adopting a soft limit above 1024.

The Bottom Line

Tune ulimit at the process launch layer: shell for a temporary experiment, PAM for future login sessions, and systemd Limit* directives for managed services. Check both soft and hard values, respect fs.nr_open, restart the session or service, and verify /proc/<pid>/limits. Choose a workload-sized value and confirm that high descriptor numbers are compatible with the application.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.