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:
[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.logWithout 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.Create the log directory with correct ownership:
- 2.```bash
- 3.sudo mkdir -p /var/log/apache2/sites
- 4.sudo chown www-data:adm /var/log/apache2/sites
- 5.sudo chmod 750 /var/log/apache2/sites
- 6.
` - 7.Configure the CustomLog directive with a path the Apache user can write to:
- 8.```apache
- 9.<VirtualHost *:80>
- 10.ServerName example.com
- 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.Fix SELinux context if applicable:
- 2.```bash
- 3.sudo semanage fcontext -a -t httpd_log_t "/var/log/apache2/sites(/.*)?"
- 4.sudo restorecon -Rv /var/log/apache2/sites
- 5.
` - 6.This labels the custom log directory so SELinux allows Apache to write to it.
- 7.Verify the configuration and test:
- 8.```bash
- 9.sudo apachectl configtest
- 10.sudo systemctl reload apache2
- 11.sudo -u www-data touch /var/log/apache2/sites/example-access.log
- 12.
` - 13.The last command verifies the Apache user can write to the log directory.
- 14.Check for log file creation after reload:
- 15.```bash
- 16.ls -la /var/log/apache2/sites/
- 17.curl -s http://localhost/ > /dev/null
- 18.cat /var/log/apache2/sites/example-access.log
- 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
rotatelogsfor 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