1

I've spent several hours on StackOverflow and other tutorials but I can't figure out why nginx is returning a 403 Forbidden when I navigate to localhost.

Here is my gunicorn start script (located in app root):

#!/bin/bash
# http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/

NAME="mbta_django_gunicorn"
SOCKFILE=run/gunicorn.sock 
USER=alexpetralia                                        # the user to run as
GROUP=alexpetralia                                     # the group to run as
NUM_WORKERS=5
DJANGO_SETTINGS_MODULE=mbta_django.settings
DJANGO_WSGI_MODULE=mbta_django.wsgi

echo "Starting $NAME"

# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

# Start Django Unicorn
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  # --bind=localhost:8000 \
  --bind=unix:$SOCKFILE \
  --log-level=debug \
  --log-file=- \
  --reload

Here is my nginx.conf:

user alexpetralia alexpetralia; # www-data
worker_processes 4;
pid /run/nginx.pid;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

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

    gzip on;
    gzip_disable "msie6";

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Here is my app-specific nginxconf file located under sites-available (and linked in sites-enabled):

upstream mbta_django_server {
    server unix:/home/alexpetralia/Projects/mbta_django/run/gunicorn.sock fail_timeout=0;
}

server {
    listen 80;
    client_max_body_size 4G;
    keepalive_timeout 5;
    root /home/alexpetralia/Projects/mbta_django/static/;

    location /static/ {
        autoindex on;
        alias /home/alexpetralia/Projects/mbta_django/static/;
    }    
}

My supervisor settings for running gunicorn (which changes the PATH in order to use the virtualenv):

[program:mbta_gunicorn]
command=/home/alexpetralia/Projects/mbta_django/gunicorn_ctl
stdout_logfile=/home/alexpetralia/Projects/mbta_django/logs/mbta_gunicorn.log
stderr_logfile=/home/alexpetralia/Projects/mbta_django/logs/mbta_gunicorn.log
redirect_stderr=true
autorestart=true
stopsignal=KILL
killasgroup=true
stopasgroup=true
environment=PATH="/home/alexpetralia/Projects/mbta_django/venv/bin"
directory=/home/alexpetralia/Projects/mbta_django

This strongly feels like a permissions issue, but I've already used chmod -R 775 mbta_django on my webapp's root folder. I am hesitant to chown it. I don't understand why, if gunicorn is loaded with the right user, as is nginx, then there shouldn't be a permissions issue.

Perhaps this has something to do with gunicorn, rather than nginx? I find it weird that I can access my app (without static files) if gunicorn is running, even if it is bound to Unix socket and not to 127.0.0.1:8000.

Thanks.

UPDATE

Nginx error log (sample, it's pretty much just this):

2016/01/18 16:42:40 [error] 20773#0: *5 directory index of "/home/alexpetralia/Projects/mbta_django/static/" is forbidden, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "localhost"
2016/01/18 16:42:40 [error] 20773#0: *5 directory index of "/home/alexpetralia/Projects/mbta_django/static/" is forbidden, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", host: "localhost"

Gunicorn error log (sample, the dirname part is a command that comes frmo the tutorial here):

Starting mbta_django_gunicorn
/home/alexpetralia/Projects/mbta_django/gunicorn_ctl: line 20: dirname: command not found
[2016-01-18 18:03:08 +0000] [1996] [INFO] Starting gunicorn 19.4.5
[2016-01-18 18:03:08 +0000] [1996] [INFO] Listening at: http://127.0.0.1:8000 (1996)
[2016-01-18 18:03:08 +0000] [1996] [INFO] Using worker: sync
[2016-01-18 18:03:08 +0000] [2008] [INFO] Booting worker with pid: 2008
[2016-01-18 18:03:08 +0000] [2009] [INFO] Booting worker with pid: 2009
[2016-01-18 18:03:08 +0000] [2016] [INFO] Booting worker with pid: 2016
[2016-01-18 18:03:08 +0000] [2019] [INFO] Booting worker with pid: 2019
[2016-01-18 18:03:08 +0000] [2022] [INFO] Booting worker with pid: 2022

Ownership of static folder:

alexpetralia@linux-box:~$ namei -ov /home/alexpetralia/Projects/mbta_django/static
f: /home/alexpetralia/Projects/mbta_django/static
d root         root         /
d root         root         home
d alexpetralia alexpetralia alexpetralia
d alexpetralia alexpetralia Projects
d alexpetralia alexpetralia mbta_django
d alexpetralia alexpetralia static

Permissions on static folder:

drwxr-xr-x  6 alexpetralia alexpetralia 4096 Jan  8 12:43 static

Gunicorn process:

alexpetralia@linux-box:~/Projects/mbta_django$ ps aux | grep gunicorn
root      1942  0.0  0.4  57416 15972 ?        S    18:52   0:00 /home/alexpetralia/Projects/mbta_django/venv/bin/python /home/alexpetralia/Projects/mbta_django/venv/bin/gunicorn mbta_django.wsgi:application --name mbta_django_gunicorn --workers 5 --user=alexpetralia --group=alexpetralia
alexpet+  1951  0.0  0.8 147648 32100 ?        S    18:52   0:00 /home/alexpetralia/Projects/mbta_django/venv/bin/python /home/alexpetralia/Projects/mbta_django/venv/bin/gunicorn mbta_django.wsgi:application --name mbta_django_gunicorn --workers 5 --user=alexpetralia --group=alexpetralia
alexpet+  1954  0.0  0.8 147660 32100 ?        S    18:52   0:00 /home/alexpetralia/Projects/mbta_django/venv/bin/python /home/alexpetralia/Projects/mbta_django/venv/bin/gunicorn mbta_django.wsgi:application --name mbta_django_gunicorn --workers 5 --user=alexpetralia --group=alexpetralia
alexpet+  1957  0.2  1.6 226280 63612 ?        S    18:52   0:01 /home/alexpetralia/Projects/mbta_django/venv/bin/python /home/alexpetralia/Projects/mbta_django/venv/bin/gunicorn mbta_django.wsgi:application --name mbta_django_gunicorn --workers 5 --user=alexpetralia --group=alexpetralia
alexpet+  1964  0.1  0.8 147676 32100 ?        S    18:52   0:00 /home/alexpetralia/Projects/mbta_django/venv/bin/python /home/alexpetralia/Projects/mbta_django/venv/bin/gunicorn mbta_django.wsgi:application --name mbta_django_gunicorn --workers 5 --user=alexpetralia --group=alexpetralia
alexpet+  1975  0.0  0.8 147688 32108 ?        S    18:52   0:00 /home/alexpetralia/Projects/mbta_django/venv/bin/python /home/alexpetralia/Projects/mbta_django/venv/bin/gunicorn mbta_django.wsgi:application --name mbta_django_gunicorn --workers 5 --user=alexpetralia --group=alexpetralia

Nginx process:

alexpetralia@linux-box:~/Projects/mbta_django$ ps aux | grep nginx
root      1362  0.0  0.0  85892  2712 ?        Ss   18:52   0:00 nginx: master process /usr/sbin/nginx
alexpet+  1363  0.0  0.0  86172  3404 ?        S    18:52   0:00 nginx: worker process
alexpet+  1364  0.0  0.0  86172  3404 ?        S    18:52   0:00 nginx: worker process
alexpet+  1365  0.0  0.0  86172  3404 ?        S    18:52   0:00 nginx: worker process
alexpet+  1366  0.0  0.0  86172  3404 ?        S    18:52   0:00 nginx: worker process
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Alex Petralia
  • 1,730
  • 1
  • 22
  • 39
  • 1
    What do your nginx and gunicorn logs say? `/var/log/nginx/nginx_error.log` and `/home/alexpetralia/Projects/mbta_django/logs/mbta_gunicorn.log` – YPCrumble Jan 18 '16 at 23:06
  • @YPCrumble Updated with error logs – Alex Petralia Jan 18 '16 at 23:14
  • 1
    What is the owner and permissions on `/home/alexpetralia/Projects/mbta_django/static/` – YPCrumble Jan 18 '16 at 23:25
  • @YPCrumble Updated with ownership/permissions; yes sorry I pasted the wrong thing. I updated it now. – Alex Petralia Jan 18 '16 at 23:56
  • That looks like permissions for `/scraper/` no? – YPCrumble Jan 18 '16 at 23:57
  • The first thing to try is currently `/static/` looks to be 755 permissions, not 775...I don't think this is the solution but it's weird when you've recursively set 755 permissions for this to be the case. – YPCrumble Jan 19 '16 at 00:03
  • I updated it so now it is: `drwxrwxr-x 6 alexpetralia alexpetralia 4096 Jan 8 12:43 static`. I restarted the nginx server `sudo service nginx restart` but still getting the 403 page. – Alex Petralia Jan 19 '16 at 00:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101024/discussion-between-ypcrumble-and-alex-petralia). – YPCrumble Jan 19 '16 at 00:15
  • Possible duplicate of [Nginx 403 error: directory index of \[folder\] is forbidden](http://stackoverflow.com/questions/19285355/nginx-403-error-directory-index-of-folder-is-forbidden) – Mark Stosberg Jan 19 '16 at 01:30
  • The Nginx configuration does not indicate that any traffic is actually forwarded to gunicorn-- "upstream" is defined but not used-- so this question is essentially a dupe of the more generic question abou [directory forbidden errors with Nginx](http://stackoverflow.com/questions/19285355/nginx-403-error-directory-index-of-folder-is-forbidden). – Mark Stosberg Jan 19 '16 at 01:32
  • Thanks for the link. I looked at it but I didn't see how to actually forward to gunicorn (besides just defining upstream). Is there something I need in the `server` block to forward to the upstream socket? – Alex Petralia Jan 19 '16 at 01:44

2 Answers2

0

Run the command "namei -l /home/alexpetralia/Projects/mbta_django/static" and see what your rights look like for all of the other parent directories.

AFAIK, Your user must have read permissions for the static directory and must have execute permissions in /, /home/, /home/alexpetralia, /home/alexpetralia/Projects/mbta_django, /home/alexpetralia/Projects/mbta_django/static.

You only included the permissions for /home/alexpetralia/Projects/mbta_django/static

ref: http://nginxlibrary.com/403-forbidden-error/

  • `f: /home/alexpetralia/Projects/mbta_django/static \ drwxr-xr-x root root / \ drwxr-xr-x root root home \ drwxr-xr-x alexpetralia alexpetralia alexpetralia \ drwxrwxr-x alexpetralia alexpetralia Projects \ drwxrwxr-x alexpetralia alexpetralia mbta_django \ drwxrwxr-x alexpetralia alexpetralia static` I believe it has all the correct permissions? – Alex Petralia Jan 19 '16 at 13:01
0

I solved this by switching to uWSGI. The process was much simpler. User:group in main nginx conf is alexpetralia alexpetralia (ie. /etc/nginx/nginx.conf/, whereas the below nginx conf is in /etc/nginx/sites-enabled/mbta_django).

App-specific nginx conf:

upstream mbta_django_uwsgi {
    server unix:///home/alexpetralia/Projects/mbta_django/run/uwsgi.sock;
}

server {

    listen      80;
    server_name 127.0.0.1;   # or FQDN
    charset     utf-8;

    location /static {
            alias /home/alexpetralia/Projects/mbta_django/static;
    }

    location / {
        uwsgi_pass  unix:/home/alexpetralia/Projects/mbta_django/run/uwsgi.sock;
        include     /etc/nginx/uwsgi_params;
    }
}

uWSGI command:

uwsgi --chdir=/home/alexpetralia/Projects/mbta_django --wsgi-file=mbta_django/wsgi.py --processes=5 --socket run/uwsgi.sock --py-autoreload=3

And finally collecting static from all my apps under root because app-specific css files were not loading (in django settings.py, I have STATIC_ROOT = os.path.join(BASE_DIR, "static")):

./manage.py collectstatic in the django root folder

Alex Petralia
  • 1,730
  • 1
  • 22
  • 39