0

While trying to deploy my app to Digital ocean I did everything according to this tutorial: How To Deploy a Local Django App to a VPS.

While Gunicorn is working perfectly and http://95.85.34.87:8001/ opens my app, Nginx, however, does not work, http://95.85.34.87 or http://95.85.34.87/static causes a 502 error.

Nginx log says, that :

2014/04/19 02:43:52 [error] 896#0: *62 connect() failed (111: Connection refused) while connecting to upstream, client: 78.62.163.9, server: 95.85.34.87, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8001/", host: "95.85.34.87"

My nginx configuration file looks like this:

server { 
listen 80 default_server; 
listen [::]:80 default_server ipv6only=on; 
server_name 95.85.34.87;

access_log off;

location /static/ { 
alias /opt/myenv/static/; 
}

location / { 
proxy_pass http://127.0.0.1:8001; 
proxy_set_header X-Forwarded-Host $server_name; 
proxy_set_header X-Real-IP $remote_addr; 
add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"'; 
}

In Django.settings I have ALLOWED_HOSTS set to '[*]'

Nginx is listening to port 80:

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      894/nginx

tcp6       0      0 :::80                   :::*                    LISTEN      894/nginx 

I think that the point is that Nginx does not point user to Gunicorn for some reason...

EDIT: I changed the proxy_pass http://127.0.0.1:8001; line under location / to my servers IP address (instead of loccalhost) and everything worked. I am not sure if it's good decission or not.

Eimantas
  • 429
  • 1
  • 4
  • 22

1 Answers1

0

I see the instructions tell you to use this to start Gunicorn:

$ gunicorn_django --bind yourdomainorip.com:8001

If you start it like this then Gunicorn will listen only on the interface that is bound to yourdomainorip.com. So it won't listen on the loopback interface and won't receive anything sent to 127.0.0.1. Rather than changing nginx's configuration like you mention in your edit, you should do:

$ gunicorn_django --bind localhost:8001

This would cause Gunicorn to listen on the loopback. This is preferable because if you bind Gunicorn to an external interface people can access it without going through nginx.

With this setup the interaction between nginx and your Django app is like this:

  1. nginx is the entry point for all HTTP requests. It listens on 95.85.34.87:80.

  2. When an request is made to a URL that should be forwarded to your application, nginx forwards it by connecting on localhost:8001 (same as 127.0.0.1:8001).

  3. Your Django application is listening on localhost:8001 to receive forwards from nginx.

By the way, gunicorn_django is deprecated.

And another thing: don't set ALLOWED_HOSTS to serve all domains. If you do so you are opening yourself to cache poisoning. Set it only to the list of domains that your Django project is meant to serve. See the documentation for details.

Community
  • 1
  • 1
Louis
  • 146,715
  • 28
  • 274
  • 320
  • Thank you for pointing that out. You was right - the Nginx now serves my static files, but I didnt notice that I am unable to write anything into the server, I am getting the same "connection refused while connecting to upstream" error... Do you have any idea what might happen there? – Eimantas Apr 19 '14 at 11:28
  • I don't know what you mean by "*write* anything into the server". The first thing I'd try is a `GET` query. – Louis Apr 19 '14 at 11:30
  • Sorry for being unclear. Now I tried to make a request POST with data (via Ajax to one of my pages), but I am getting a connection refused error. Since Gunicorn is serving my App and there's no log entries regarding the POST error at nginx's error.log I assume that something is wrong with gunicorn. The get queries from Nginx works fine, because my static files are served... I will try to find out what happens at the background when request POST is executed. I guess it is related to gunicorn somehow – Eimantas Apr 19 '14 at 11:42
  • When I suggested I `GET` I meant a `GET` that will be routed to Gunicorn. Gunicorn should have a log file somewhere. What do you see in it? – Louis Apr 19 '14 at 11:48
  • In Django admin 'Sites' settigns I had an old domain entry 'http://95.85.34.87:8001/' left so I tried to change it to my new domain 'http://lynxapp.io' and everything works now. I think that your answer to bind gunicorn to localhost solved the problem, thank you - now there is no "connection refused" error. – Eimantas Apr 19 '14 at 11:55
  • I surely have to read more about the 'localhost' thing, because I am not sure I fully understand how gunicorn can 'serve my app from localhost' though :) – Eimantas Apr 19 '14 at 11:57
  • I've updated my answer with an explanation of the interaction between nginx and Gunicorn. I've also added a note regarding `ALLOWED_HOSTS`. **You've opened a security hole while testing.** Please close it. – Louis Apr 19 '14 at 12:05