Nginx Gunicorn Django -- upstream prematurely closed connection Error - django

I am pretty new to NGINX, GUNICORN, DJANGO setup. I am using supervisor between nginx, gunicorn. Without NGINX, setup works well with supervisor and gunicorn and I can see the result through my server IP. But when i am using nginx to serve the requests, the error "upstream prematurely closed connection while reading response header from upstream" occurs. please anyone help me in this?
Supervisor command I am using:
sudo /path/to/gunicorn/gunicorn -k gevent --workers 4 --bind unix:/tmp/gunicorn.sock --chdir /path/to/application wsgi:application --timeout 120
below is the nginx.conf i am currently using and it is working as expected. but i am not sure it is up to the mark. Please look into this. Thanks.
==============Update=============
upstream xxxx {
server unix:/tmp/gunicorn.sock;
}
server{
listen 80;
listen [::]:80;
server_name xxx.in www.xxx.in;
return 301 https://$host$request_uri;
}
server{
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/xxx.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.in/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root path/to/project;
}
location / {
include uwsgi_params;
proxy_pass http://unix:/tmp/gunicorn.sock;
}
}

Please check this steps:
First of all be sure that gunicorn is creating .sock file running with supervisor. You can ensure it with
$sudo supervisorctl status <name-of-supervisor-task-for-it>
(check if service is RUNNING)
$ls /tmp
(There should be a gunicorn.sock file existing there)
Also be aware of user that you are assigning to supervisor config. In this case you don't need to set root before command, just give privilege of root user to config file. like this:
[program:myprogram]
command=/path/to/gunicorn/gunicorn -k gevent --workers 4 --bind unix:/tmp/gunicorn.sock --chdir /path/to/application wsgi:application --timeout 120
<other commands>
user=root
And you nginx config should should look like this:
upstream django {
server unix://tmp/gunicorn.sock;
}
server {
listen 80;
server_name <your_app_domain_here>;
location / {
include uwsgi_params;
proxy_pass http://django/;
}

Related

Gunicorn, nginx, django, inside of a docker container. Gunicorn successfully runs on port 80 but nginx fails

I'm trying to set up a simple blogging site that I wrote using the django framework. The website works except that it isn't serving static files. I imagine that's because nginx isn't running. However, when I configure it to run on any port other than 80 I get the following error:
nginx: [emerg] bind() to 172.17.0.1:9000 failed (99: Cannot assign requested address)
When I run it on a port that is already being used by gunicorn I get the following error:
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
My nginx configuration file is as follows:
upstream django {
server 127.0.0.1:8080;
}
server {
listen 172.17.0.1:9000;
server_name my.broken.blog;
index index.html;
location = /assets/favicon.ico { access_log off; log_not_found off; }
location /assets {
autoindex on;
alias /var/www/html/mysite/assets;
}
location / {
autoindex on;
uwsgi_pass unix:///run/uwsgi/django/socket;
include /var/www/html/mysite/mysite/uwsgi_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
But if I run nginx without starting guincorn it runs properly but I get a 403 forbidden error.
Going with the suggested answer I don't get any errors, but the site is returning 403 forbidden and doesn't present the part of the website gunicorn is supposed to deliver.
Configure Nginx and Gunicorn in following way to make it work,
Use unix socket to comminicate between nginx and gunicron rather than running gunicorn in some port
Create a unit file for gunicorn in the following location
sudo nano /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=root
Group=nginx
WorkingDirectory=/path-to-project-folder
ExecStart=/<path-to-env>/bin/gunicorn --workers 9 --bind unix:/path-to-sockfile/<blog>.sock app.wsgi:application
Restart=on-failure
[Install]
WantedBy=multi-user.target
Then start and enable gunicorn service
It will generate a sock file in the specified path.
sudo systemctl enable gunicorn
sudo systemctl start gunicorn
Note: Choose the suitable number of workers for gunicorn, can sepecify log files as follows
ExecStart=//bin/gunicorn --workers 9 --bind unix:/path-to-sockfile/.sock app.wsgi:application --access-logfile /var/log/gunicorn/access.log --error-logfile /var/log/error.log
create a new configuration file specific to the project in /etct/nginx rather than edit the default nginx.conf
nano /etc/nginx/blog.conf
and add the following lines ( can also add the file in /etc/nginx/default.d/)
server {
listen 80;
server_name 172.17.0.1; # your Ip
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /path-to-static-folder;
}
location /media/ {
root /path-to-media-folder;
}
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/path-to-sock-file/<blog-sock-file>.sock;
}
}
include the /etc/nginx/blog.conf to nignx.conf
---------
----------
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/blog.conf; # the new conf file added
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
------
-------
run sudo nginx -t // to check for errors in nginx configuration.
run sudo systemctl nginx restart
refer: https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04

Connection betweetn docker containers

I am struggling with the connection of nginx and django (docker container)
My strategy is like this ,
run uwsgi http option and 8001 port. (not socket)
uwsgi --http :8001 --module myapp.wsgi --py-autoreload 1 --logto /tmp/mylog.log
then I confirmed wget http://127.0.0.1:8001 works.
but from, nginx, It can't connect somehow. (111: Connection refused) error
However from nginx wget http://django:8001 works.
How can I connect between containars
upstream django {
ip_hash;
server 127.0.0.1:8001;
}
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
location / {
proxy_pass http://127.0.0.1:8001/;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
I am trying this config but, if I try this, my container doesn't launch.
log is like this
2020/03/24 08:24:04 [emerg] 1#1: upstream "django" may not have port 8001 in /etc/nginx/conf.d/app_nginx.conf:16
upstream django {
ip_hash;
server django:8001;
}
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
location / {
proxy_pass http://django:8001/;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
my docker compose is very simple...
nginx:
image: nginx:1.13
container_name: nginx
ports:
- "8000:8000"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./nginx/static:/static
depends_on:
- django
Finally thanks to helps. my server works. final conf is like this below.
remove upstream and use name 'django' instead of 127.0.0.1
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location /static {
alias /static;
}
location / {
proxy_pass http://django:8001/;
include /etc/nginx/uwsgi_params;
}
}
server_tokens off;
If they run in different containers, 127.0.0.1 is not the correct IP; use the name of the other container, e.g.
proxy_pass http://django:8001;
so Docker's internal DNS can route things.

HTTP request 408 error(Client request timeout) over mobile network. Django + Gunicorn + Nginx

I have faced with strange issue. My API has endpoint on which i am using PATCH(tried also PUT and POST - same result) to send json with jsonarray(request body size typically is 40KB) from mobile phone. When i am doing this using Wi-Fi - all works fine. But if i am using mobile network, i am facing with SocketConnection Timeout(in Retrofit/Kotlin) with some phones(iOS works perfect).
From nginx access.log :
domain - - [21/Nov/2017:16:33:01 +0000] "PATCH /endpoint/ HTTP/1.1" 408 0 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Nexus 5 Build/M4B30Z)"
Nginx config :
server {
listen port;
server_name domain;
client_max_body_size 32m;
proxy_connect_timeout 75s;
proxy_read_timeout 300s;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/user/apps/api;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/user/apps/api/api.sock;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
Gunicorn config :
respawn
setuid root
setgid www-data
chdir /home/user/apps/api
exec /home/user/virtualenvs/apienv/bin/gunicorn --workers 3 --timeout=90 --bind unix://api.sock api.wsgi:application
The problem was in network connection. We changed location of our clouds from Frankfurt to Amsterdam and now all works perfect

How can I test if gunicorn is working and communicating with nginx?

I'm deploying my first attempt at using django+gunicorn+nginx.
I have django working (curl -XGET http://127.0.0.0.1:8000 works fine if I run the development server).
I have nginx working for static content (for example I can retrieve http://example.com/static/my_pic.png in my browser).
I'm not getting any wsgi content from my website, and I haven't been able to find a good troubleshooting guide (does it just work for everyone else?!). I start gunicorn using supervisor, which reports that it is indeed running:
(in shell:)
supervisorctl status my_app
my_app RUNNING pid 1002, uptime 0:29:51
Here's the boilerplate script I used to start it:
#!/bin/bash
#script variables
NAME="gunicorn_myapp" # Name of process
DJANGODIR=/webapps/www/my_project # Django project directory
SOCKFILE=/webapps/www/run/gunicorn.sock # communicte using this socket
USER=app_user # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=my_project.settings # settings file
DJANGO_WSGI_MODULE=my_project.wsgi # WSGI module name
# 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
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE
Here's the (condensed) nginx config file:
upstream my_server {
server unix:/webapps/www/run/gunicorn.sock fail_timeout=10s;
}
server {
listen 80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
client_max_body_size 4G;
access_log /webapps/www/logs/nginx-access.log;
error_log /webapps/www/logs/nginx-error.log;
location /favicon.ico { access_log off; log_not_found off; }
location /static/ {
autoindex on;
alias /webapps/www/my_project/my_app/static/;
}
location /media/ {
autoindex on;
alias /webapps/www/my_project/my_app/media/;
}
location / {
proxy_pass http://my_server;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://example.com;
break;
}
}
location /robots.txt {
alias /webapps/www/my_project/my_app/static/robots.txt ;
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/www/my_project/my_app/static/;
}
}
So: gunicorn is running, nginx is running ... what tests (and how?) should I perform to determine if gunicorn is doing the wsgi stuff properly (and if nginx is proxying the said stuff through correctly)?
Edit: I've narrowed the problem down to the communication between gunicorn and nginx via the unix socket. If I change the $SOCKFILE to be bound to 0.0.0.0:80 and stop nginx, then the app's pages are served from my website. The bad news is that the socket file strings are exactly the same between the two conf files, so I don't know why they aren't communicating. I suppose this means nginx isn't correctly fetching and passing the data through then?
Go to project directory :
cd projectname
gunicorn --log-file=- projectname.wsgi:application
and
sudo systemctl status gunicorn

nginx : How to make nginx point to django

Iam new to nginx.
I have configured nginx,gunicorn and django.
when i start nginx, it gives an error as,
404 Not Found
nginx/1.1.19
as it is not pointing to django.
Now i need to point out nginx to django(using gunicorn as middleware) in conf file using location or root.
Can anyone tell me how to point out nginx to django.
Thank you
I've got many Apps running like this:
server {
# listen, statics, media, etc
location / {
proxy_pass http://127.0.0.1:8000; # Gunicorn Server
}
}
First, you need to actually have the gunicorn process running. Do this either manually, or ideally using a process management tool such as supervisord. Here's a sample supervisord script that runs a gunicorn process on a django project:
[program:example]
user=ubuntu
group=ubuntu
directory=/home/ubuntu/dev/example
command=python manage.py run_gunicorn -c gunicorn_config.py
autostart=true
autorestart=true
redirect_stderr=True
Then you need a proper nginx conf. Here's a minimal sample based off a site running in production:
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
server_name example.com;
location / {
proxy_pass http://localhost:8000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# use this if you're serving static assets locally
location /static/ { # make sure this is your STATIC_ROOT
alias /home/ubuntu/dev/example/static/;
access_log off;
}
}