75

I have Nginx setup and displaying the test page properly. If I try to change the root path, I get a 403 Forbidden error, even though all permissions are identical. Additionally, the nginx user exists.

nginx.conf:

user nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log;

pid        /run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    index   index.html index.htm;

    server {
        listen       80;
        server_name  localhost;
        root         /var/www/html; #changed from the default /usr/share/nginx/html
    }
}

namei -om /usr/share/nginx/html/index.html

f: /usr/share/nginx/html/index.html
dr-xr-xr-x root root /
drwxr-xr-x root root usr
drwxr-xr-x root root share
drwxr-xr-x root root nginx
drwxr-xr-x root root html
-rw-r--r-- root root index.html

namei -om /var/www/html/index.html

f: /var/www/html/index.html
dr-xr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root www
drwxr-xr-x root root html
-rw-r--r-- root root index.html

error log

2014/03/23 12:45:08 [error] 5490#0: *13 open() "/var/www/html/index.html" failed (13: Permission denied), client: XXX.XX.XXX.XXX, server: localhost, request: "GET /index.html HTTP/1.1", host: "ec2-XXX-XX-XXX-XXX.compute-1.amazonaws.com"

Adam Pearlman
  • 971
  • 1
  • 9
  • 16
  • 1
    `tail` the log file `/var/log/nginx/error.log;` and tell me what error u see? – Mohammad AbuShady Mar 23 '14 at 07:34
  • Error log added - sorry, forgot to add that originally - that is the only entry for each request. (I relpaced the IP with Xs. Seems like is error is expected, no?) – Adam Pearlman Mar 23 '14 at 12:48
  • @Adam - `restorecon -r /var/www/` will restore the SELinux contexts in `/var/www/` and below. If you `mv` or `cp` from outside `/var/www` to inside `/var/www` then give `restorecon` a try. I believe it is because the original SELinux context will follow the documents. Kurt or Terry's answers likely fixed the issue, however. – jww Mar 27 '19 at 15:13
  • @Adam - This selected answer leaves something to be desired. It is more like an observation and another question rather then an answer. I think you should chose a different one if you remener the details of the problem. – jww Mar 27 '19 at 15:14

16 Answers16

239

I experienced the same problem and it was due to SELinux.

To check if SELinux is running:

# getenforce

To disable SELinux until next reboot:

# setenforce Permissive

Restart Nginx and see if the problem persists. If you would like to permanently alter the settings you can edit /etc/sysconfig/selinux

If SELinux is your problem you can run the following to allow nginx to serve your www directory (make sure you turn SELinux back on before testing this. i.e, # setenforce Enforcing)

# chcon -Rt httpd_sys_content_t /path/to/www

If you're still having issues take a look at the boolean flags in getsebool -a, in particular you may need to turn on httpd_can_network_connect for network access

# setsebool -P httpd_can_network_connect on

For me it was enough to allow http to serve my www directory.

Kurt
  • 7,102
  • 2
  • 19
  • 16
  • 3
    Hey Kurt, does your answer have something to do with Adam's answer below? Running through your steps did not seem to fix the issue (although disabling SELinux did). Following Adam's answer DID fix the issue, even with SELinux enabled. Thought you might have some more insight on this. – John Leehey Feb 02 '15 at 05:33
  • 2
    Thanks for this answer! I got here after banging my head on this for hours (literally). I am sharing a fuse-based mount (e.g. to S3, like riofs, ObjectiveFS etc) and the `chcon` command didn't work ("operation not supported" trying it with ObjectiveFS mount). You can use the following command to enable it: `$ setsebool httpd_use_fusefs 1` (I got this answer from ObjectiveFS support people - thanks!). Following that, I could serve files from the fuse mount. Apparently, a similar solution should work with nfs (`httpd_use_nfs`, didn't try) – Tomer Cagan Mar 07 '16 at 13:16
  • 3
    best, work like a charm `chcon -Rt httpd_sys_content_t /path/to/www` after setup all permission this is the case, thanks. – bowpunya Jul 19 '16 at 10:59
  • Take a peek at /var/log/messages where selinux messages are logged, then follow the message instruction to enable the correct policy. – Jerther Mar 27 '17 at 15:28
  • Thanks--I had given up hope. – Pete Alvin Jul 31 '17 at 18:05
  • I had to edit /etc/selinux/config (NOT /etc/sysconfig/selinux) on centos 7 – Roni Jan 20 '18 at 20:34
  • What I did was like this: I used ftp to upload a file into server /root folder, then I move the file from /root folder to my html root folder like /var/www, thus the SELinux policy still see the file as root own, even chmod 777 won't solve the problem. Only after chcon it worked. Thank you! – Zhang Buzz Dec 28 '18 at 09:41
  • It is not a good idea to use `chcon` to manage SELinux problem, use `semanage fcontext` instead. – Tony Chou Jan 04 '19 at 06:18
  • @kurt - Thanks for your answer. I swear I meant to accept it *years ago*, after I had some time to review it and see how it applied to my situation, but, you know, life happened... – Adam Pearlman Apr 30 '19 at 13:33
  • simply running sudo chcon -Rt httpd_sys_content_t /path/to/www fixed the issue – Nitish Kumar Oct 23 '19 at 11:22
  • I must have run the `chcon -Rt httpd_sys_content_t` command on the wrong directory ( users home directory). Which caused the effect of bypassing the authorized ssh key and forces to enter my password when logging in via ssh. How can I undo this or overwrite the entire entry to match it with the right value? – user007 Dec 23 '19 at 23:19
  • Will this persist? – leonheess Apr 02 '20 at 16:42
  • I've easily lost a couple days searching for an answer for this, plus being relatively new to linux / centos fuels the headaches! Thanks so much, `sudo chcon -Rt httpd_sys_content_t /path/to/www` did the job for me! :) – chamberlainpi Nov 25 '20 at 20:54
10

First of all you have to run following command to allow nginx to access filesystem

sudo setsebool -P httpd_read_user_content 1

You can check if the files or directory with following command:

ls -Z

If it is still not accessible, you can try changing the SELinux property of the files and folder with following command:

chcon -Rt httpd_sys_content_t /path/to/www

However, above command cannot apply to files under FUSE or NFS system.

To enable serving files from FUSE mounts, you can use:

setsebool httpd_use_fusefs 1

To enable serving files from NFS mounts, you can use:

setsebool httpd_use_nfs 1
Terry Lam
  • 1,025
  • 1
  • 12
  • 13
7

I ran into the same problem. If you're using Fedora/RedHat/CentOS, this might help you:

  • According to SELinux: setsebool -P httpd_read_user_content 1

Hope this helps.

Bryan Macías
  • 71
  • 1
  • 1
5

There are 2 possible reasons for denied access:

  1. Access is denied by DAC. Double check user, group and file permissions. Make sure the nginx process, when running as the user specified in its config file, can access the new html root path.

  2. Access is denied by MAC. The most widely used of such is SELinux. To check whether it caused the problem, you can stop the nginx process and run this command:

    setenforce Permissive
    

    Then start nginx again to see if access is granted.

    Alternatively, you can check the file context:

    setenforce Enforcing
    ls -Zd /usr/share/nginx/html /var/www/html
    

    If the two contexts differ, you may need to change the context for the new html root path:

    chcon -R -t httpd_sys_content_t /var/www/html
    

    Restart nginx and see if it works fine. If so, you can make the change permanent:

    semanage fcontext -a -t httpd_sys_content_t '/var/www/html(/.*)?'
    restorecon -Rv /var/www/html
    

    Some of these commands need to be run as root.

Cyker
  • 9,946
  • 8
  • 65
  • 93
4

This is an addition to Prowlas answer but I dont have enough reputation to commment: If the /path/to/www is a home directory of a user. You should try:

setsebool -P httpd_enable_homedirs=1

This solved my problem

Source: http://forums.fedoraforum.org/archive/index.php/t-250779.html

rassi
  • 375
  • 3
  • 8
3

Remember you need to allow other users to read the entire path. Also remember Dropbox will set 700 to its root directory. So chmod 755 ~/Dropbox solved my problem.

Michael Ma
  • 872
  • 8
  • 20
3

The folks using the /home/{user} directory to serve their website need to provide a chmod 755 access on their /home/{user} directory to make this work .

Also , if SELinux is enabled on the server please use the below mentioned commands :-

  1. sudo setsebool -P httpd_can_network_connect on
  2. chcon -Rt httpd_sys_content_t /path/to/www
animo3991
  • 181
  • 2
  • 9
2

well seems logical, all files are root user, try changing it to nginx user, just wanted to make sure it's not a listing permission denied first.

sudo chown -R nginx:nginx /var/www/html
Mohammad AbuShady
  • 40,884
  • 11
  • 78
  • 89
  • Changed all owners and groups to nginx (including /var) and I get the same error: 2014/03/23 13:08:47 [error] 5595#0: *23 open() "/var/www/html/index.html" failed (13: Permission denied), client: XXX.XX.XXX.XXX, server: localhost, request: "GET /index.html HTTP/1.1", host: "ec2-XXX-XX-XXX-XXX.compute-1.amazonaws.com" – Adam Pearlman Mar 23 '14 at 13:10
  • 1
    The same index file will work if I place it into the /usr/share/nginx/html dir, so I guess that's a work-around, but I'd really like to figure this out. Thanks for your help. – Adam Pearlman Mar 23 '14 at 13:13
  • 1
    it's kinda strange, I usually don't use neither `/var/www` nor `/usr/share/nginx`, I can't really say I've seen this error before – Mohammad AbuShady Mar 23 '14 at 13:16
  • What about the `www-data` user? – NerdOfCode Nov 06 '17 at 03:48
  • @NerdOfCode I'd say it depends on the linux distro, find what your distro is using and replace `nginx` with it. – Mohammad AbuShady Nov 06 '17 at 08:39
  • @Adam - `restorecon -r /var/www/` will restore the SELinux contexts in `/var/www/` and below. If you `mv` or `cp` from outside `/var/www` to inside `/var/www` then give `restorecon` a try. I believe the original SELinux context will follow the documents. Kurt or Terry's answers likely fixed the issue, however. – jww Mar 27 '19 at 15:11
2

I have met this problem when I added a new user with a folder /home/new_user as a new virtual host. Make sure these folders (/home, /home/new_user, /home/new_user/xxx...) are 755 so that it resolved my problem. At last, I found my problem were correctly according to the /var/log/nginx/error.log file.

superarts.org
  • 7,009
  • 1
  • 58
  • 44
loszer
  • 21
  • 2
1

I was using:

sudo service nginx start

If I use:

sudo nginx 

...everything works fine. Can anyone explain the difference between these two?

Adam Pearlman
  • 971
  • 1
  • 9
  • 16
  • 8
    See answer here: http://serverfault.com/a/656371 Also in my humble opinion I think you should accept Kurt's answer. – Snorex Jul 14 '15 at 18:35
1

I ran into the same problem:

  • Checked nginx.conf to verify the user
  • Permissions were set properly
  • Made sure "x" right was set for the entire path

Did a restart from the command line (I'd been using Webmin all this time) and noticed this error:

 aed@aed:/var/www/test.local$ sudo service nginx restart
 * Restarting nginx nginx 
nginx: [warn] conflicting server name "test.local" on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name "test.local" on 0.0.0.0:80, ignored

Apparently there was a duplicate definition and thus my attempt to access "test.local" failed.

dougB
  • 499
  • 5
  • 11
1

Work fine for me on nginx

semanage permissive -a httpd_t
Makara Set
  • 333
  • 3
  • 4
0

Another possible reason (NOT IN THIS CASE) is a symlink for index.html file pointing to another directory.

ls -lrt /usr/share/nginx/html/

enter image description here

rsync files to that particular directory will easily solve the problem.

or disable symlinks in nginx.conf

http {
    disable_symlinks off;
}
Ashfaq
  • 1,137
  • 1
  • 12
  • 22
0

i meet another issue(don't know why yet, but it might be useful for someone else)

i first put the folder under my /home/my_name/www/site_name, and change the owner and change the permission. then check the selinux stuff.

all the above doesn't solve my problem. finally, i change the folder to /srv/www/site_name, all is good now.

NormanOu
  • 65
  • 8
-1

Modify the file nginx.conf, change the user name to your account name, and restart nginx.it work !

zhuoming
  • 17
  • 1
-11

this solved the same problem:

restart Nginx and try again. If it fails, check again the logs. This worked for me

mauva
  • 1