DirectAdmin Apache 100% CPU Usage: How to Find the Cause and Fix It Fast

Priya

Content Writer & Researcher

Last Updated: 22 September 2026
DirectAdmin Apache 100% CPU Usage: How to Find the Cause and Fix It Fast
🖥️

Is Apache Still Overloading Your Server?

Our server engineers respond within 15 minutes to CPU crises on DirectAdmin servers. We diagnose the root cause, tune your Apache MPM settings, block attack traffic, and set up proactive monitoring — so your sites stay online even under traffic spikes.

🖥️12,400+PCs Fixed
⭐4.9★Google Rating
⚡<15 minAvg. Response
🛡️ISO 27001Certified

If you manage a VPS or dedicated server running DirectAdmin and Apache is suddenly pinning your CPU at 100%, websites are timing out and your load average has gone through the roof — you need a fast, reproducible diagnosis. This guide is a step-by-step runbook for the directadmin apache high cpu usage fix that takes you from zero to root-cause in under 10 minutes, using exact DirectAdmin file paths and real commands.

Whether the culprit is a brute-force attack on xmlrpc.php, a misconfigured MPM spawning hundreds of httpd workers, or a single runaway PHP script, the process below will surface it — and give you the tools to stop it.

What Causes Apache CPU to Spike on DirectAdmin Servers

Before reaching for a fix, it helps to know what you are actually fighting. The most common root causes on DirectAdmin servers are:

  • Too many simultaneous httpd workers — MaxRequestWorkers (or the legacy MaxClients) is set higher than your RAM can support, causing the kernel to swap and thrash.
  • HTTP flood or DDoS attack — bots hammering WordPress xmlrpc.php, wp-login.php, or other entry points generate thousands of short-lived Apache children.
  • Slow back-end (PHP/MySQL) — if PHP-FPM or MySQL is slow, Apache workers block waiting for a response, filling the process table and driving load sky-high.
  • KeepAlive set too aggressively — long KeepAliveTimeout values tie up workers for clients that have already disconnected.
  • ModSecurity rule exhaustion — complex WAF rule sets run per-request regex matching which is extremely CPU-intensive under high traffic.
  • Runaway PHP or CGI script — a single site with an infinite loop or memory leak can consume an entire CPU core.

💡 None of these worked? Skip the guesswork.

Get Expert Help →

Step 1 — Immediately Identify the Offending Process or Site

1Check overall load and top CPU consumers

The moment you suspect a problem, run:

uptime
top -b -n 1 -o %CPU | head -30

If httpd (or apache2) processes fill the top of the list, you are dealing with an Apache overload. Note the PIDs of the highest consumers.

2Count how many httpd children are alive
ps aux | grep httpd | grep -v grep | wc -l

On a 2 GB VPS with Prefork MPM the safe ceiling is roughly 20–30 workers. Anything above 80–100 indicates runaway spawning.

3Identify which site a specific PID is serving
lsof -p <PID> | grep -E 'vhost|public_html'

Replace <PID> with the offending process ID. The output will show the open file handles pointing to a specific user's public_html directory — that is your problem site.

4Confirm with strace (last resort)
strace -p <PID> -e trace=read,write -s 512 2>&1 | head -40

This reveals what system calls the process is actually executing, useful for catching an infinite PHP loop or a blocking socket.

1Enable mod_status temporarily

Add the following block to /etc/httpd/conf/extra/httpd-info.conf (create it if it does not exist) and include it from the main config:

<IfModule mod_status.c>
  ExtendedStatus On
  <Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1
  </Location>
</IfModule>

Then add to /etc/httpd/conf/httpd.conf:

Include conf/extra/httpd-info.conf

Reload Apache:

service httpd reload

Access the status page from the server itself:

curl -s http://127.0.0.1/server-status?auto | head -50

Look at the Request column — you will instantly see if every worker is serving requests from the same IP, or all hitting the same URL (a clear sign of a flood attack or bot storm).

2Scan Apache access logs for the top attackers

DirectAdmin stores per-user access logs at:

/var/log/httpd/domains/<domain.com>.log

The global combined log is at:

/var/log/httpd/access_log

To find the top 20 requesting IPs in the last 5,000 lines:

tail -5000 /var/log/httpd/access_log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

To find the top 20 requested URLs:

tail -5000 /var/log/httpd/access_log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20

If /xmlrpc.php, /wp-login.php, or /?author= scans appear thousands of times, you have a WordPress attack — jump to Step 5.

1Calculate a safe MaxRequestWorkers value

Rule of thumb: MaxRequestWorkers = (Total RAM in MB − 256 MB for OS) ÷ Average httpd process size in MB

Check average httpd process RAM:

ps aux | grep httpd | grep -v grep | awk '{sum+=$6; count++} END {print sum/count/1024 " MB average"}'

A 4 GB server with 30 MB average workers can safely run about 125 workers: (4096−256) ÷ 30 ≈ 128. Set it slightly below that.

2Example safe Prefork block
<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxRequestWorkers   100
    MaxConnectionsPerChild 300
</IfModule>

Lower MaxConnectionsPerChild (formerly MaxRequestsPerChild) forces workers to recycle after 300 requests, preventing PHP memory leaks from accumulating indefinitely.

3Tighten KeepAlive settings

In /etc/httpd/conf/httpd.conf:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 3

Reducing KeepAliveTimeout from the default 15 seconds to 3 seconds frees workers much faster between requests.

4Reload and verify
apachectl configtest && service httpd reload
1Enable Nginx + Apache in CustomBuild 2.0
cd /usr/local/directadmin/custombuild
./build set webserver nginx_apache
./build nginx
./build apache
./build rewrite_confs
2Verify the stack is running
service nginx status
service httpd status

Nginx listens on port 80/443. Apache moves to port 8080 (internal only). Your users see no change — Nginx proxies PHP requests to Apache on 8080 and serves everything else itself.

3Check the Nginx config path

The Nginx virtual host config per user is at:

/etc/nginx/conf.d/virtual/<domain.com>.conf

The Apache virtual host template (now internal) stays at:

/usr/local/directadmin/data/users/<username>/httpd.conf
4Performance tip: enable Nginx static file caching

Add to /etc/nginx/nginx.conf inside the http {} block:

open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
1Emergency IP block with iptables
# Drop a single attacking IP
iptables -I INPUT -s 203.0.113.45 -j DROP

# Drop a /24 subnet
iptables -I INPUT -s 203.0.113.0/24 -j DROP

# Save rules
service iptables save
2Block xmlrpc.php at the Apache level (fastest mitigation)

Add to the WordPress site's per-user httpd.conf at /usr/local/directadmin/data/users/<username>/httpd.conf inside the <VirtualHost> block, or create a site-specific include:

<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
</Files>

Alternatively, block it in .htaccess inside public_html:

# Block xmlrpc.php
<Files xmlrpc.php>
    Require all denied
</Files>

# Block wp-login.php brute force — only allow your IP
<Files wp-login.php>
    Require ip 192.0.2.1
</Files>
3Rate-limit with mod_ratelimit or fail2ban

Install and enable fail2ban with the Apache-specific jails:

yum install fail2ban -y   # AlmaLinux / CentOS
# or
apt install fail2ban -y   # Ubuntu / Debian

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

In /etc/fail2ban/jail.local enable:

[apache-auth]
enabled = true
maxretry = 5
bantime = 3600

[apache-noscript]
enabled = true

[apache-overflows]
enabled = true
systemctl enable fail2ban
systemctl restart fail2ban
fail2ban-client status
4If ModSecurity is causing the CPU spike itself

ModSecurity config on DirectAdmin lives at:

/etc/httpd/conf/extra/httpd-modsecurity.conf

To temporarily verify ModSecurity is the culprit, switch it to detection-only mode:

SecRuleEngine DetectionOnly

If CPU immediately drops, your rule set is too broad for your traffic volume. Consider switching to OWASP CRS in Paranoia Level 1 or disabling rule IDs that match your legitimate traffic.

If your server is under persistent attack or you want proactive protection, our team provides managed server support including 24/7 monitoring, emergency response, and Apache hardening — so you are never fighting a CPU crisis alone.

FAQs

Get the Free Linux Server Admin Cheatsheet (PDF)

Essential commands for server management, networking, and troubleshooting — all on one printable page.

Running Linux servers? Let us manage them for you.

Our Managed Linux Server plans cover updates, security hardening, monitoring, and 24/7 incident response — so your servers stay up and your team stays focused.

  • Proactive OS patching and security updates
  • 24×7 monitoring with instant alerting
  • Backup configuration and disaster recovery
  • Dedicated Linux engineers on call
See Pricing Plans →

What our customers say

“Our production server went down at 2 AM. CloudHouse had it back online in under 20 minutes. Incredible response time.”

Arun S.

CTO, SaaS Startup

“They migrated our entire infrastructure from Ubuntu 18 to 22 with zero downtime. Couldn't have asked for better.”

Deepak N.

DevOps Lead

Frequently Asked Questions

Run `lsof -p <PID>` on the high-CPU httpd process ID — the open file handles will point to a specific user's public_html directory, identifying the offending site. You can also enable mod_status and curl http://127.0.0.1/server-status to see every active request in real time.

Need this done for you?

Server Management Service

Managed Linux and Windows servers: monitoring, patching, security and 24/7 support.

Learn more

Book your free 15-minute diagnosis

A certified technician will call you back within 15 minutes during business hours.

Share this article

Leave a Comment

Comments (0)

Loading comments...