Restricting a URL or directory to specific client addresses in Apache reduces exposure for admin panels, staging sites, internal APIs, and other resources that should not answer the public internet. An IP allowlist is simple, immediate, and often enough to stop routine scans or accidental access from untrusted networks.
On Apache 2.4, host-based access control is handled by Require rules from mod_authz_host. The Require ip provider accepts individual IPv4 or IPv6 addresses plus network ranges, and it is typically placed inside a <Location> block for a URL path or a <Directory> block for a filesystem path. Older Allow, Deny, and Order directives are compatibility syntax and are no longer the preferred way to build new rules.
This example uses a dedicated conf snippet in /etc/apache2/conf-available with a2enconf, apache2ctl configtest, and a systemd reload on Ubuntu or Debian. If Apache sits behind a reverse proxy or load balancer, restore the real client address with a trusted mod_remoteip configuration before relying on Require ip, otherwise the rule matches the proxy address instead of the original client. Keep console or other out-of-band access available until the allowlist is confirmed, because one wrong CIDR can lock out the protected path immediately.
Related: How to secure Apache web server
Related: How to disable access to a directory in Apache
Related: How to log X-Forwarded-For IP in Apache
Steps to restrict access by IP in Apache:
- Identify whether the rule should match a URL path or a filesystem directory.
Use <Location> for URL paths such as /admin/ and <Directory> for filesystem paths such as /var/www/html/admin.
- Create a dedicated Apache conf snippet for the restriction.
$ sudoedit /etc/apache2/conf-available/restrict-admin-by-ip.conf
Keeping the rule in a separate snippet makes it easier to enable, disable, and audit without editing the whole virtual host file.
Related: Location for Apache configuration
- Add a Require ip rule for the protected path.
# /etc/apache2/conf-available/restrict-admin-by-ip.conf <Location "/admin/"> Require ip 203.0.113.10 198.51.100.0/24 </Location>Replace the example address and CIDR with the real client IPs or networks that should be allowed.
For a real directory on disk, use <Directory "/var/www/html/admin"> with the same Require ip line instead.
Multiple Require lines in the same block are treated as an implicit <RequireAny>. Use <RequireAll> when a request must satisfy both Require ip and another condition such as Require valid-user.
Do not mix legacy Allow or Deny rules with new Require rules in the same protected context unless you are intentionally dealing with compatibility behavior.
- Enable the new conf snippet.
$ sudo a2enconf restrict-admin-by-ip Enabling conf restrict-admin-by-ip. To activate the new configuration, you need to run: systemctl reload apache2
On RHEL-family systems, place the same rule in a file under /etc/httpd/conf.d/ and reload the httpd service instead of using a2enconf.
- Test the Apache configuration syntax.
$ sudo apache2ctl configtest Syntax OK
Use sudo apachectl -t or sudo httpd -t on platforms that do not ship apache2ctl.
Related: How to test Apache configuration
- Reload Apache so the new authorization rule becomes active.
$ sudo systemctl reload apache2
The new allowlist applies immediately after the reload, so a wrong address or mask can block legitimate access at once.
- Request the protected URL from a client address that is inside the allowlist.
$ curl -I http://admin.example.net/admin/ HTTP/1.1 200 OK Date: Thu, 09 Apr 2026 04:51:47 GMT Server: Apache/2.4.58 (Ubuntu) Last-Modified: Thu, 09 Apr 2026 04:51:46 GMT ETag: "9-64effc60a2b96" Accept-Ranges: bytes Content-Length: 9 Content-Type: text/html
Any non-403 result such as 200, 302, or 401 means the request reached the protected resource.
When testing a name-based virtual host locally, use a matching Host header instead of the public hostname.
- Request the same URL from a client address that is outside the allowlist.
$ curl -I http://admin.example.net/admin/ HTTP/1.1 403 Forbidden Date: Thu, 09 Apr 2026 04:51:47 GMT Server: Apache/2.4.58 (Ubuntu) Content-Type: text/html; charset=iso-8859-1
HTTP 403 Forbidden confirms that Apache denied the request during authorization.
- Inspect the Apache error log if the result does not match the expected source address.
$ sudo tail -n 10 /var/log/apache2/error.log [Thu Apr 09 04:51:47.531351 2026] [authz_core:error] [pid 3447:tid 281472803860768] [client 127.0.0.1:34926] AH01630: client denied by server configuration: /var/www/html/admin/
The denial entry confirms that the request hit the protected resource and was rejected by the Apache authorization layer.
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.
