I'm trying to serve both a Django and a Flask site using gunicorn and nginx. The Django site is currently available at example.com, and I'd like for the Flask site to be availabe at myapp.example.com .
My nginx configuration file is as follows for the Django site:
cat /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com;
location /static {
alias /home/me/sites/example.com/static;
}
location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/example.com.socket;
}
}
I also have a second nginx config file for the Flask site:
cat /etc/nginx/sites-available/myapp.example.com
server {
listen 80;
server_name myapp.example.com;
access_log /var/log/nginx/access.log;
location / {
proxy_pass http://127.0.0.1:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
I'm pretty sure that I want to change my proxy_pass variable, but am not sure what I should change it to.
My gunicorn file currently is as follows:
description "Gunicorn server for example.com"
start on net-device-up
stop on shutdown
respawn
setuid me
chdir /home/rowan/sites/example.com/source
exec ../virtualenv/bin/gunicorn \
--bind unix:/tmp/example.com.socket \
example.com.wsgi:application
Do I need a second gunicorn config file for the Flask site? Which I would then put in /etc/init/ and start through the sudo start gunicorn-myapp.example.com command?
Related
My goal is to serve the staticfiles to nginx on ubuntu from a docker django app container without using docker nginx
I setup the reverse proxy to django all works fine in dev mode but when i turn Debug to False nginx doesn't recognize the staticfiles path
here's a screenshot
Here's my dockerfile for django app
FROM python:3.9
RUN mkdir /app
WORKDIR /app
COPY . /app
RUN pip install pipenv
RUN pipenv install --system --deploy --ignore-pipfile
EXPOSE 8000
ENTRYPOINT ["python", "manage.py"]
CMD ["runserver", "0.0.0.0:8000"]
And here's my nginx config
upstream django {
server 127.0.0.1:8001;
}
server {
server_name django.com;
listen 80;
listen 8000;
client_max_body_size 100M;
location / {
proxy_pass http://django;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
proxy_read_timeout 1000;
proxy_connect_timeout 1000;
proxy_send_timeout 1000;
}
}
To have NGINX serve your staticfiles, your config needs to be edited. How do you expect nginx to find your files otherwise?
Luckily, it's a simple edit. :)
upstream django {
server 127.0.0.1:8001;
}
server {
server_name django.com;
listen 80;
listen 8000;
client_max_body_size 100M;
location /static {
alias /PATH/TO/STATIC_FILES;
}
location / {
proxy_pass http://django;
...
}
}
Don't forget to configure your static root, and run:
py manage.py collectstatic
This will make sure Django's default CSS/JS is included in your staticfiles.
When DEBUG=True, your staticfiles will be served by Django. This is not good, and can lead to some serious perfomance and security problems.
Edit:
Alternatively, have a look at Django-Whitenoise. It's great for serving staticfiles.
http://whitenoise.evans.io/en/stable/
My flask web app is based on socket.io, flask, nginx and gunicorn. One of frontend features sends 1.3MB message to the backend using socket.io. I know that from 3.x socket.io maxHttpBufferSize was decreased from 100MB to 1MB so I have max_http_buffer_size limit set to 2MB on the server side. Everything works good, backend receiving message but after few seconds of executing code on backend side it stops without any information in nginx error.log and gunicorn.log. Web browser(Opera, Chrome) console does not return any error too. I think that the problem is on the nginx side because when I execute my app using only gunicorn it works in the right way.
Have you any idea what should I change in my nginx config? Or the problem is elsewhere?
I'm using
Python 3.7.9,
python-engineio 4.0.0,
python-socketio 5.0.2,
Flask-SocketIO 5.0.0,
Javascript SocketIO 3.0.0
gunicorn 20.0.4,
nginx 1.14.0
My .service config file
[Unit]
Description=Gunicorn instance to serve <my_app>
After=network.target
[Service]
User=<my_user>
Group=www-data
WorkingDirectory=/path/to/my/app
Environment="PATH=/path/to/my/env/bin"
ExecStart=/path/to/my/env/bin/gunicorn --certfile=/path/to/my/app/cert.crt --keyfile=/path/to/my/app/key.key --access-logfile /path/to/my/app/gunicorn_logs.log --worker-class eventlet -w 1 --timeout 300 -b 0.0.0.0:5000 <my_app>:app
[Install]
WantedBy=multi-user.target
My nginx proxy requests config
server{
listen 80;
listen [::]:80;
server_name <my_domain> <my_server_ip>;
return 301 https://$host$request_uri;
}
server{
listen 443 default_server ssl;
listen [::]:443 default_server ssl;
access_log /path/to/my/app/access.log;
error_log /path/to/my/app/error.log;
ssl_certificate /etc/letsencrypt/live/<my_domain>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<my_domain>/privkey.pem;
server_name <my_domain> <my_server_ip>;
proxy_read_timeout 300;
# reverse proxy for HTTP connection
location / {
include proxy_params;
# 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_pass https://0.0.0.0:5000/;
proxy_redirect off;
}
# reverse proxy for Socket.IO connections
location /socket.io {
proxy_pass https://0.0.0.0:5000/socket.io;
proxy_redirect off;
proxy_buffering off;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
# let's encrypt host validation
location ~ /.well-known{
root /path/to/my/app/static/;
}
}
I think this erros happens, because of proxy_pass is incorrect, if someone has any idea please tell me thanks
NGINX FILE
proxy_cache_path /var/nginx/cache/project
keys_zone=djangoproject_cache:60m;
gzip on;
gzip_proxied any;
gzip_types text/plain text/xml text/css application/javascript application/x-javascript;
gzip_vary on;
gzip_disable msie6;
upstream appserver {
server unix:/home/dir/projects/djangoproject/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name www.subdominion.dominion www.subdominion.dominion;
add_header X-Frame-Options "SAMEORIGIN";
ssl_certificate certificate.crt;
ssl_certificate_key certificate.key;
ssl on;
server_tokens off;
root /var/www/html/;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location /djangoproject{
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_set_header X-Forwarded-Proto $scheme;
# Fix the “It appears that your reverse proxy set up is broken" error.
rewrite ^/djangoproject(.*) /$1 break;
proxy_pass http://unix:/home/sftpserver/projects/podaexpress/gunicorn.sock; -- I think the error is here
try_files $uri #proxy_to_appserver;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
sendfile_max_chunk 1024k;
root /home/dir/projects/djangoproject/static;
proxy_read_timeout 90;
}
location /flaskproject{
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_set_header X-Forwarded-Proto $scheme;
# Fix the “It appears that your reverse proxy set up is broken" error.
rewrite ^/flaskproject(.*) /$1 break;
proxy_pass http://unix:/home/dir/projects/flaskproject/gunicorn.sock;
proxy_read_timeout 90;
}
location #proxy_to_appserver {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_redirect off;
proxy_pass http://appserver;
}
}
using this nginx file I got one page manager index.html, in this page has two buttons with href link for my dominion/djangoproject or dominion/flaskproject , everything is correct until here, but when I click in button whose link directs for another project has one error http 502, but gunicorn file is correct
gunicorn file from djangoproject
#!/bin/bash
NAME="djangoproject" # Name of the application (*)
DJANGODIR=/home/dir/projects/djangoproject/ # Django project directory (*)
SOCKFILE=/home/dir/projects/djangoproject/gunicorn.sock # we will communicate using this unix socket (*)
USER=root # the user to run as (*)
GROUP=root # the group to run as (*)
NUM_WORKERS=15 # how many worker processes should Gunicorn spawn (*)
DJANGO_SETTINGS_MODULE=project.qasettings # which settings file should Django use (*)
DJANGO_WSGI_MODULE=project.wsgi # WSGI module name (*)
echo "------------- INICIANDO $NAME gunicorn -------------"
# Activate the virtual environment
cd $DJANGODIR
source /home/dir/projects/djangoproject/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
# Start your Django Unicorn Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec /home/dir/projects/djangoproject/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user $USER \
--bind=unix:$SOCKFILE \
--daemon
in both links I get the correct url example https://subdominion.dominion.com.br/djangoprojects or https://subdominion.dominion.com.br/flaskproject
I am running my flask project in nginx. This is the conf file
server {
listen 80;
server_name site.in;
root /root/site-demo/;
access_log /var/log/site/access_log;
error_log /var/log/site/error_log;
location / {
proxy_pass http://127.0.0.1:4000/;
proxy_redirect http://127.0.0.1:4000 http://site.in;
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_set_header X-Forwarded-Proto $scheme;
}
}
When i tried to put the expires part for static files into the conf it failed. I read that this may be due to the fact that the static files are served by flask rather than nginx. If so what changes should i bring to the above conf file so that the static file serving can be done by nginx for my project.
As per the answer i changed the conf as below. Now all static file shows 403 error.
server {
listen 80;
server_name site.in;
root /root/site-demo/;
access_log /var/log/site/access_log;
error_log /var/log/site/error_log;
location / {
proxy_pass http://127.0.0.1:4000/;
proxy_redirect http://127.0.0.1:4000 http://site.in;
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_set_header X-Forwarded-Proto $scheme;
}
location /static {
alias /root/site-demo/static;
autoindex on;
expires max;
}
}
Add this to your nginx configuration:
location /static {
alias /path/to/your/static/folder;
autoindex on;
expires max;
}
EDIT
nginx requires the whole tree to be readable and not just where your root starts in nginx.conf. So the command
sudo chmod -R 777 /root/site-demo/static
should solve the permissions problem. But, I think, is not a good thing - for security reasons - to put your site in the /root directory of your web server. Usually a site is put under the /var/www folder.
P.S.
The chmod -R 777 command gives owner, group and others permission to read, write and execute files in a folder and in all its subfolders.
check your nginx configuration here:
/etc/nginx/sites-enabled/
/etc/nginx/sites-available/
I was experiencing the same issue you describe
Noticed that I had several configuration files
Leaving only one config file fixed
This site is also helpful:
https://realpython.com/blog/python/kickstarting-flask-on-ubuntu-setup-and-deployment/
if you run on server or docker ,you should do like that:
server {
listen 443;
server_name sample.xx.code;
location /{
proxy_pass http://127.0.0.1:5000;
}
location /static {
proxy_pass http://video/static;
expires max;
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
}
I'm new at this and have only been using nginx to serve static files. I have now installed flask and gunicorn. If I run gunicorn -b 127.0.0.2:8000 hello:app and then wget it from the server it works well. If I try to access it from a browser, however, it returns a 404 error (I am running this on a server that hosts a wordpress site which is locatet at root).
The flask app:
from flask import Flask
from werkzeug.contrib.fixers import ProxyFix
app = Flask(__name__)
#app.route('/')
def hello():
return "Hello world!"
app.wsgi_app = ProxyFix(app.wsgi_app)
if __name__ == '__main__':
app.run()
And the relevant part of my nginx configuration:
location /flask {
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_pass http://127.0.0.2:8000;
proxy_redirect off;
}
I hope this is all the relevant info. If not, do tell. Thanks!
This is how I serve my flask apps in Nginx:
Run gunicorn daemonized using a socket:
sudo gunicorn app:app --bind unix:/tmp/gunicorn_flask.sock -w 4 -D
Related nginx config:
upstream flask_server {
# swap the commented lines below to switch between socket and port
server unix:/tmp/gunicorn_flask.sock fail_timeout=0;
#server 127.0.0.1:5000 fail_timeout=0;
}
server {
listen 80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
client_max_body_size 4G;
server_name example.com;
keepalive_timeout 5;
# path for static files
location /static {
alias /path/to/static;
autoindex on;
expires max;
}
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://flask_server;
break;
}
}
}
}