Skip to content

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

Terminal window
apachectl -v

2.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_http2 allowing 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 .htaccess file 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 .htaccess has a page.

Nothing below helps if you’re running a version with a remotely reachable double-free. Patch first.

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:

Terminal window
apachectl -t -D DUMP_INCLUDES # every file included, in order
apachectl -S # the vhost map as parsed
apachectl -M # every loaded module

apachectl -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.

Terminal window
sudo apachectl -t && sudo systemctl reload apache2

Always -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.