uWSGI, nginx, django unix sockets not working - python

I have a django application. I can't seem to get nginx to serve the static files correctly, but that's not this issue.
The current issue is that when following this guide: https://gist.github.com/evildmp/3094281
I try to use the unix sockets rather than the web socket.
e.g.
server unix:///tmp/uwsgi.sock; # for a file socket
#server 127.0.0.1:8001; # for a web port socket
using the /tmp/uwsgi.sock socket rather than the 127.0.0.1:8001 web port socket.
The issue is that when I use the web port socket, and I navigate to domainname.com:8001 I reach the website as served by uWSGI, but there are no staticfiles loaded. So that means that at least uwsgi is working. But when I switch over to the file socket, I cannot even get it to work at all.
What am I doing wrong?
Here is my nginx.conf:
# nginx.conf
upstream django {
# connect to this socket
# server unix:///tmp/uwsgi.sock; # for a file socket (TRYING TO USE)
server 127.0.0.1:8001; # for a web port socket (RATHER THAN THIS)
}
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name .cshenkan.com; # substitute your machine's IP address or FQDN
charset utf-8;
#Max upload size
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /home/ubuntu/sasite-rewrite/media; # your Django pro$
}
location /static {
alias /home/ubuntu/sasite-rewrite/static; # your Django pro$
}
location /assets {
alias /home/ubuntu/sasite-rewrite/assets
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # or the uwsgi_params you installe$
}
}
And my base.py settings file snippet:
STATIC_ROOT = normpath(join(SITE_ROOT, 'static'))
STATIC_URL = '/static/'
STATICFILES_DIRS = (
normpath(join(SITE_ROOT, 'static')),
normpath(join(SITE_ROOT, 'assets')),
)
And how I run uwsgi when using the web socket:
uwsgi --http :8001 --chdir /home/ubuntu/sasite-rewrite --wsgi-file /home/ubuntu/sasite-rewrite/sasite/wsgi.py
And how I run it when using the unix socket:
uwsgi --socket /tmp/uwsgi.sock --chdir /home/ubutnu/sasite-rewrite --wsgi-file /home/ubuntu/sasite-rewrite/sasite/wsgi.py
I just can't seem to get it to work when using the unix socket.
Neither can I get nginx to serve the correct static files, for example if I add a file to the media directory called 1.png or 1.txt and try to access them with domainname.com:8000/media/1.png I always get a hang or a no response from server error.
What am I doing wrong?
How can I get the unix socket to work correctly? And is the command I'm using correct?
I also don't understand this, when I use the web socket, I can connect to domainname.com:8001 and get the page with no static files, it looks like crap but loads from uwsgi. But with the unix sockets I have no idea how to access the page served by uwsgi to see if it works with the unix socket. Before I can move onto getting nginx working, I need to solve this issue, as I tried using web sockets with nginx and still had no luck there, I'm hoping once my unix sockets are set up correctly nginx will work better.
Any suggestions, or examples you could provide? Would be much appreciated, I am a long time django programmer, but I have very rarely deployed the sites myself. So I am really struggling here.
Any help is much appreciated, thanks.

Today I had the same problem with NGINX + Socket Unix for uwsgi protocol.
I discovered that version 1.8 of the NGINX is bugged.
Try installing version 1.10 that will work via UNIX SOCKET.
If you use open-SuSE, you can get the rpm here:
http://download.opensuse.org/repositories/home:/ghostlyrat/openSUSE_Leap_42.2/x86_64/nginx-1.10.1-3.3.x86_64.rpm
Or, directly in the official nginx downloads area:
http://nginx.org/en/download.html

Related

Forwarding Nginx port to gunicorn instance

I was following this tutorial to setup my flask server.
https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-18-04#step-6-%E2%80%94-securing-the-application
When I got to step 6 I see that they are setting flask for the whole url but I would like to point it to a specific port.
This is the code I have for my nginx which points. This currenly produces a 404.
server {
listen 5000;
server_name site.com;
location / {
include proxy_params;
proxy_pass http://unix:/home/user/project/project.sock;
}
}
All the other files are the same as the tutorial. I have tried to modify the .sock file but it seems like it was generated automatically and it can't be modified. In addition I need to find a way for nginx to handle this before I worry about handling it from gunicorn.
My end goal is to have nginx foward requests to flask running when a request is sent to 0.0.0.0:5000 and have all other requests 0.0.0.0 , 0.0.0.0/* be handled by nginx.
Any help to undestand all this is really appreciated got lost at this point.
EDIT
my nginx configuration in sites-available
server {
server_name domain www.domain;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:8080/;
}
}
If you want flask to be open to a port instead of a file you should override
[service] to
[service]
...
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 -m 007 wsgi:app
And change your nginx config to proxy_pass http://127.0.0.1:8000/;
This way you can have access to port 8000 for checking how are working gunicorn and flask. Remember to be careful with firewall rules to secure port 8000. For a good discussion on which one is better you can try: gunicorn + nginx: Server via socket or proxy?

python - How to deploy Flask+Gunicorn+Nginx+supervisor on a cloud server?

I've read a lot of instructions since yesterday about this issue but all of them have similar steps. However I followed step by step but still can't get everything Ok.
Actually I can make Flask+Gunicorn+supervisor working but Nginx is not working well.
I connect my remote cloud server with SSH and I'm not deploying the site on my computer.
Nginx is installed correctly because when I visit the site via the domain name (aka. example.com) it shows the Nginx welcome page.
I use supervisor to start Gunicorn and the configuration is
[program:myapp]
command=/home/fh/test/venv/bin/gunicorn -w4 -b 0.0.0.0:8000 myapp:app
directory=/home/fh/test
startsecs=0
stopwaitsecs=0
autostart=false
autorestart=false
stdout_logfile=/home/fh/test/log/gunicorn.log
stderr_logfile=/home/fh/test/log/gunicorn.err
here I bind the server to port 8000 and I don't actually know what does 0.0.0.0 stand for but I think it doesn't mean the localhost because I can visit the site via http://example.com:8000 and it works well.
Then I tried to use Nginx as a proxy server.
I deleted /etc/nginx/sites-available/default' and '/etc/nginx/sites-enabled/default/ and created /etc/nginx/sites-available/test.com and /etc/nginx/sites-enabled/test.com and symlink them.
test.com
server {
server_name www.penguin-penpen.com;
rewrite ^ http://example/ permanent;
}
# Handle requests to example.com on port 80
server {
listen 80;
server_name example.com;
# Handle all locations
location / {
# Pass the request to Gunicorn
proxy_pass http://127.0.0.1:8000;
# Set some HTTP headers so that our app knows where the request really came from
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
To my understanding, what Nginx do is when I visit http://example.com it passes my request to http://example.com:8000.
I'm not quite sure that I should use proxy_pass http://127.0.0.1:8000 here because I don't know whether should Nginx pass the request to localhost But I 've tried to change it to 0.0.0.0:8000 but it still doesn't work.
Can anyone help?
0.0.0.0 means the server will accept connections from all IP address. See https://en.wikipedia.org/wiki/0.0.0.0 for more detail.
If the gunicorn server listens on 127.0.0.1, only you (or someone else on the same machine with gunicorn server) can access it through local loop https://en.wikipedia.org/wiki/Local_loop.
But since you use Nginx to accept connection from the internet, you can just proxy_pass http://127.0.0.1:8000; and change the command to command=/home/fh/test/venv/bin/gunicorn -w4 -b 127.0.0.1:8000 myapp:app. In this scenario, gunicorn itself only need to accept connections from Nginx which runs on the same machine with gunicorn.
The whole process looks like this
Connections from the Internet -> Nginx (reverse proxy, listen on 0.0.0.0:80) -> Gunicorn (which runs your Python code, listen on 127.0.0.1:8000)

How to run django project on nginx and uwsgi

I'm trying to run my first Django project using nginx and uwsgi. And I faced with the problem with nginx. I get the message in the brouser "Unable to connect. Firefox can't establish a connection to the server at localhost:8000". I'm following the instructions from this link Everything is fine with uwsgi and installing nginx. Then I downloaded uwsgi_params file and created mysite_nginx.conf file as the instruction says.
Here's mysite_nginx.conf file:
# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name localhost; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /home/ubuntu/myproject/mysite/friends_plans/media; # your Django project's media files - amend as required
}
location /static {
alias /home/ubuntu/myproject/mysite/friends_plans/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /home/ubuntu/myproject/mysite/uwsgi_params; # the uwsgi_params file you installed
}
}
It worked with server name "localhost" and port 8000 when I was checking uwsgi according to the intruction. I made the commands sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/ , python manage.py collectstatic , sudo /etc/init.d/nginx restart. In my settinds.py: STATIC_ROOT = "/home/ubuntu/myproject/mysite/friends_plans/static/". The command about static files worked properly. But I can't set the connection with the server. Could you please tell me where I have a mistake and how to correct it? Thank you very much in advance.

Nginx, django on ec2 with elastic ip not responding

I have a problem with my amazon ec2 instance. I cannot access my django application running on port 8004 from the browser.
I have setup an instance on amazon ec2, installed django and nginx. This is running on ubuntu trusty 14.04. I have a domain on external dns-nameserver and I have correctly pointed that domain to the public elastic ip of my amazon ec2 instance. When I ping the server it works and it shows the public ip.
I've seen similar threads before and in most cases problems with this have been because firewall rules have not been added for specific ports, that is they are not open to the outside world. In my case I made sure that port 22, 80 and 443 were open when I created the instance. I've even made ports 8000 - 8100 open.
Note: Eventually I will make django run with gunicorn but just to test it I'm simply running it by going: manage.py runserver 8004
Here is a snapshot of how my inbound rules look like for open ports on amazon ec2
Could it be because I'm editing inbound rules after I launched the instance? Isn't that what you're suppose to be able to do?
Nginx is running without problems, I'll post my config below. I have no idea why this doesn't work. I have followed any thread I find on the subject and nothing seems to fix it.
UPDATE: I can now confirm that I can access my django site directly through the ip, by going
ip:8004. So obviously this is not a problem with the ports but has likely something to do with nginx config or my DNS settings.
My nginx config (I've replaced ip's with x, and the domain with sub.domain.com. I then try to access the site from sub.domain.com)
upstream docko_server {
server 127.0.0.1:8004 fail_timeout=0;
}
server {
server_name sub.domain.com;
listen xx.xx.xx.xxx:80;
return 303 https://$host$request_uri;
}
# HTTPS server
#
server {
listen xx.xx.xx.xxx:443;
server_name sub.domain.com;
ssl on;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
client_max_body_size 25M;
access_log /webapps/docko/logs/nginx-access.log;
error_log /webapps/docko/logs/nginx-error.log;
location /assets/ {
alias /webapps/docko/docko/staticfiles/;
}
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) {
proxy_pass http://docko_server;
break;
}
}
}
If you want to access the django dev server from the Internet through the port 8004 try:
manage.py runserver 0.0.0.0:8004
The dev server will only listen by default on 127.0.0.1.
However you won't need this if you get to the dev server through Nginx, i.e. you connect to your.domain.com:80. In this case Nginx will act as a proxy, passing the request to the dev server.
BTW you can edit the rules of existing security group after launching the instances, this works perfectly.
To answer my own question I succeeded by not assigning the elastic ip but simply just listening on port 80, 443. So in my nginx conf instead of this.
server_name sub.domain.com;
listen xx.xx.xx.xxx:80;
I now just have
server_name sub.domain.com
listen 80;
same for 443.

Serving a request from gunicorn

Trying to setup a server on Rackspace.com.
Have done the following things:
Installed Centos 6.3
Installed Python 2.7
Installed gunicorn using the "Quick Start" on their home page: gunicorn.org/
In the quick start, a "hello world" application seems to be initialized:
Create file "myapp.py":
(tutorial) $ vi myapp.py
(tutorial) $ cat myapp.py
Contents of "myapp.py"
def app(environ, start_response):
data = "Hello, World!\n"
start_response("200 OK", [
("Content-Type", "text/plain"),
("Content-Length", str(len(data)))
])
return iter([data])
Since I know very little about servers, I do not know what to do next. I tried typing the server's IP address into the browser, but that seemed to result in a timeout.
I'm not sure if there is:
something else that needs to be installed. Nginx is mentioned under "deploy" on the gunicorn website. Looks like Nginx is a proxy server which is confusing to me because I thought gunicorn was a server. Not sure why I need two servers?
something that needs to be configured in gunicorn
something that needs to be configured on the server itself
something that else entirely that needs to be done in order to actually serve a request
What are the next steps?
Thanks so much!
since gunicorn is a Web server on your case Nginx will act as a back proxy passing the an HTTP request from Nginx to gunicorn.
So, I will put here the steps to take for a simple Nginx and Gunicorn configuration running on the same machine.
Starting with nginx configuration
Go to your /etc/nginx/nginx.conf and under the http{} make sure you have: include /etc/nginx/site-enabled/*;
http{
# other configurations (...)
include /etc/nginx/sites-enabled/*;
}
now, include a file on /etc/nginx/sites-enabled/mysite.conf where you will proxy your requests to your gunicorn app.
server {
listen 80 default; # this means nginx will be
# listening requests on port 80 and
# this will be the default nginx server
server_name localhost;
# declare proxy params and values to forward to your gunicorn webserver
proxy_pass_request_headers on;
proxy_pass_request_body on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 120s;
location / {
# here is where you declare that every request to /
# should be proxy to 127.0.0.1:8000 (which is where
# your gunicorn will be running on)
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://127.0.0.1:8000/; # the actual nginx directive to
# forward the request
}
}
Ok, at this point all you have is an Nginx acting as a proxy where all the requests going to 127.0.0.1:80 will be passed to 127.0.0.1:8000.
Now is time to configure your Gunicorn webserver:
Usually the way I do I use a configuration file, Gunicorn config file can be an ordinary python file. So now, create a file at any location you like, I will assume this file will be /etc/gunicorn/mysite.py
workers = 3 # number of workers Gunicorn will spawn
bind = '127.0.0.1:8000' # this is where you declare on which address your
# gunicorn app is running.
# Basically where Nginx will forward the request to
pidfile = '/var/run/gunicorn/mysite.pid' # create a simple pid file for gunicorn.
user = 'user' # the user gunicorn will run on
daemon = True # this is only to tell gunicorn to deamonize the server process
errorlog = '/var/log/gunicorn/error-mysite.log' # error log
accesslog = '/var/log/gunicorn/access-mysite.log' # access log
proc_name = 'gunicorn-mysite' # the gunicorn process name
Ok, all set in configuration. Now all you have to do its to start the servers.
Starting the gunicorn and telling it which app to use and which config file.
from the command line and the folder where your myapp.py file is located run:
gunicorn -c /etc/gunicorn/mysite.py mysite:app
Now, only start nginx.
/etc/init.d/nginx start
or
service nginx start
Hope this helps.
looking at the quickstart guide, you probably should have run
(tutorial) $ ../bin/gunicorn -w 4 myapp:app
which should have produced a line that looks a bit like:
Listening at: http://127.0.0.1:8000
Among others. see if you can access your site at that address.
Also Note that 127.0.0.1 is the loopback address; accessible only from that host itself. To get gunicorn to bind to a different option, pass it --bind 0.0.0.0:80, as Jan-Philip suggests.
Since you mention rackspace, its possible that you may need to adjust the firewall settings to allow incoming connections to the desired ports.
Looks like you do not have a web application developed so far. So, I assume that your goal for now is to set up a development environment. For the time being, develop your web application using the development web server included in most frameworks, e.g. Flask.
Whatever framework you are using, make the development web server listen on 0.0.0.0 so that the service is listening on all configured network interfaces and make sure that the port is open to the outside (check the Rackspace settings).
When you are done developing your application or are looking into an existing one, you have to deploy it in a solid way. Then, gunicorn behind nginx is an option.
I will roughly go through your questions. It looks you have to read a bit more :-)
Nginx is mentioned under "deploy" on the gunicorn website. Looks like Nginx is a proxy server which is confusing to me because I thought gunicorn was a server. Not sure why I need two servers?
Nginx is a full-featured web server. It is appreciated for its performance and stability. People use it to serve static files (to not burden a dynamic web application with this task), to forward requests to web applications whenever necessary, for SSL-termination, and for load-balancing. Note that this is an incomplete picture.
gunicorn is a server for serving WSGI apps. Mainly, it manages worker processes that actually execute the web application.
something that needs to be configured in gunicorn.
something that needs to be configured on the server itself.
something that else entirely that needs to be done in order to actually serve a request.
Actually, you can optimize your linux box in endless ways (for performance, e.g. increase the file descriptor limit and for security). Within gunicorn, you can configure the number of worker processes and a lot more. If you have nginx as frontend or even another load balancer, this one has its own configuration. You see, your setup might become very complex for actual deployment in a real-world scenario. This is not trivial.
However, for playing around with a WSGI application, just set up your development framework properly, which is very simple in most cases, and make sure that there are no firewall issues. That's all.

Categories