How to Fix SELinux Context for Apache Write Permissions to httpd_sys_content_t Log Files


2 views

When your Apache server throws an IOError 13 while trying to write to a log file it technically owns, you're likely facing SELinux context mismatch. The classic symptom:

IOError: [Errno 13] Permission denied: '/var/www/webapp/k/site/k.log'

The file's current security context shows:

$ ll -Z k.log 
-rw-r--r--. apache apache system_u:object_r:httpd_sys_content_t:s0 k.log

While the audit.log reveals the actual conflict:

type=AVC msg=audit(1409945481.163:1561): avc: denied { append } for pid=16862 comm="httpd" name="k.log" dev="dm-1" ino=201614333 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file

Instead of disabling SELinux (setenforce 0), set the correct context:

# For existing files:
sudo chcon -R -t httpd_sys_rw_content_t /var/www/webapp/k/site/

# For persistent changes:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/webapp/k/site(/.*)?"
sudo restorecon -Rv /var/www/webapp/k/site/

For development environments, you might consider:

# Create a custom policy module from audit log:
sudo grep httpd /var/log/audit/audit.log | audit2allow -M mypolicy
sudo semodule -i mypolicy.pp

# OR set permissive mode for specific domain:
sudo semanage permissive -a httpd_t

After applying changes, verify the new context:

$ ls -lZ /var/www/webapp/k/site/k.log
-rw-r--r--. apache apache system_u:object_r:httpd_sys_rw_content_t:s0 k.log

When your Apache server throws an IOError: [Errno 13] Permission denied error despite correct file ownership, SELinux context is usually the culprit. The audit log clearly shows:

avc: denied { append } for pid=16862 comm="httpd"
scontext=system_u:system_r:httpd_t:s0 
tcontext=system_u:object_r:httpd_sys_content_t:s0

This indicates Apache's httpd_t process is being blocked from writing to a file labeled httpd_sys_content_t.

The key mismatch here is between:

  • Process context: httpd_t (Apache's default SELinux domain)
  • File context: httpd_sys_content_t (typically for read-only web content)

A quick verification shows our file's context:

$ ls -Z /var/www/webapp/k/site/k.log
-rw-r--r--. apache apache system_u:object_r:httpd_sys_content_t:s0 k.log

1. Correct Context Assignment

For log files that Apache needs to write to, use httpd_log_t:

sudo semanage fcontext -a -t httpd_log_t "/var/www/webapp/k/site(/.*)?"
sudo restorecon -Rv /var/www/webapp/k/site

2. Alternative: Custom Policy Module

If you specifically need httpd_sys_content_t, generate a policy module:

sudo grep httpd /var/log/audit/audit.log | audit2allow -M httpd_append
sudo semodule -i httpd_append.pp

3. Temporary Debugging Approach

To test if SELinux is really the issue:

sudo ausearch -c 'httpd' --raw | audit2allow

After applying changes, verify with:

sudo sealert -l "*"

The proper context should now appear:

$ ls -Z /var/www/webapp/k/site/k.log
-rw-r--r--. apache apache system_u:object_r:httpd_log_t:s0 k.log