Apache errors - (sh*t happens)


Apache error : AH00035: access to /myPage.html denied

While trying to setup a basic Apache configuration, /var/log/httpd/error_log reports :
[Wed Sep 20 15:48:30.346550 2017] [core:error] [pid 25989] (13)Permission denied: [client] AH00035: access to /myPage.html denied (filesystem path '/path/to/myPage.html') because search permissions are missing on a component of the path

Solution (part 1/2) :

This is usually because the user account running apache (or httpd for Red Hatoids) is not allowed to read the path set as DocumentRoot.
  1. Just to make sure you're not running something exotic : check the username + group of the apache process owner :
    • on Red Hatoids :
      grep -E '^(User|Group) ' /etc/httpd/conf/httpd.conf
      User apache
      Group apache
    • on Debianoids :
      grep -E '^(User|Group) ' /etc/apache2/apache2.conf
      User ${APACHE_RUN_USER}
      Group ${APACHE_RUN_GROUP}
      grep -E 'APACHE_RUN_(USER|GROUP)' /etc/apache2/envvars
      export APACHE_RUN_USER=www-data
      export APACHE_RUN_GROUP=www-data
  2. Check current configuration options :
    • on Red Hatoids :
      httpd -t -D DUMP_RUN_CFG | grep DocumentRoot
    • on Debianoids :
      apache2 -t -D DUMP_RUN_CFG | grep DocumentRoot
    Main DocumentRoot: "/path/to"
  3. Set permissions (source) :
    myDocumentRoot='/path/to'; find "$myDocumentRoot" -type d -exec chmod 755 {} +; find "$myDocumentRoot" -type f -exec chmod 644 {} +

This should do the trick, unless SE Linux is on the way. Red Hatoid users, keep on reading part 2

Solution (part 2/2) (source) :

Quick check that SE Linux is the one throwing off your groove :

  1. make sure SE Linux is enabled and enforcing :
  2. try your HTTP request :
    <title>403 Forbidden</title>
    <p>You don't have permission to access this resource.</p>
  3. disable SE Linux :
    setenforce 0
  4. make a new HTTP request :
    curl -i
    HTTP/1.1 200 OK
    (contents of myPage.html)
  5. now you know who the guard has to throw out of the palace window

Extra evidence against SE Linux :

  1. monitor the logs :
    tail -f /var/log/audit/audit.log | grep -E 'type=(AVC|SYSCALL)'
  2. generate some HTTP traffic by replaying the curl command again
    If you've left SE Linux in Permissive mode from previous experiments, curl commands will succeed whereas the logs will show otherwise.
    Read more about SELinux modes.
  3. you found the culprit if you can see things
    • like this :
      type=AVC msg=audit(1505919935.243:23294): avc: denied { getattr } for pid=28387 comm="httpd" path="/path/to/myPage.html" dev="dm-2" ino=786435 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:unlabeled_t:s0 tclass=file
      type=SYSCALL msg=audit(1505919935.243:23294): arch=c000003e syscall=4 success=no exit=-13 a0=7f511728e340 a1=7ffe6a31c6e0 a2=7ffe6a31c6e0 a3=7f510d20c792 items=1 ppid=28385 pid=28387 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
    • or like this :
      uid=48 gid=48
      id apache
      uid=48(apache) gid=48(apache) groupes=48(apache)


chcon --user system_u --type httpd_sys_content_t -Rv "$myDocumentRoot"

Apache error : AH01630: client denied by server configuration


After upgrading Apache 2.2.x to Apache 2.4.10, /var/log/apache2/error.log started complaining :

[Sun Jan 03 15:55:13.845797 2016] [authz_core:error] [pid 2205:tid 139630284179200] [client] AH01630: client denied by server configuration: /path/to/some/web/resource


This is due to changes in the access control methods between versions 2.2 and 2.4, now using the mod_authz_host module.


The website we're considering is on a development workstation, and should only be accessed from that workstation. The virtualhost configuration had the following lines for Apache 2.2.x :

Order Deny,Allow
Deny from all
Allow from
Which can be replaced, for Apache 2.4.10, with :
Require host

This is a quick fix, and the Apache documentation should be further studied before doing this to production servers.

Other interesting Require options :

Require local
allow connections from the local host
Require all granted
grant access to all requests
Require all denied
deny access to all requests

apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName

If the webserver hosts a single site, and the server names matches the website's name :

echo 'ServerName myServerName' > /etc/apache2/conf.d/fqdn

Otherwise (multiple websites, multiple virtualhosts, multiple server names per virtualhost) :

  1. echo 'ServerName localhost' >> /etc/apache2/apache2.conf
  2. Make sure /etc/hosts has a line as short as : localhost (no more aliases are necessary / welcome)

When Apache VirtualHosts are in a mess : Warning: DocumentRoot [] does not exist


Some colleagues are not the Please-leave-this-place-as-clean-as-it-was-when-you-arrived type : they add VirtualHosts to a shared Apache webserver (development platform) and just don't give a f*ck about the warnings at reload/restart when their VirtualHosts are not required / working anymore.


Upon reload/restart, Apache complains :
Warning: DocumentRoot [/path/to/docRoot1/] does not exist
Warning: DocumentRoot [/path/to/docRoot2/] does not exist
Warning: DocumentRoot [/path/to/docRoot3/] does not exist


So let's do some cleaning :
cd /etc/apache2/sites-available/; for missingDocRoot in /path/to/docRoot1/ /path/to/docRoot2/ /path/to/docRoot3/; do a2dissite $(grep -l "$missingDocRoot" *); done; /etc/init.d/apache2 reload