Hardening Apache httpd
Apache’s defaults are better than its reputation. The shipped configuration denies everything at the filesystem root and grants access back per directory, which is the right way round — and it is the reason the 2021 path traversal only worked on servers where someone had removed it.
So this cluster is mostly not about adding protections. It’s about the ones that came with the config and got taken out, and about the modules that are loaded because they always have been.
8 controls
- Severity: critical
- Severity: high
- Severity: high
- Severity: high
- Severity: high
- Severity: medium
- Severity: medium
- Severity: medium
Check your version before anything else
Section titled “Check your version before anything else”apachectl -v2.4.68 is current, released 8 June 2026. It fixes 13 CVEs affecting every version from 2.4.0 through 2.4.67 — use-after-free, XSS, heap overflow, DoS, privilege escalation and out-of-bounds reads across several modules.
Two from that stretch are worth naming, because they change what else on this list matters:
- CVE-2026-23918 — a double-free in
mod_http2allowing remote code execution (CVSS 8.8). It affects only 2.4.66, fixed in 2.4.67. If you are on 2.4.66 specifically, stop reading and upgrade. - CVE-2026-24072 — privilege escalation in
mod_rewrite: a user with write access to a.htaccessfile can craft an expression that makes httpd read files outside their own directory, using httpd’s own privileges. On shared hosting that is one tenant reading another’s files, and it is why.htaccesshas a page.
Nothing below helps if you’re running a version with a remotely reachable double-free. Patch first.
Where the config lives
Section titled “Where the config lives”Apache’s layout differs sharply by distribution:
| Debian / Ubuntu | RHEL / Rocky / Alma | |
|---|---|---|
| Main | /etc/apache2/apache2.conf |
/etc/httpd/conf/httpd.conf |
| Sites | sites-enabled/*.conf |
conf.d/*.conf |
| Modules | mods-enabled/*.load + a2enmod |
conf.modules.d/*.conf |
| Binary | apache2ctl |
apachectl |
Don’t read one file and conclude anything. Ask the server what it assembled:
apachectl -t -D DUMP_INCLUDES # every file included, in orderapachectl -S # the vhost map as parsedapachectl -M # every loaded moduleapachectl -S is the one people skip and shouldn’t: it shows which vhost actually
answers for which name, which is frequently not what the file layout implies.
Reloading
Section titled “Reloading”sudo apachectl -t && sudo systemctl reload apache2Always -t first. A graceful reload with a broken config leaves the running
server alone and reports the error. A restart with a broken config leaves you with
no web server. There is no reason to ever restart what you can reload.