109

Just want to help somebody out. yes ,you just want to serve static file using nginx, and you got everything right in nginx.conf:

location /static {
       autoindex on;
       #root /root/downloads/boxes/;
       alias /root/downloads/boxes/;
      }

But , in the end , you failed. You got "403 forbidden" from browser...

----------------------------------------The Answer Below:----------------------------------------

The Solution is very Simple:


Way 1 : Run nginx as the user as the '/root/downloads/boxes/' owner

In nginx.conf :

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;

YES, in the first line "#user noboy;" , just delete "#" , and change "nobody" to your own username in Linux/OS X, i.e change to "root" for test. The restart nginx.

Attention , You'd better not run nginx as root! Here just for testing, it's dangerous for the Hacker.

For more reference , see nginx (engine X) – What a Pain in the BUM! [13: Permission denied]


Way 2 : Change '/root/downloads/boxes/' owner to 'www-data' or 'nobody'

In Terminal:

ps aux | grep nginx

Get the username of running nginx . It should be 'www-data' or 'nobody' determined by the version of nginx. Then hit in Terminal(use 'www-data' for example):

chown -R www-data:www-data /root/downloads/boxes/

------------------------------One More Important Thing Is:------------------------------

These parent directories "/", "/root", "/root/downloads" should give the execute(x) permission to 'www-data' or 'nobody'. i.e.

ls -al /root
chmod o+x /root
chmod o+x /root/downloads

For more reference , see Resolving "403 Forbidden" error and Nginx 403 forbidden for all files

Community
  • 1
  • 1
isaacselement
  • 2,579
  • 3
  • 22
  • 23
  • 2
    you can also give the files permission to the group nginx is in, which is what is usually done, and also a little bit more logical – gitaarik May 29 '13 at 09:06
  • @rednaw, i'm new in stackoverflow too, sorry for the pervious comment, yes , i did it following you answer, but i failed again. i did changed owner to the file , but the browser show me the "403 forbidden". – isaacselement May 29 '13 at 12:51
  • 1
    did you restart nginx? also, nginx has a error log files (usually in `/var/log/nginx/`) where you can find more information, check the error and access log for example. BTW, maybe you should comment on my answer instead of your question. – gitaarik May 29 '13 at 13:12
  • `user root` worked perfectly for me on my development machine – necromancer Sep 13 '13 at 04:19
  • 1
    @no_answer_not_upvoted , hey man , be careful with "root" , if a hacker hack you nginx server , root will be the hacker . – isaacselement Sep 13 '13 at 08:38
  • 1
    Don't run nginx as root please! – Poli Jun 04 '14 at 19:42
  • @rednaw thank you. I vow to make "did you restart nginx?" my go-to first step – AtAFork Nov 28 '16 at 07:00

13 Answers13

90

You should give nginx permissions to read the file. That means you should give the user that runs the nginx process permissions to read the file.

This user that runs the nginx process is configurable with the user directive in the nginx config, usually located somewhere on the top of nginx.conf:

user www-data

http://wiki.nginx.org/CoreModule#user

The second argument you give to user is the group, but if you don't specify it, it uses the same one as the user, so in my example the user and the group both are www-data.

Now the files you want to serve with nginx should have the correct permissions. Nginx should have permissions to read the files. You can give the group www-data read permissions to a file like this:

chown :www-data my-file.html

http://linux.die.net/man/1/chown

With chown you can change the user and group owner of a file. In this command I only change the group, if you would change the user too you would specify the username before the colon, like chown www-data:www-data my-file.html. But setting the group permissions correct should be enough for nginx to be able to read the file.

gitaarik
  • 42,736
  • 12
  • 98
  • 105
  • 23
    `user root` made the problem go away and never, ever show its face again. (may the hyperventilation begin! ;-) – necromancer Sep 13 '13 at 04:18
  • 14
    It might be an easy fix, but running programs as root can be dangerous. If there's an exploid in Nginx, and it's running as root, a cracker might be able to take over the complete OS. – gitaarik Sep 17 '13 at 08:06
  • 1
    see my hyperventilation remark. yes, it is a valid concern but often the machine is dedicated to nginx or has no critical information so even if a cracker takes over it is no big deal. and again it is indeed valid if you are running nginx on a serer which also has all your company IP and your email – necromancer Sep 17 '13 at 08:09
  • 1
    i did upvote your answer btw because it helps for the times when you do need to do things right – necromancer Sep 17 '13 at 08:10
44

Since Nginx is handling the static files directly, it needs access to the appropriate directories. We need to give it executable permissions for our home directory.

The safest way to do this is to add the Nginx user to our own user group. We can then add the executable permission to the group owners of our home directory, giving just enough access for Nginx to serve the files:

CentOS / Fedora

  sudo usermod -a -G your_user nginx

  chmod 710 /home/your_user 

Set SELinux to globally permissive mode, run:

sudo setenforce 0

for more info, please visit https://www.nginx.com/blog/using-nginx-plus-with-selinux/

Ubuntu / Debian

  sudo usermod -a -G your_user www-data

  sudo chown -R :www-data /path/to/your/static/folder
sandes
  • 1,917
  • 17
  • 28
  • 4
    Thanks! I searched online for hours and only your answer helped. Appreciate it!! – Logan Yang Mar 15 '18 at 22:31
  • 3
    The "Ubuntu" solution resulted that now I can't login by ssh anymore! – Miguel Mar 03 '20 at 11:57
  • 1
    The ubuntu solution worked for me thanks! – Bruce Dec 05 '21 at 11:31
  • 1
    In the same folder, all files have the same permission flags, but only one of the files cannot be accessed (with nginx's permission denied error). Set SELinux to permissive mode addressed my problem. – Gary Wang Jun 09 '22 at 01:15
16

for accepted answer

sudo chown -R :www-data static_folder

for changing group owner of all files in that folder

masternone
  • 429
  • 5
  • 13
12

I ran into this issue with a Django project. Changing user permissions and groups didn't work. However, moving the entire static folder from my project to /var/www did.

Copy your project static files to /var/www/static

# cp -r /project/static /var/www/static

Point nginx to proper directory

# sudo nano /etc/nginx/sites-available/default

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name _;

        location /static/ {
                root /var/www;
        }

        location / {
                include proxy_params;
                proxy_pass http://unix:/run/gunicorn.sock;
        }

}

Test nginx config and reload

# sudo nginx -t
# sudo systemctl reload nginx
Jason
  • 813
  • 11
  • 13
11

For me is was SElinux, I had to run the following: (RHEL/Centos on AWS)

sudo setsebool -P httpd_can_network_connect on 
chcon -Rt httpd_sys_content_t /var/www/
Joe
  • 462
  • 6
  • 14
  • Thank you! I’m using Fedora on my remote dev box, and am not used to SELinux. This was exactly the comment I was looking for :) – Lyndsy Simon Oct 28 '19 at 16:01
  • 2
    Just `chcon -Rt httpd_sys_content_t /var/www/` works like a charm – noomz Feb 12 '20 at 14:45
  • Had no problem running Flask with Nginx on Centos 7. Updated to Almalinux recently and since then had 403 forbidden and tore my hair out. Changing user permissions didn't do anything good. This has finally worked for me but used the command on my static folder instead of /var/ww/! Thanks! – Majte Jan 09 '22 at 21:43
9

After digging into very useful answers decided to collect everything related to permissions as a recipe. Specifically, the simplest solution with maximal security (=minimal permissions).

  1. Suppose we deploy the site as user admin, that is, she owns site dir and everything within. We do not want to run nginx as this user (too many permissions). It's OK for testing, not for prod.
  2. By default Nginx runs workers as a user nginx, that is, config contains line user nginx
  3. By default user nginx is in the group with the same name: nginx.
  4. We want to give minimal permissions to user nginx without changing file ownership. This seems to be the most secure of naive options.
  5. In order to serve static files, the minimal required permissions in the folders hierarchy (see the group permissions) should be like this (use the command namei -l /home/admin/WebProject/site/static/hmenu.css):

    dr-xr-xr-x root root /
    drwxr-xr-x root root home
    drwxr-x--- admin nginx admin
    drwx--x--- admin nginx WebProject
    drwx--x--- admin nginx site
    drwx--x--- admin nginx static
    -rwxr----- admin nginx hmenu.css

  6. Next, how to get this beautiful picture? To change group ownership for dirs, we first apply sudo chown :nginx /home/admin/WebProject/site/static and then repeat the command stripping dirs from the right one-by-one.

  7. To change permissions for dirs, we apply sudo chmod g+x /home/admin/WebProject/site/static and again strip dirs.

  8. Change group for the files in the /static dir: sudo chown -R :nginx /home/admin/WebProject/site/static

  9. Finally, change permissions for the files in the /static dir: sudo chmod g+r /home/admin/WebProject/site/static/*

(Of course one can create a dedicated group and change the user name, but this would obscure the narration with unimportant details.)

4

Setting user root in nginx can be really dangerous. Having to set permissions to all file hierarchy can be cumbersome (imagine the folder's full path is under more than 10 subfolders).

What I'd do is to mirror the folder you want to share, under /usr/share/nginx/any_folder_name with permissions for nginx's configured user (usually www-data). That you can do with bindfs.

In your case I would do:

sudo bindfs -u www-data -g www-data /root/downloads/boxes/ /usr/share/nginx/root_boxes

It will mount /root/downloads/boxes into /usr/share/nginx/root_boxes with all permissions for user www-data. Now you set that path in your location block config

location /static {
   autoindex on;
   alias /usr/share/nginx/root_boxes/;
  }
roj4s
  • 251
  • 2
  • 8
  • 1
    after testing different setups with chmod etc. this looked to me the best suitable (and most safe) way. finally worked for me. Thanks man! :) – Phil Jul 19 '20 at 10:22
  • 1
    This method was helpful for me. I changed ownership and permissions for my static folder, but apparently my working path didn't allow Nginx to access. I did'n want to give to www-data user-group permissions all across the root directory upwards. Nice solution. – RicHincapie Nov 30 '20 at 23:54
4

Try the accepted answer by @gitaarik, and if it still gives 403 Forbidden or 404 Not Found and your location target is / read on.

I also experienced this issue, but none of the permission changes mentioned above solved my problem. It was solved by adding the root directive because I was defining the root location (/) and accidentally used the alias directive when I should have used the root directive.

The configuration is accepted, but gives 403 Forbidden, or 404 Not Found if auto-indexing is enabled for /:

location / {
  alias /my/path/;
  index index.html;
}

Correct definition:

location / {
  root /my/path/;
  index index.html;
}
Jeremy
  • 843
  • 11
  • 16
2

You can just do like what is did:

CentOS / Fedora

sudo usermod -a -G your_user_name nginx

chmod 710 /home/your_user_name 

Ubuntu / Debian

sudo usermod -a -G your_user_name www-data

sudo chown -R :www-data /path/to/your/static_folder

And in your nginx file that serve your site make sure that your location for static is like this:

location /static/ {
        root /path/to/your/static_folder;
    }
Dhia Shalabi
  • 1,332
  • 1
  • 13
  • 29
1

To those that got locked out of ssh by following @sandes 's answer for Ubuntu. You need to somehow regain access as user with permissions and run this command

sudo gpasswd -d www-data your_user

This removes the www-data user from the group and allows you to log back in.

0

I bang my head on this 403 problem for quite some time. I'm using CentOS from DigitalOcean.

I thought to fix the problem was just to set SELINUX=disabled in /etc/selinux/config but I was wrong. Somehow, I screwed my droplet.

This works for me! sudo chown nginx:nginx /var/www/mydir

EPS
  • 1
  • 1
0

My nginx is run as nginx user and nginx group, but add nginx group to public folder not work for me.

I check the permission as a nginx user.

su nginx -s /bin/bash

I found the I need to add the group for the full path. My path is start at /root, so I need to do following:

chown -R :nginx /root
lingceng
  • 2,415
  • 1
  • 18
  • 19
0

The best option to this is puting your static in /var/www/static/

and changing your /etc/nginx/sites-available/projectname to

 location /static/ {
        root /var/www;
    }

or

 location /static/ {
        alias /var/www/static;
    }
Martins
  • 1,130
  • 10
  • 26