Blocking direct web access to sensitive files reduces the blast radius of common deployment mistakes, such as leaving .env files, backup copies, database dumps, or private keys inside the web root. Even a single leaked credential file can turn a routine misconfiguration into a full compromise.
The Apache HTTP Server maps request URLs to filesystem paths under a virtual host’s DocumentRoot, then applies authorization rules before serving content. Apache 2.4 access control uses the Require directive, and regex containers like FilesMatch and LocationMatch can deny entire classes of risky resources across all sites.
Deny rules are defense-in-depth, not a substitute for correct filesystem ownership and permissions, and overly broad patterns can block legitimate downloads. Test syntax before reloads to avoid outages, and keep special paths (such as ACME challenges under /.well-known/) in mind when expanding deny lists.
Related: How to test your Apache configuration
Related: How to enable or disable Apache modules
Steps to deny access to sensitive files in Apache:
- Create /etc/apache2/conf-available/deny-sensitive-files.conf with deny rules covering dotfiles, version-control metadata, backups, dumps, and key material.
# /etc/apache2/conf-available/deny-sensitive-files.conf # Deny hidden files (dotfiles) like .env, .gitignore, and editor config files. <FilesMatch "^\."> Require all denied </FilesMatch> # Deny common backup, dump, and key formats when they exist under the web root. <FilesMatch "(?i)(\.(bak|old|orig|swp|sql|sqlite|db|pem|key|p12|pfx|kdbx)$|~$)"> Require all denied </FilesMatch> # Deny version-control directories (.git, .svn, .hg, .bzr) anywhere in the URL path. <LocationMatch "(?i)(^|/)\.(git|svn|hg|bzr)(/|$)"> Require all denied </LocationMatch>Keep the extension-based FilesMatch list as small as practical on sites that intentionally serve downloads, since matching extensions are blocked regardless of intent.
RHEL-style systems commonly place the same rules in /etc/httpd/conf.d/deny-sensitive-files.conf and reload the httpd service.
- Enable the conf with a2enconf.
$ sudo a2enconf deny-sensitive-files Enabling conf deny-sensitive-files. To activate the new configuration, you need to run: systemctl reload apache2
- Validate the Apache configuration syntax.
$ sudo apache2ctl -t Syntax OK
- Reload apache2 to apply the new rules.
$ sudo systemctl reload apache2
- Confirm the apache2 unit is active after the reload.
$ sudo systemctl status apache2 ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2025-12-13 20:12:44 UTC; 12s ago ##### snipped ##### - Request a dotfile path to confirm access is denied.
$ curl -I http://localhost/.env HTTP/1.1 403 Forbidden Date: Sat, 13 Dec 2025 20:13:01 GMT Server: Apache Content-Type: text/html; charset=iso-8859-1 ##### snipped #####
For name-based virtual hosts, test locally with curl -I -H 'Host: example.com' http://127.0.0.1/.env to hit the intended site.
- Request a version-control metadata path to confirm access is denied.
$ curl -I http://localhost/.git/config HTTP/1.1 403 Forbidden Date: Sat, 13 Dec 2025 20:13:10 GMT Server: Apache Content-Type: text/html; charset=iso-8859-1 ##### snipped #####
- Review recent denied requests in the access log.
$ sudo tail -n 5 /var/log/apache2/access.log 127.0.0.1 - - [13/Dec/2025:20:13:01 +0000] "HEAD /.env HTTP/1.1" 403 195 "-" "curl/8.0.1" 127.0.0.1 - - [13/Dec/2025:20:13:10 +0000] "HEAD /.git/config HTTP/1.1" 403 196 "-" "curl/8.0.1" ##### snipped #####
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
