Introduction

When Apache's CustomLog directive references a path where the Apache process cannot write, the server may refuse to start or fail silently without recording access logs. The error log shows:

bash
[Mon Apr 08 23:30:00.123456 2026] [core:error] [pid 1234] (13)Permission denied: AH00091: httpd: could not open transfer log file /var/log/apache2/custom_access.log

Without access logs, you lose visibility into traffic patterns, error rates, and security events.

Symptoms

  • Apache fails to start with "Permission denied: could not open transfer log file"
  • Access log file is empty despite active traffic
  • Error occurs after changing the log path in VirtualHost configuration
  • Works when running as root but fails when running as www-data or apache user
  • SELinux audit log shows AVC denials for httpd writing to the log path

Common Causes

  • Log directory owned by root with permissions 755, not writable by the Apache worker user
  • Custom log path outside the standard /var/log/apache2/ directory lacks proper permissions
  • SELinux prevents Apache from writing to non-standard log paths
  • Log file was created by root during initial config test but Apache worker cannot append to it
  • NFS or network-mounted log directory has restrictive permissions

Step-by-Step Fix

  1. 1.Create the log directory with correct ownership:
  2. 2.```bash
  3. 3.sudo mkdir -p /var/log/apache2/sites
  4. 4.sudo chown www-data:adm /var/log/apache2/sites
  5. 5.sudo chmod 750 /var/log/apache2/sites
  6. 6.`
  7. 7.Configure the CustomLog directive with a path the Apache user can write to:
  8. 8.```apache
  9. 9.<VirtualHost *:80>
  10. 10.ServerName example.com
  11. 11.DocumentRoot /var/www/html

ErrorLog ${APACHE_LOG_DIR}/sites/example-error.log CustomLog ${APACHE_LOG_DIR}/sites/example-access.log combined

# Or use a custom log format LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined CustomLog ${APACHE_LOG_DIR}/sites/example-vhost.log vhost_combined </VirtualHost> ```

  1. 1.Fix SELinux context if applicable:
  2. 2.```bash
  3. 3.sudo semanage fcontext -a -t httpd_log_t "/var/log/apache2/sites(/.*)?"
  4. 4.sudo restorecon -Rv /var/log/apache2/sites
  5. 5.`
  6. 6.This labels the custom log directory so SELinux allows Apache to write to it.
  7. 7.Verify the configuration and test:
  8. 8.```bash
  9. 9.sudo apachectl configtest
  10. 10.sudo systemctl reload apache2
  11. 11.sudo -u www-data touch /var/log/apache2/sites/example-access.log
  12. 12.`
  13. 13.The last command verifies the Apache user can write to the log directory.
  14. 14.Check for log file creation after reload:
  15. 15.```bash
  16. 16.ls -la /var/log/apache2/sites/
  17. 17.curl -s http://localhost/ > /dev/null
  18. 18.cat /var/log/apache2/sites/example-access.log
  19. 19.`

Prevention

  • Use Apache's ${APACHE_LOG_DIR} variable in all log directives for consistency
  • Include log directory setup in your server provisioning playbooks or scripts
  • Add log directory permission verification to your deployment checklist
  • Use rotatelogs for log rotation to avoid permission issues with external logrotate:
  • ```apache
  • CustomLog "|/usr/bin/rotatelogs /var/log/apache2/sites/example-access-%Y%m%d.log 86400" combined
  • `
  • Monitor log file sizes and ensure rotation is working: ls -lhS /var/log/apache2/sites/ | head
  • Document all custom log paths in your infrastructure documentation with their expected permissions