1
votes

I followed this tutorial : http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/

My directory structure is quite the same:

-rw-r--r-- 1 django webapps    0 Nov 30 15:58 access.log
drwxr-xr-x 3 django webapps 4096 Nov 30 17:27 bin
-rw-r--r-- 1 django webapps 6450 Nov 30 15:58 error.log
drwxr-xr-x 2 django webapps 4096 Nov 30 15:58 gunicorn
drwxr-xr-x 2 django webapps 4096 Nov 30 16:10 include
drwxr-xr-x 3 django webapps 4096 Nov 30 16:10 lib
lrwxrwxrwx 1 django webapps    3 Nov 30 16:10 lib64 -> lib
drwxr-xr-x 2 django webapps 4096 Nov 30 17:12 logs
drwxr-xr-x 5 django webapps 4096 Nov 30 13:36 narcisse
-rw-r--r-- 1 django webapps   59 Nov 30 16:11 pip-selfcheck.json
-rw-r--r-- 1 django webapps   75 Nov 30 16:10 pyvenv.cfg
-rw-r--r-- 1 django webapps   85 Nov 30 15:50 README.md
drwxrwxrwx 2 django webapps 4096 Nov 30 17:51 run

I have a /etc/supervisor/conf.d/filename that looks like this:

[program:site]
command = /var/www/site/bin/gunicorn_start -user=django
user = django
stdout_logfile = /var/www/site/logs/gunicorn_supervisor.log
redirect_stderr = true

My gunicorn_start is located inside /var/www/site/bin ()and looks like this:

NAME="api"
DJANGODIR=/var/www/site/site
SOCKFILE=/var/www/site/run/gunicorn.sock
USER=django
GROUP=webapps
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=api.settings
DJANGO_WSGI_MODULE=api.wsgi

echo "Starting $NAME as `whoami`"

# Activate the virtual environment
cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

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

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

And finally the nginx conf file:

upstream your-gunicorn {
    server unix:/var/www/site/run/gunicorn.sock fail_timeout=0;
}

server {
    listen 80 default;
    client_max_body_size 4G;
    server_name <ip_address>;
    keepalive_timeout 70;
    access_log /var/log/nginx/site.access_log;
    error_log /var/log/nginx/site.error_log;
    root /var/www/site/;

    location /static/ {
        autoindex on;
        alias /var/www/site/site/static/;
        expires 1M;
        access_log off;
        add_header Cache-Control "public";
        proxy_ignore_headers "Set-Cookie";
    }

    location @proxy_to_app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass   http://127.0.0.1;
    }

    location / {
        try_files $uri @proxy_to_app;
    }
}

I have the feeling I have tried every keyboard combinations. Cannot find what is wrong.

I keep getting this Operation Not permitted error inside gunicorn logs right after it starts.

Here is the full output:

    [2018-11-30 17:49:28 +0000] [13849] [INFO] Starting gunicorn 19.9.0
[2018-11-30 17:49:28 +0000] [13849] [DEBUG] Arbiter booted
[2018-11-30 17:49:28 +0000] [13849] [INFO] Listening at: unix:/var/www/site/run/gunicorn.sock (13849)
[2018-11-30 17:49:28 +0000] [13849] [INFO] Using worker: sync
[2018-11-30 17:49:28 +0000] [13923] [INFO] Booting worker with pid: 13923
[2018-11-30 17:49:28 +0000] [13923] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/var/www/site/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
    worker.init_process()
  File "/var/www/site/lib/python3.6/site-packages/gunicorn/workers/base.py", line 93, in init_process
    initgroups=self.cfg.initgroups)
  File "/var/www/site/lib/python3.6/site-packages/gunicorn/util.py", line 165, in set_owner_process
    os.setgid(gid)
PermissionError: [Errno 1] Operation not permitted

Thank you for your help.

Julien

1
Try removing the --USER and --GROUP flags from the gunicorn command. Supervisor should already have dropped privileges to the proper user. - Håken Lid
This specific bug is not related to the nginx config. But I don't understand what you are trying to do there. Why do you proxy pass to 127.0.0.1 instead of to the gunicorn upstream? - Håken Lid
Thank you for you help. Should I put the address of the server instead? - Julien Séveno-Piltant
@HåkenLid actually I see what you mean. I tried and now I get: Connection in use: ('127.0.0.1', 8000) again and again in logs. Nginx is using this address. Don't know why yet. - Julien Séveno-Piltant
If the address is in use, then you have something running on that port already. Possibly django runserver or another instance of gunicorn. Either shut down that server, or use a different port number. Or use the unix socket that's in the nginx config. - Håken Lid

1 Answers

2
votes

So, with the help of Haken Lid, I managed to fix my architecture.

Here is what I did:

Fixed nginx configuration file

upstream your-gunicorn {
    server unix:/var/www/site/run/gunicorn.sock fail_timeout=0;
}

Changed to:

upstream gunicorn_upstream {
    server unix:/var/www/site/run/gunicorn.sock fail_timeout=0;
}

And:

proxy_pass   http://127.0.0.1;

Changed to:

proxy_pass   http://gunicorn_upstream;

Fixed gunistart_start file

Last line changed from:

exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level=debug \
  --log-file=-

To:

exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --bind=unix:$SOCKFILE \
  --log-level=debug \
  --log-file=-

One of the error I made was actually quite silly because I commented the:

--user=$USER --group=$GROUP

of the line and this behave like the rest of the line was commented also. So basically, everything was in nginx configuration file.

Now fixed. Thanks

Julien