I encounterd an error when bound gunicorn listen address to my nginx server,here is the thing:
1.gunicorn_wsgi.py
import multiprocessing
bind="192.168.239.145:8080"(my nginx server ip address)
workers = multiprocessing.cpu_count() 2 + 1
2.nginx.conf
http{
upstream realservers{
server 192.168.239.146:8080;(my django and gunicorn address)
}
servr{
listen 80;
server_name example.com
location / {
proxy_pass http://realservers
}
}
}
when i ran gunicorn -c gunicorn-wsgi.py myproject.wsgi,error occur:
[2015-03-30 04:56:05 -0700] [38656] [INFO] Starting gunicorn 19.3.0
[2015-03-30 04:56:05 -0700] [38656] [ERROR] Invalid address: ('192.168.239.145', 8080)
I noticed that gunicorn has mentioned that if you are running nginx on a different host than gunicorn you need to tell gunicorn to trust the the x-forward-* headers sent by nginx.
If you are running Nginx on a different host than Gunicorn you need to
tell Gunicorn to trust the X-Forwarded-* headers sent by Nginx. By
default, Gunicorn will only trust these headers if the connection
comes from localhost. This is to prevent a malicious client from
forging these headers:
gunicorn -w 3 --forwarded-allow-ips="10.170.3.217,10.170.3.220" test:app
I followed what it said ,but still same error. And I change the address to 127.0.0.1 and 0.0.0.0 ,they work fine,but is not secure,How to configure it ,please help me !
It's obviously not your problem, but it is confusing that you're calling your configuration file "gunicon_wsgi.py". It's not your WSGI file. Call it "gunicorn_conf.py" or something similar.
Your problem is however that you have misunderstood what it means to bind to an IP address. You can't bind your gunicorn server to an IP address on a different machine; that makes no sense at all. And it's not "insecure" to bind to 0.0.0.0.
Related
I'm trying to deploy a Django app in a Ubuntu Server 18.04 using Nginx and Gunicorn. Every tool seems to work properly, at least, from logs and status points of view.
The point is that if I log into my server using SSH and try to use curl, gunicorn is able to see the request and handle it. However, if I write directly my IP, I get simply the typical Welcome to nginx home page and the request is completely invisible to gunicorn, so it seems nginx is unable to locate and pass the request to the gunicorn socket.
I'm using nginx 1.14.0, Django 2.2.1, Python 3.6.7, gunicorn 19.9.0 and PostgreSQL 10.8.
This is my nginx config
server {
listen 80;
server_name localhost;
location /favicon.ico { access_log off; log_not_found off; }
location /static/ {
alias /home/django/myproject/myproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
And these are my gunicorn.sock
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
and gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=django
Group=www-data
WorkingDirectory=/home/django/myproject/myproject
ExecStart=/home/django/myproject/myproject/myproject/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
MyProject.wsgi:application
[Install]
WantedBy=multi-user.target
I've been following this guide (https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04), where most of all has worked as expected, but with the difference that my project is not a completely new one as in the tutorial, but cloned from my git repo (however, it's tested and the code works properly)
I was expecting the Django admin to be accessible from my browser already with this config, but it's not. I try to access my IP from my browser and I get Welcome to nginx but also 404 if I visit /admin. In addition, the gunicorn logs shows no requests.
In the other hand, if I log through SSH into my server and I execute curl --unix-socket /run/gunicorn.sock localhost, I can see in the gunicorn logs the request done by curl.
Any help is welcome.. I've been here for hours and I'm not able to get even 1 request from outside the server.
PD: it's also not something related to the ports in the server, since when I access the root of my IP, I receive the nginx answer. It just seems like Nginx has no config at all.
in your nginx config, you should use your proper server_name instead of localhost
server_name mydomain.com;
If not, you will fall back to the default nginx server, which returns the "welcome to nginx" message. You can change which virtual server is default by changing the order of servers, removing the nginx default, or using the default_server parameter. You can also listen to multiple server names.
listen 80 default_server;
server_name mydomain.com localhost;
If the Host header field does not match a server name, NGINX Plus routes the request to the default server for the port on which the request arrived. The default server is the first one listed in the nginx.conf file, unless you include the default_server parameter to the listen directive to explicitly designate a server as the default.
https://docs.nginx.com/nginx/admin-guide/web-server/web-server/#setting-up-virtual-servers
Remember that you have to reload the nginx config after making changes. sudo nginx -s reload for example.
Finally, I've got it working properly. You were right about the config of nginx, although my real problem was not to delete/modify default config file for nginx in sites_enabled folder. Thus, when I was setting listen 80 default_server I got the following error
[emerg] 10619#0: a duplicate default server for 0.0.0.0:80 in
/etc/nginx/sites-enabled/mysite.com:4
Anyway, I had a problem with the static files which I still not knowing why it works like that. I needed to set DEBUG = True to be able to see static files of the admin module.
I'll keep on investigating the proper way of serving static files in production for the admin panel.
Thank you so much for the help!
I'm trying to put my django app online on a VPS. I tried following several different tutorials but I could not get it to work...
WHAT I'VE ACHIEVED ALREADY :
I got DJANGO's DevServ running on my VPS and I was able to browse my app using the VPS' IP address (the static files didn't correctly show up, error 404 104, and I only saw the HTML content without background/css or anything else).
I got NGINX running on my VPS and I was able to browse to its' default homepage (gunicorn was running at the time but the requests didn't get properly forwarded from NGINX to GUNICORN I believe).
I got GUNICORN running my app on my VPS with the command below.
Here's how I launch GUNICORN :
gunicorn MySite.wsgi:application
[2017-03-12 08:54:47 +0000] [1054] [INFO] Starting gunicorn 19.7.0
[2017-03-12 08:54:47 +0000] [1054] [INFO] Listening at: http://127.0.0.1:8000 (1054)
[2017-03-12 08:54:47 +0000] [1054] [INFO] Using worker: sync
[2017-03-12 08:54:47 +0000] [1059] [INFO] Booting worker with pid: 1059
And here is my NGINX configuration file which I named to match my domain name without the ".eu" (even though right now I'm trying to get it to work with the actual IP address, could this be the issue ?). I placed it in "/etc/nginx/sites-available" and made a symlink to the file in "/etc/nginx/sites-enabled" just like the tutorials said to:
#IP has been added to ALLOWED_HOSTS in settings.py
server {
listen 80;
server_name xxx.xxx.xx.xx;
charset utf-8;
access_log /var/log/nginx/MySite.access.log;
error_log /var/log/nginx/MySite.error.log;
#/static/ location as per my configuration and after running "manage.py collectstatic"
location /static/ {
alias /home/EveSite/static/;
}
# Forward HTTP requests to GUNICORN
location / {
proxy_pass http://127.0.0.1:8000;
}
}
I'm also having trouble linking my domain name to my VPS' IP but I will leave that for another question.
According to the tutorials I read, everything should be working now but I can only see NGINX's default homepage, no sign of my Django app altho GUNICORN says it is running.
Is there anything I am doing wrong here ? I know I'm probably missing something obvious.
I have a django app and running it with gunicorn on localhost:8000
I have configs for nginx to use it as a reverse proxy.
upstream django {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server localhost:8000 fail_timeout=0;
}
I know how to expose 80 port and run nginx in container, but I don't understand how to connect gunicorn running on localhost and nginx in container.
You'll need to utilize the IP of the bridge created by docker. There is a good article on Docker explaining this:
https://docs.docker.com/v1.6/articles/networking/
When Docker starts, it creates a virtual interface named docker0 on
the host machine. It randomly chooses an address and subnet from the
private range defined by RFC 1918 that are not in use on the host
machine, and assigns it to docker0.
If we take a look at the IP address assigned to docker0 (sudo ip addr show docker0) we could use this as the IP address to communicate with the host from within a docker container.
upstream django {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server IP_OF_DOCKER0:8000 fail_timeout=0;
}
I haven't tested the above but I believe it should work. If not you may need to bind gunicorn to the docker0 IP as well.
This answer has some good insight into this process as well...
From inside of a Docker container, how do I connect to the localhost of the machine?
A better approach might be "dokerize" the django application too, build a
network between the dokerized nginx and the dockerized django application
then expose the http port from the dockerized nginx to all interfaces.
Here is a good post about this, maybe you can take some hints from it :)
I've been struggling with this problem for two days without success. I've created an instance of the default Django (1.6.1) app called "testdj", installed it on an Amazon AWS EC2 t1.micro instance running Ubuntu Server 13.10, and I'm trying to reach the default Django "It worked!" page via Gunicorn (v. 18). When I start gunicorn from the command line:
gunicorn testdj.wsgi:application --bind [ec2-public-dns]:8001
I can see the page when I enter this URL:
http://[ec2-public-dns]:8001
However, if I use a "start-gunicorn" bash script I created after reading Karzynski's blogpost "Setting Up Django with Nginx, Gunicorn, virtualenv, supervisor, and PostgreSQL", I always get an error. When I enter this URL...
http://[ec2-public-dns]
... I get this error:
Error 502 - Bad Request
The server could not resolve your request for uri: http://[ec2-public-dns]
Here is the start-gunicorn script:
#!/bin/bash
NAME="testdj"
DJANGODIR=/usr/share/nginx/html/testdj
SOCKFILE=/usr/share/nginx/html/testdj/run/gunicorn.sock
USER=testdj
GROUP=testdj
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=testdj.settings
DJANGO_WSGI_MODULE=testdj.wsgi
WORKON_HOME=/home/testdj/venv
source `which virtualenvwrapper.sh`
workon $NAME
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGO_DIR:$PYTHONPATH
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--access-logfile /tmp/gunicorn-access.log \
--error-logfile /tmp/gunicorn-error.log \
--log-level=debug \
--bind=unix:$SOCKFILE
As you can see, I've created a special account on my server called "testdj" to run the app under. I'm running my Django app in a virtual environment. I haven't changed the Django wsgi.py file at all. As I eventually want to use nginx as my reverse proxy, I've installed nginx and put the Django app in nginx's default root directory /usr/share/nginx/html. User/group www-data owns /usr/share/nginx and everything below except that user/group "testdj" owns /usr/share/nginx/html/testdj and everything below it. /usr/share/nginx/html/testdj and all its subdirectories have perms 775 and I've added www-data to the testdj group.
I do have nginx installed but I don't have the nginx service running. I did try starting it up and enabling an nginx virtual server using the following configuration file but the error still occurred.
upstream testdj_app_server {
server unix:/usr/share/nginx/html/testdj/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name ec2-[my-public-dns-ip].us-west-2.compute.amazonaws.com;
client_max_body_size 4G;
access_log /var/log/nginx/testdj-access.log;
error_log /var/log/nginx/testdj-error.log;
location /static/ {
alias /usr/share/nginx/html/testdj/static/;
}
location /media/ {
alias /usr/share/nginx/html/testdj/media/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
# This must match "upstream" directive above
proxy_pass http://testdj_app_server;
break;
}
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /usr/share/nginx/html/testdj/static/;
}
}
The problem seems to be with gunicorn because if I replace the "--bind=unix:$SOCKFILE" in my start-gunicorn script with "--bind --[ec2-public-dns]:8000", I can see the Django default page. However, I don't want to bind to my public DNS name on port 8000, I want to run on port 80 and use nginx as my front end reverse proxy.
I initially had AWS inbound security group rules that limited access to the site to HTTP on ports 80, 8000, and 8001 to my laptop but even if I delete these rules and leave the site wide open, I still get the 502 error message.
My gunicorn access log doesn't show any activity and the only thing I see in the gunicorn error log is gunicorn starting up. When I access the default Django page, there are no errors in the error log:
2014-02-03 18:41:01 [19023] [INFO] Starting gunicorn 18.0
2014-02-03 18:41:01 [19023] [DEBUG] Arbiter booted
2014-02-03 18:41:01 [19023] [INFO] Listening at: unix:/usr/share/nginx/html/testdj/run/gunicorn.sock (19023)
2014-02-03 18:41:01 [19023] [INFO] Using worker: sync
2014-02-03 18:41:01 [19068] [INFO] Booting worker with pid: 19068
2014-02-03 18:41:01 [19069] [INFO] Booting worker with pid: 19069
2014-02-03 18:41:01 [19070] [INFO] Booting worker with pid: 19070
Does anyone know what's happening here? It doesn't look like I'm even getting to gunicorn. I apologize for the long post but there seems to be a lot of "moving parts" to this problem. I'd be very grateful for any help as I've tried many different things but all to no avail. I've also looked at other questions here where other people had similar problems but I didn't see anything pertinent to this problem. Thanks!
I repeated my configuration process line-for-line on my Linode server and had no problems at all. I have to assume that this problem has something to do with the way AWS EC2 instances are configured, probably with respect to security.
I was running into the same problem today. Daniel Roseman explained it to me in the comments here:
port 8000 is not open to the outside by default; you'd either need to
fiddle with your load balancer/firewall settings to open it, or run
gunicorn on port 80 (which will mean killing nginx and starting
gunicorn as the superuser). Much easier to just get the nginx settings
right; there is a perfectly usable configuration on the gunicorn
deploy docs page.
It seems it's possible to run Gunicorn directly, but EC2 isn't set up to do so by default.
I'm deploying my django app with nginx-uwsgi
I wanna add Varnish to this stack.
As I know Varnish can cache only ip and port.
But my stack configured this way:
location / {
uwsgi_pass unix://home/mechanism/SERVER/run/MechanisM.sock;
include uwsgi_params;
}
so my nginx works with uwsgi's socket. not ip and port.
but Varnish needs ip and port. like this:
backend default {
.host = "127.0.0.1";
.port = "8080";
}
should I change uwsgi to run with ip and port? or there's some way to configure Varnish to work with uwsgi's sock? or how to know ip and port of this socket?
btw, I'm starting uwsgi with this command:
exec /usr/sbin/uwsgi --socket /home/mechanism/SERVER/run/MechanisM.sock --chmod-socket --module wsgi_app --pythonpath /home/mechanism/SERVER/django-projects/MechanisM/uwsgi -p 12 -t 15
should I use -s 127.0.0.1:3031 instead of --socket /home/mechanism/SERVER/run/MechanisM.sock ??
Varnish will cache date coming from nginx, not from uWSGI.
Put the nginx address in varnish not the uWSGI one