sfw/fix
AH01630 high

Apache AH01630: client denied by server configuration

Apache 2.4's access-control module rejected the request before any handler ran, returning a 403 logged as AH01630.

What you see

[authz_core:error] [pid 2211] [client 203.0.113.9:51877] AH01630: client denied by server configuration: /var/www/html/app

What’s actually happening

Visitors get a 403 Forbidden on a directory or the whole site, and the error_log shows AH01630 from authz_core naming the path it refused. The file clearly exists and permissions look fine. This very commonly appears right after upgrading from Apache 2.2 to 2.4, or after dropping in a config snippet copied from an old tutorial.

Common causes

  • The directory block still uses Apache 2.2 syntax (Order allow,deny / Allow from all), which 2.4's authz_core ignores, leaving the default of deny-all in effect.
  • A <Directory> or <Location> block is missing `Require all granted` entirely, so nothing authorizes the request.
  • An alias or new docroot points outside the paths that have a permissive Require, e.g. serving from /srv/app while only /var/www is granted.
  • A `Require ip` / `Require host` rule is narrower than the client actually connecting (proxy IP vs real client, IPv6 vs IPv4).
  • Conflicting <RequireAll> / <RequireAny> nesting where one unmet condition denies the whole block.

How to fix it

  1. Grant access with 2.4 syntaxIn the <Directory> for your docroot, replace any Order/Allow lines with:\n<Directory /var/www/html>\n Require all granted\n</Directory>\nThen `apachectl configtest` and `systemctl reload apache2`. This clears the bulk of AH01630 cases.
  2. Find every block touching that pathRun `apachectl -t -D DUMP_INCLUDES` or grep the path: `grep -rn 'Require\|Order\|Allow' /etc/apache2/`. The denying rule may live in a conf.d snippet or an .htaccess, not the vhost you're editing.
  3. Match the docroot to the granted directoryIf your DocumentRoot or Alias points at /srv/app, add a matching <Directory /srv/app> ... Require all granted block. A grant on /var/www does nothing for files served from elsewhere.
  4. Migrate mixed 2.2/2.4 configs cleanlyIf you must keep old-style directives temporarily, load mod_access_compat — but the right fix is to convert: `Allow from all` -> `Require all granted`, `Deny from all` -> `Require all denied`, `Allow from 10.0.0.0/8` -> `Require ip 10.0.0.0/8`.
  5. Check the real client IP behind a proxyIf you use `Require ip`, requests coming through a load balancer or Cloudflare arrive from the proxy's IP. Either grant the proxy range or use mod_remoteip so Require ip sees X-Forwarded-For correctly.

Stop it recurring

After any 2.2-to-2.4 upgrade, grep the whole config tree for Order/Allow/Deny and convert each to the Require syntax before going live.

Related errors