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.

Steps to restrict access by IP in Apache:

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

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

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

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

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

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

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

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

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