nginxpermissionsgunicornmanage.pydjango-commands

Python Django call_command permissions gunicorn+nginx


Problem

Receive 502 bad gateway when i try to execute a django management command via gunicorn

Logic Line

I think the problem is about permissions, something like gunicorn is not able call the command. I say that because i can run it locally where i don't use gunicorn.

I can run it in these two methods:

PS. If i remove call_command it returns 200 ok, so, it seems like the core problem is the execution of this command.

The code

class TestCommandView(views.APIView):
    def post(self, request):
        id = request.data['id']

        try:
            call_command('command_name', target_id=id)
            return Response({"status": "success"})
        except Exception as error:
            return Response({"status": "error: " + str(error) })

Return sample

<html>
    <head>
        <title>502 Bad Gateway</title>
    </head>
    <body bgcolor="white">
        <center>
            <h1>502 Bad Gateway</h1>
        </center>
        <hr>
        <center>nginx/1.14.0 (Ubuntu)</center>
    </body>
</html>

Gunicorn Conf

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=ubuntu
Group=www-data
RuntimeDirectory=gunicorn
WorkingDirectory=/var/www/project
ExecStart=/var/www/project/venv/bin/ddtrace-run /var/www/project/venv/bin/guni$
Environment="DJANGO_SETTINGS_MODULE=project.settings.prod"

[Install]
WantedBy=multi-user.target

Nginx Log error

2019/03/13 13:43:38 [error] 27552#27552: *3128 upstream prematurely closed connection while reading response header from upstream, client: IP, server: api.project.com, request: "POST /api/project/endpoint/ HTTP/1.1", upstream: "http://unix:/tmp/project.sock:/api/project/endpoint/", host: "api.project.com"

What i've tried


Solution

  • I realized it was a problem of timeout

    The default timeout of gunicorn is 30 seconds based on its documentation.

    Doc. Workers silent for more than this many seconds are killed and restarted.

    My request get more than 30 seconds, so, gunicorn killed the process and nginx returned 502.

    Solution

    Gunicorn

    I added the timeout option to gunicorn ExecStart line

    --timeout 300

        ExecStart=/var/www/project/venv/bin/ddtrace-run /var/www/project/venv/bin/gunicorn --bind unix:/tmp/project.sock project.wsgi:application --access-logfile /home/ubuntu/gunicorn.log --error-logfile /home/ubuntu/gunicorn.error.log --timeout 720 --workers 3
    

    Nginx

    Added this option to HTTP part of nginx conf

    proxy_read_timeout 300s;
    

    Restarted nginx and gunicorn and that's worked like a charm