Blocking web access to a non-public directory in Apache keeps backup exports, private uploads, maintenance tools, and other internal content from being downloaded directly from the site. One exposed folder under the web root can leak source code, data, or admin-only assets that were never meant to be public.
Apache evaluates authorization after it maps the request to a resource and merges the matching configuration sections. For a real filesystem path, <Directory> is the correct container, and on Apache 2.4 the supported deny rule is Require all denied; URL-only rules belong in <Location> instead.
This guide uses the Ubuntu and Debian layout with /etc/apache2/conf-available/, a2enconf, apache2ctl, and the apache2 systemd unit. Test the configuration before reloading, and verify the blocked URL returns HTTP 403 instead of 404, which usually means the request is not reaching the directory you intended to protect.
$ sudo grep -RIn "DocumentRoot" /etc/apache2/sites-enabled/ /etc/apache2/sites-enabled/000-default.conf:12: DocumentRoot /var/www/html
$ sudoedit /etc/apache2/conf-available/deny-private-directory.conf
Keeping the rule in /etc/apache2/conf-available/ makes it easy to enable, disable, or reuse without editing the main site file directly.
If the directory should be blocked only inside one virtual host, place the same <Directory> block inside that site's virtual host config instead.
# /etc/apache2/conf-available/deny-private-directory.conf
<Directory "/var/www/html/private">
Require all denied
</Directory>
Do not point the rule at a parent path such as /var/www/html/ unless you intend to block the entire site tree below it.
<Directory> matches filesystem paths. Use <Location> only when you need to protect a URL path that does not map cleanly to one directory on disk.
Allow, Deny, and Order are legacy compatibility directives on Apache 2.4; prefer Require all denied for new rules.
$ sudo a2enconf deny-private-directory Enabling conf deny-private-directory. To activate the new configuration, you need to run: systemctl reload apache2
On RHEL-style systems, the equivalent rule is usually stored under /etc/httpd/conf.d/ and applied with the httpd service.
$ sudo apache2ctl configtest Syntax OK
Related: How to test Apache configuration
$ sudo systemctl reload apache2
$ curl -i http://127.0.0.1/private/ HTTP/1.1 403 Forbidden Date: Wed, 08 Apr 2026 04:36:51 GMT Server: Apache/2.4.58 (Ubuntu) Content-Length: 274 Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access this resource.</p> <hr> <address>Apache/2.4.58 (Ubuntu) Server at 127.0.0.1 Port 80</address> </body></html>
Use a Host header such as curl -i -H 'Host: host.example.net' http://127.0.0.1/private/ when testing a name-based virtual host locally.
A 404 response usually means the URL does not resolve to the directory you meant to protect.
$ sudo tail -n 10 /var/log/apache2/error.log [Wed Apr 08 04:36:51.979810 2026] [authz_core:error] [pid 3433:tid 281473540399392] [client 127.0.0.1:42150] AH01630: client denied by server configuration: /var/www/html/private/