CentOS 7 + SELinux + PHP + Apache – cannot write/access file no matter what

I’ve spent 2-3 hours pulling my hair trying to setup a supposed to be simple PHP/MySQL web application on an Amazon EC2 instance running on CentOS 7. Apache logs keep saying that it can’t write to file due to permission where file permissions are properly setup, only to realize it was SELinux in action.

Problem 1: Can’t serve files on a custom directory

The first problem I have encountered is that I tried to setup the application inside /data/www/html/sites/mysite. When viewed on the browser, it says 403 Forbidden and error logs says:

13)Permission denied: [client] AH00529: /data/www/html/sites/mysite/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable and that '/data/www/html/sites/mysite/' is executable

The directory structure has proper ownership and permissions, ex: directory is owned by apache:apache, file permission is 0644 and directory permission is 0755. It doesn’t make sense at all. I noticed though that the default document root has no problem serving the php file so I decided to serve it off the /var/www/html/mysite directory, which is the default document root.

Problem 2: Can’t write to file

Moving to the default document root directory did the trick and I was able to run the application but with errors. The error says it can’t write to file although again, proper permissions are already set to the directory. Below is the error (it is a custom error log, but if writing to log file doesn’t work, imagine how your upload functionality would work):

PHP Warning:  fopen(/var/www/html/mysite/application/config/../../logs/web/20150708.ALL.log): failed to open stream: Permission denied in /var/www/html/mysite/application/core/App_Exceptions.php

Surprise! SELinux is here!

You guys choose CentOS, so you got SELinux as well.

After realizing that it was SELinux whose messing with me for the past 2 hours, I was thinking of ditching CentOS and go with the recommended Ubuntu instead. But then my instinct tells me that if SELinux is blocking the read/write operations, it must did it for a good reason, and that was for security. I realize that you need to specify which files/directories Apache can serve files and which files/directories it can write into.

SELinux seems to have some rules/policies that applies to files/directories on top of the unix file permissions structure. When I run the command below on the default document root, I saw more information on the file/directory permissions.

ls -Z /var/www/html/mysite

Below is the output (some information removed):

drwxr-xr-x. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 application
-rw-r--r--. apache apache unconfined_u:object_r:httpd_sys_content_t:s0 index.php

And below is what I got for other normal directories:

drwxr-xr-x. apache apache unconfined_u:object_r:default_t:s0 www

Therefore, we can conclude that we need to specify the proper SELinux permissions on directories in order to serve files on a custom directory and set another SELinux permissions to allow writing to file. Therefore, we can solve the original problem then.

Fixing the original problem

So we want to serve our files at /data/www/html/sites/mysite and enable writing to log files and file uploads as well? Let’s play nice with SELinux.

First, copy the files as usual to /data/www/html/sites/mysite, then set the proper ownership and permissions.

# Ownership
sudo chown apache:apache -R /data/www/html/sites/mysite
cd /data/www/html/sites/mysite

# File permissions, recursive
find . -type f -exec chmod 0644 {} \;

# Dir permissions, recursive
find . -type d -exec chmod 0755 {} \;

# SELinux serve files off Apache, resursive
sudo chcon -t httpd_sys_content_t /data/www/html/sites/mysite -R

# Allow write only to specific dirs
sudo chcon -t httpd_sys_rw_content_t /data/www/html/sites/mysite/logs -R
sudo chcon -t httpd_sys_rw_content_t /data/www/html/sites/mysite/uploads -R

httpd_sys_content_t – for allowing Apache to serve these contents and httpd_sys_rw_content_t – for allowing Apache to write to those path.

That’s it! I enjoyed and you share!

This entry was posted in Linux and tagged , , , , . Bookmark the permalink.

Related Posts

94 Responses to CentOS 7 + SELinux + PHP + Apache – cannot write/access file no matter what

  1. Bui Tonny says:

    httpd_enable_cgi –> on
    httpd_unified –> on
    httpd_builtin_scripting –> on

    Check values of three this on php.ini sure it is on

  2. EdwinTG says:

    Perfect, I solved my “zend forbidden permission” issue with your help,
    # SELinux serve files off Apache, resursive
    sudo chcon -t httpd_sys_content_t /data/www/html/sites/mysite -R
    Thank you so much!

  3. lysender says:

    @Edwin, great!

  4. K says:

    This is what saved me, was struggling for about 6hrs yesterday and today combined to attempt to fix it and I was nowhere close. This knocked out my problem first try.
    Thanks for taking the time to make this guide!


  5. Paresh says:

    Thanks lysender ….

    Solved the issue. Was struggling since 2 days…

    Thank you so much πŸ™‚

  6. Anton says:

    httpd_sys_rw_content_t will be replaced back after restorecon
    for example: restorecon -R “/data/www/html/sites/mysite”
    better use
    semanage fcontext -a -t httpd_sys_rw_content_t “/data/www/html/sites/mysite/uploads(/.*)?”
    to apply the settings permanently

  7. lysender says:

    @Anton, interesting. SELinux seems too complicated to me now.

  8. Antonio says:

    Thank you !

  9. Vuong says:

    So cool…it is very interesting.
    Thank you!

  10. David says:

    Thanks for the post. The problem with selinux problems is that you have to know have to know that its an selinux problem before you google. Otherwise, you just end up with people saying you’ve just chown’d or chmod’d wrong. *sigh*

    Your site popped right up and solved my problem once I knew the problem. Thanks again!

  11. Guillaume says:

    sudo chcon -t httpd_sys_rw_content_t /data/www/html/sites/mysite/logs -R
    THANK YOUUUUUU, centos is so painful for the permissions ^^

  12. lysender says:

    I’m glad that it helps! We are trying to switch to Ubuntu Wily by the way, which is a new beast to me.

  13. Ricardo Mendes says:


    Just to leave an opinion.
    I don’t like nor recommend Ubuntu for production servers (and it’s widely discouraged).
    CentOS/RedHat and it’s relatives are rock solid server material.

    Regarding this issue and SELinux, by setting the content type to httpd_sys_content_t you don’t need to chown the files to apache user/group.

  14. lysender says:

    We’re ditching CentOS completely as we can’t really catch up with more recent PHP packages with CentOS 7. Not sure what happens during the EOL of PHP 5.4 but right now, we are even planning to get PHP 7 with Ubuntu Xenial.

  15. George Andor says:

    Thank you for sharing the solution to this problem!
    It really saved my day.
    I was having trouble having WordPress writing its configuration file during install.
    While searching CentOS and WordPress related issues, all I found on the internet was recommendations of changing ownership and rights, which were already set correctly.
    I had no knowledge of the SELinux imposed security mechanism.

  16. Moko says:

    thank you, works fine on centos 7. (i’m using codeigniter)

  17. Edgar says:

    Wow, thank you so much for sharing. Edgar from Mexico :V

  18. PROGYS says:

    You are a life time saver !
    I spend about 2 days on it, desable SELinux is not a issu, they made it for a purpose I believed !

    I have a website by default with ‘root’ as the owner and it goes nicely. But when I decide to add another one I have got that f**king error, I even change the owner to the ‘root’ same thing.
    I am not a Linux Admin, but I used to host some website on Centos.

    Again thanks !

  19. Manuel says:

    thank you, works on centos 7 + php + wordpress->(migration).

    again, thank you.

  20. DCF says:

    Spent many days on this and finally came across your post. Thanks so much!

  21. Alok Ranjan says:

    Thanks for nice information.

  22. anotherGoodDay says:

    u really saved my day Lysender! many many thanks!

  23. denshade says:

    Thanks, I’ve looking into this for hours. Good thing I found you blog!

  24. chloe says:

    THANKS for the accurate, simple notes.

    For CentOS 7 + SELinux + Apache + SVN, I used all your fix steps through SELinux serve files off Apache, resursive, but then, instead of adjusting logs and uploads, I gave httpd_sys_rw_content_t on the ./db and ./locks subdirectories under each repo. That solved my problem of trying to commit changes to the repository.

    Sample error message had been:
    Commit failed (details follow):
    Can’t move
    to ‘/var/www/(snip)/db/revs/3/3993’:
    Permission denied

  25. lysender says:

    @chloe, that’s odd. If you just do the svn or git stuff as a regular user or a user with enough permissions, you should be able to perform svn/git commands without messing up with SELinux.

  26. James says:

    I have had this issue for the past two days! I’ve had the hosting support on the case changing folder permissions, apache configuration, php configuration with no luck.

    I am so grateful, thank you so much!

  27. Pingback: Sometimes it is annoying – Paolo Redaelli

  28. Sboon says:

    Thanks a lot…

  29. fewrare says:

    Thanks a lot. I really appreciate it.

  30. Francisco Cortes says:

    6 hours of search online on why third party install was not able to write to the installation folder (nothing generic to search for) and then I run into your post, run the commands you provided and bam!!!. it worked like a charm

    Thank you, thank you, thousand thank you’s!!!!!
    you’ve made my day!!

  31. Yuriu says:

    Thanks a lot.
    chcon -t httpd_sys_rw_content_t symfony/app/cache -R
    chcon -t httpd_sys_rw_content_t symfony/app/logs -R
    It works.

  32. raitch says:

    Thank you! This solved my ResourceSpace installation issue, I sent a link to this page for them to review in their docs, hope that is okay.

  33. lysender says:

    I’m glad it helps you.

  34. Rajesh Maulekhi says:

    Thanks it works , and solve problem

  35. Jerome says:

    You saved me! I have been scratching my head for 3 hours now.
    Never heard of this before.
    Thanks a lot Lysender.
    Thank you for sharing <3

  36. Mike Kormendy says:

    So what happens when SELinux is disabled?
    SELinux is disabled on my CentOS7 install and I still cannot write to folders outside of my web root.

  37. Abdul Manaaf says:

    Thank you, that’s solved my stupid problems

  38. tom says:

    SELinux disabled your asking for a major security risk. It’s ok I guess if your the only site..

  39. lysender says:

    Agreed! SELinux should be enabled and specify the right security setting rather than disabling it completely.

  40. Harkat Zamasi says:

    Thanks you. My web problem solved.

  41. Serge says:

    It doesn’t work for me. If SELinux disabled OK, but with SELinux even with your sulution doesn’t work.

  42. shameer says:

    Thank you so much. Its worth reading. Your are awesome

  43. ligz says:

    Thanks a lot offor the post! It helped a lot.

  44. Max Musermann says:

    Thank you very much!

  45. Daniel Pe says:

    Thank you so much man, this solve my problems with TCPDF

  46. tim says:

    Incredible, this should be everywhere! fixed my problems with mpdf. Holy smokes I spent all weekend trying to get this to work. Thanks!!

  47. Lusungu Chisesa says:

    WOW this has been so helpful eish I was about to dish CentOS 7 to Fedora or even go back to ubuntu. Finally this has been my rescue. Thumbs up….

  48. Mojtaba Rezaeian says:

    Perfect Article! Thank you :X:X:X

  49. DocDawning says:

    Thanks a lot. I’ve been retooling from Ubuntu to CentOS. On the one hand SELinux is “annoying” and “in the way” and on the other hand, it seems a platform with a reason to exist. Thanks for the help!

  50. May says:

    Thank you, your information is helpful πŸ™‚

  51. Omar says:

    You are awesome thank u very much spend two days o searching this

  52. Nanda Elyas says:

    thx sir… my problem fixed

  53. Raman says:

    Awesome … It Worked..I was just going to switch back to debian… thinking of some problem in cent os 7… but its security… Thank You..

  54. Vuong says:

    Thanks for great tip. It also fixed my problem πŸ™‚

  55. Daptim says:

    This Article just save me from my poor Linux knowlegde, I just install apache 2.4 on my centos 7 lab virtual machine and i was has the same problem for the past fews days now.
    Thanks for this nice article

  56. Ivan says:

    Thanks fro great article!

  57. Khiem Le says:

    Thank you very much !
    You helped me so much to resolve my issue.
    I took a lot of time but cannot resolve it.
    Thanks for great article!

  58. Martin says:

    This is an amazing post, you know, you have saved many hard working people!! You are super hero!!!!!!

    Thank you very much!!

  59. rod says:

    thanks! it work! really appreciated for your help!

  60. sebastien says:

    Thanks you!

  61. LC says:

    Perfect, you did share a great experience. Appreciate your effort! Thanks!!!

  62. lefale00 says:

    Could not get my Drupal 8 site to work properly until I found your post. You saved my day, sir πŸ™‚

  63. Palvinder says:

    Awesome! You made my day πŸ™‚

    Thank you very much!

  64. Palvinder says:

    It is worth to share on Social Sites, however, I don’t see any option for Social Sharing.

    Please advise.

  65. lysender says:

    @Palbinder, I removed the Facebook/Google share buttons to remove those trackers. If you use desktop, you can just copy and paste the URL. On mobile, well, not sure.

  66. Joseph says:

    Thanks for your useful information. I just thought I would share some since I am also using Centos (7) for server with Apache. I did some tests and found that PHP/Apache PHP can operate with all directories as permissions “100” and can write to a log file that is permissions “200”. So, in a production server, the following permissions are just fine (working on localhost at least).

    # File permissions, recursive
    find . -type f -exec chmod 0400 {} \;

    # Dir permissions, recursive
    find . -type d -exec chmod 0100 {} \;

  67. Lucian Costin says:

    November 2018 and there you are, you saved my day. More hours spend and gray hairs grown, kept getting a PHP permission denied at mkdir, hours of ownerships and groups changing, reading and what not, thank you sir!
    SELinux!!! thank you for this article!

  68. lysender says:

    @Lucian – I’m glad it helps. It’s been a long time since I’ve used CentOS as I’m mostly using Ubuntu or Alpine.

  69. Rajesh Manickavel says:

    Superb!! This resolved my issue too.

  70. Fajarra says:

    Brilliant, my problem solved….!thx

  71. oscar serrano says:

    thank you the selinux commands big help!

  72. VugarAli says:

    Tahnks man

  73. Alberto Lepore says:

    Great post! Solved! Centos 7

  74. Lyghtnyn says:

    Thanks a lot for this post, had this issue since Monday. Worked great for CENTOS 7. This post was from 3 + yrs ago. Good job

  75. Ravi says:

    Thank you lysender! I was struck for 24 hours to fix this File Open Permission issue on Google Cloud Compute Engine but could not.

    Your post solved it like a charm!

    Great JOB! Thank you once again!

  76. seafree says:

    Hi, I have this error but in the same server exist a web site, the question is: have I need to do other modifications?
    Thank you.

  77. lysender says:

    @seafree – I don’t know what your question exactly is, so I don’t have an answer πŸ˜€

  78. Sunil Kumar says:

    Thank you !! Helped me.

  79. NOYB says:

    Perfect! That’s what I was looking for (apache httpd file write permission).

  80. Thanks alot…!!!
    I spent almost 2 days to resolve this issue.
    You are a life saver to me.

    It worked perfectly to me.
    Thank you again..

  81. Bryan Brodie says:

    Dude! five years later you’re still helping people – me included – thanks!

  82. Bob says:

    Yes! Dude, you should put a Buy Me a Beer button on this page!

  83. Akeel says:

    Spent a good couple of hours before this post. Thank you so much for this. Works on CentOs 7

    P.S. I hate CentOs

  84. Pedro says:

    Thanks! You saved my morning.

  85. mgaidi says:

    Thanks so much !

  86. Vishwa Jay says:

    Spent a week before this post … why didn’t this come up sooner in the list of answers????

    Thank you, Lysender!

  87. Sebastian says:

    Thank you!

  88. Rido says:

    Nice article, help us so much .. thanks

  89. George says:

    really helpful. Thank you a ton

  90. Provided og:image, https://wp.nurse.com/wp-content/uploads/2020/03/Nurses-shaking-hands-FB-GettyImages-1179802241.jpg could not be downloaded. This can happen due to several different reasons such as your server using unsupported content-encoding. The crawler accepts deflate and gzip content encodings.

    server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.6.40

    What is the issue please let me know?

  91. Wow. Thank you. I think sys_content is writable until I see this. It’s understanable for security perspective.

    I also seen here.

  92. Snabor says:

    Great article.
    Easy and simple.
    Thanks a lot !!

  93. Abid Maqbool says:

    It really worked for me. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *