What happened
You're running a script, starting a service, or SSH-ing into a server โ and suddenly everything seizes up with this:
bash: fork: retry: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
New processes can't start. SSH connections time out. Cron jobs silently fail. RAM is fine, CPU is idle, the server is clearly up โ but nothing will fork. You've hit the max user processes (nproc) limit.
Linux tracks how many processes each user owns at any given moment. Hit that ceiling and fork() returns EAGAIN โ which is exactly what you're seeing.
Diagnose first
Check the current limits
# See limits for your current shell session
ulimit -a
# Specifically max user processes
ulimit -u
On older systems, the default is painfully low:
max user processes (-u) 1024
Modern systemd distros tend to default higher (63503 on Ubuntu 22.04, for example), but services running under their own dedicated users often inherit a much lower PAM limit โ sometimes still 1024.
Count how many processes the affected user is running
# Replace 'www-data' with the actual user
ps -u www-data --no-header | wc -l
# Or see all users sorted by process count
ps aux | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
If that number is at or near the ulimit value, you've confirmed the problem.
Check the PAM-configured limit (the real ceiling)
grep -r nproc /etc/security/limits.conf /etc/security/limits.d/
You might see something like:
* soft nproc 1024
* hard nproc 4096
The soft limit is what processes start with. The hard limit is the maximum a process can raise itself to. Both being low is your culprit.
Check what systemd enforces (for services)
Here's a gotcha: if the affected process is a systemd service, /etc/security/limits.conf often doesn't apply at all โ systemd manages its own limits separately.
# Check the effective limits of a running service (e.g. nginx)
systemctl show nginx | grep -i task
# Or check /proc for a specific PID
cat /proc/$(pgrep -o nginx)/limits | grep processes
Fix it
Option 1: Raise the limit for the current session (temporary)
Good for quick testing or one-off scripts. It resets the moment the shell closes.
# Raise soft limit to 8192
ulimit -u 8192
# Verify
ulimit -u
You can only raise up to the hard limit. Raising the hard limit requires root.
Option 2: Set permanent limits via PAM (for login users and daemons)
Add a new file under /etc/security/limits.d/ โ it's cleaner than editing limits.conf directly:
sudo nano /etc/security/limits.d/99-nproc.conf
Add these lines (adjust values to your actual workload):
# Raise nproc for all users
* soft nproc 65536
* hard nproc 65536
# Or target a specific user
www-data soft nproc 32768
www-data hard nproc 32768
# root is often excluded from the * wildcard โ set explicitly if needed
root soft nproc unlimited
root hard nproc unlimited
Important: PAM limits only apply to new login sessions. Existing processes keep their old limits. Restart the service or log out and back in to pick up the change.
Option 3: Fix limits for systemd services
PAM limits don't reach services started by systemd. Override per-service with a drop-in file:
sudo systemctl edit nginx
Add:
[Service]
TasksMax=infinity
LimitNPROC=65536
Then reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart nginx
To raise the global default for all systemd services, edit /etc/systemd/system.conf:
sudo nano /etc/systemd/system.conf
[Manager]
DefaultTasksMax=infinity
sudo systemctl daemon-reload
Option 4: Check for a process leak (fix the root cause)
Raising the limit treats the symptom. If a zombie process or a runaway spawning loop is the real problem, no limit will save you for long.
# List zombie processes
ps aux | awk '$8 == "Z"'
# Watch if a specific user's count keeps climbing
watch -n 2 "ps -u myuser --no-header | wc -l"
# Find the parent spawning too many children
ps -eo pid,ppid,user,comm | awk '{print $2}' | sort | uniq -c | sort -rn | head -5
Count climbing continuously and never dropping? That's a leak. Fix the application.
Verify the fix worked
# After applying limits.conf changes, open a new session and check:
ulimit -u
# For a systemd service, confirm the new limit is live:
cat /proc/$(pgrep -o nginx)/limits | grep processes
# Stress test โ spawn 100 background processes:
for i in $(seq 1 100); do sleep 1 & done
# Should complete without 'Resource temporarily unavailable'
jobs | wc -l
kill $(jobs -p)
Quick reference: common defaults by distro
- CentOS 6 / RHEL 6: default nproc = 1024 for non-root users โ Java apps and Ruby on Rails deployments blow past this constantly
- CentOS 7 / RHEL 7+: ships
/etc/security/limits.d/20-nproc.confwith 4096 โ check and override this specific file, notlimits.conf - Ubuntu 20.04+: systemd-managed, TasksMax defaults to 15% of the system max (roughly 4915 on a typical VPS) โ services with high concurrency still hit it
- Docker containers: inherit the host's ulimits by default; pass
--ulimit nproc=65535:65535when running containers with many concurrent processes
Real-world culprit: CI runners
The most common place I've seen this: a Jenkins or GitLab Runner instance running 20 parallel builds, where each job forks a shell, a compiler, and a test suite. That's 60+ processes per job โ multiplied by 20 jobs, you blow past 1024 in seconds.
For any user that runs services, set nproc to at least 65536. There's no cost โ it's just a kernel accounting limit, not a memory reservation.
One more thing: on systems where PAM is configured but systemd manages your services, fixing limits.conf alone won't help. You need both.

