I am running a server with Nginx + Gunicorn + Django.
I have configured Django to show a robots.txt file, and this works just fine when I test Django on its own, without Nginx+Gunicorn.
However, when I run the whole stack, /robots.txt suddenly gets replaced with a different file that I didn't write.
Why is this happening? I never wrote anything to tell Nginx or Gunicorn to do such a thing. Is there a default somewhere that I need to overwrite or deactivate?
The folder /etc/nginx/sites-enabled contains only my own sites file, and it doesn't mention /robots explicitly. It just has a location block targeting / which gets routed to Gunicorn+Django, and for every site except robots.txt this works just fine.
My Gunicorn config:
[Unit]
Description=gunicorn daemon
After=network.target
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/root/lod/collab/collab
ExecStart=/root/lod/CollabVenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/root/lod/collab.sock collab.wsgi:application
[Install]
WantedBy=multi-user.target
My Nginx config:
server {
# if no Host match, close the connection to prevent host spoofing
listen 80 default_server;
listen [::]:80 default_server;
return 444;
}
server {
# redirect any http requests to https
listen 80;
listen [::]:80;
server_name example.com www.example.com localhost;
return 301 https://example.com$request_uri;
}
server {
# this is the main server application, serving example.com with https
listen 443;
listen [::]:443;
server_name example.com;
# SSL certificate
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
# allow large request bodies, which may be necessary for some JSON commands
client_max_body_size 4G;
# ignore a missing favicon
location = /favicon.ico { access_log off; log_not_found off; }
# Django media
location /media {
alias /root/lod/CollabData/media_public; # your Django project's media files
}
# Django static
location /static {
autoindex on;
alias /root/lod/collab/collab/static_processed; # your Django project's static files
}
# send all non-media requests to the Django server
location / {
# necessary for SSL
# note:
# I have no idea what most of these do. I just followed tutorials on the internet.
# Feel free to improve this if you know what you are doing.
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host:443;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
# the connection to Gunicorn
proxy_pass http://unix:/root/lod/collab.sock;
}
}
EDIT:
It just started working correctly, even though I made no changes since the last time I opened the site. Maybe some background process or cache took a while to update? I'm leaving this question open in case someone can explain what caused this, so that other people won't have to spend as much time with this problem as I did.
Related
I know many others have asked the same question, but I haven't found any answers that are relevant or work for me. If you do know of a duplication, feel free to direct me to it.. I'm getting lost in the maze of nginx threads!
I am new to this and used the following tutorials to set up my django site with gunicorn and nginx:
https://vahiwe.medium.com/deploy-django-and-flask-applications-in-the-cloud-using-nginx-gunicorn-and-systemd-centos-7-4b6aef3a8578
https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-centos-7
My website works if I access it via the IP address but I get a Bad Request error when I try by the domain name.
In nginx.conf my server block looks like:
server {
listen 80;
server_name 123.456.78.910 mywebsite.com www.mywebsite.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /var/www/userf/website;
}
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:/var/www/userf/website/website.sock;
}
}
My gunicorn.service file is:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ssej91D
Group=nginx
WorkingDirectory=/var/www/ssej91D/pwebsite
ExecStart=/var/www/userf/website/env/bin/gunicorn --workers 3 --error-logfile - --bind unix:/var/www/userf/website/website.sock website.wsgi:application
EnvironmentFile=/var/www/userf/website/.env
[Install]
WantedBy=multi-user.target
And my ALLOWED_HOSTS in django's settings.py:
ALLOWED_HOSTS = ["mywebsite.com", "www.mywebsite.com", "123.456.78.910"]
I have not added any SSL related settings to the Django settings file yet.
To test the domain name, I've tried making a test index.html file in another directory (let's call it testwebsite and then changing the nginx.conf to:
server {
listen 80;
server_name 123.456.78.910 mywebsite.com www.mywebsite.com;
location = /favicon.ico { access_log off; log_not_found off; }
location / {
root /var/www/userf/testwebsite;
}
}
This worked perfectly. My domain name showed index.html.
I've checked the logs, and they are always empty. I'll be totally honest, I just copied all of the proxy server settings from the tutorial and I don't actually understand them. I guess my suspicion is I'm doing something wrong in setting up nginx as a proxy server.
Any help would be very appreciated.
Thanks
I was missing a host in the ALLOWED_HOSTS list.
The host name of the droplet I'm using is different because I'm sharing it.
I was under the assumption that I could run a Django Channels app using only Daphne (ASGI) and Nginx as a proxy for my Django app to begin with.
The application would be running with Daphne on 127.0.0.1:8001
However, I am running into a 403 Forbidden error.
2019/03/06 17:45:40 [error] *1 directory index of "/home/user1/app/src/app/" is forbidden
And when I posted about that, another user mentioned
There is no directive to pass http request to django app in your
nginx config
And suggested to look into fastcgi_pass or uwsgi_pass or Gunicorn.
Obviously Django Channels runs on ASGI and I am passing all requests through that right now (not to uWSGI then on to ASGI depending on the request.)
Can I serve my Django app with only Nginx and Daphne? The Django Channels docs seem to think so as they don't mention needing Gunicorn or something similar.
my nginx config
upstream socket {
ip_hash;
server 127.0.0.1:8001 fail_timeout=0;
}
server {
listen 80;
#listen [::]:80 ipv6only=on;
server_name your.server.com;
access_log /etc/nginx/access.log;
root /var/www/html/someroot;
location / {
#autoindex on;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri =404;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Host $http_host;
#proxy_set_header X-NginX-Proxy true;
#proxy_pass http://socket;
#proxy_redirect off;
#proxy_http_version 1.1;
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
#proxy_redirect off;
#proxy_set_header X-Forwarded-Proto $scheme;
#proxy_cache one;
#proxy_cache_key sfs$request_uri$scheme;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/some/fullchain.pem;
# managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/some/privkey.pem;
# managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
Yes, it's possible. Try this config:
upstream socket {
ip_hash;
server $DAPHNE_IP_ADDRESS$ fail_timeout=0;
}
server {
...
location / {
proxy_pass http://socket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
...
}
Where $DAPHNE_IP_ADDRESS$ - your daphne IP and port without schema(127.0.0.1:8001).
I'm trying to use nginx as a reverse proxy to receive incoming calls, then, depending on the server_name, redirect those calls to different computers (hosts), running nginx Django and Gunicorn. So far, I've tried different configurations for the conf file on the host, but none of them are working. Is there anything wrong with my conf files?
This is the nginx.conf in 192.168.0.13 that will function as a reverse proxy:
server {
listen 80;
server_name www.coding.test;
location / {
proxy_pass http://192.168.0.8:80;
proxy_redirect off;
# app1 reverse proxy follow
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
This is the nginx.conf in 192.168.0.8 that is intended to run the django app:
upstream django {
server unix:///home/pi/coding-in-dfw/mysocket.sock fail_timeout=0;
}
server {
listen 80 default_server;
server_name www.coding.test
client_max_body_size 4G;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /static/ {
alias /home/pi/coding-in-dfw/static/;
}
location /media/ {
alias /home/pi/coding-in-dfw/media/;
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
location /.well-known {
alias /home/pi/coding-in-dfw/.well-known;
}
}
Finally this is the way I'm running gunicorn:
gunicorn --workers 5 --bind unix:///home/pi/coding-in-dfw/mysocket.sock codingindfw.wsgi:application && sudo service nginx restart
Any help is appreciated.
I am using Nginx and gunicorn to serve my Django project. I currently have it working for ssl (https), but do not quite understand the correct settings for the settings file and nginx. Could someone have a look at my setup and tell me if anything blatantly looks wrong, or horribly executed?
My Nginx File, Please Note that some lines are commented out. When I uncomment them, the site stops working. Edit: When I uncomment them all at the same time/
server {
server_name example.com;
listen 443 ssl;
ssl on;
ssl_certificate /etc/ssl/mycrt.crt;
ssl_certificate_key /etc/ssl/mykey.key;
location = /favicon.ico {access_log off; log_not_found off;}
location /static/ {
gzip on;
gzip_types text/css;
alias /home/project/static/;
}
location / {
include proxy_params;
# 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;
proxy_pass http://unix:/home/project/myproject/project.sock;
}
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
My Gunicorn File
[Unit]
Description=gunicorn daemon
After= network.target
[Service]
User=tyler
Group=www-data
Environment="Production=production"
WorkingDirectory=/home/project/myproject
ExecStart=/home/project/projectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/projecty/myproject_a$
[Install]
WantedBy=multi-user.target
And lastly, the dajngo settings
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
Are there any issues with this setup? I am very confused about the Nginx settings that I had to comment out in order for https to start working. Also, I know Django is very cautious on using the SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') setting. Does all look well?
Thanks!
It works for me. I don't sure it will work for you, but you can try.
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:/home/project/myproject/project.sock;
}
I am currently working on deploying my project over https however I am running into some issues. I have it working with http but when I try to incorporate the ssl it breaks. I think I am misconfiguring the gunicorn upstream client in my nginx block but I am uncertain. Could the issue be in the unix binding in my gunicorn service file? I am very new to gunicorn so I'm a little lost.
Here is my configuration below.
Gunicorn:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
Environment=PYTHONHASHSEED=random
User=USER
Group=www-data
WorkingDirectory=/path/to/project
ExecStart=/path/to/project/project_env/bin/gunicorn --workers 3 --bind unix:/path/to/project/project.sock project.wsgi:application
[Install]
WantedBy=multi-user.target
Nginx (working-http):
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name server_domain;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /path/to/project;
}
location / {
include proxy_params;
proxy_pass http://unix:/path/to/project/project.sock;
}
}
Nginx (https):
upstream server_prod {
server unix:/path/to/project/project.sock fail_timeout=0;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name server_domain;
}
server {
server_name server_domain;
listen 443;
ssl on;
ssl_certificate /etc/ssl/server_domain.crt;
ssl_certificate_key /etc/ssl/server_domain.key;
location /static/ {
root /path/to/project;
}
location / {
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://server_prod;
break;
}
}
}
Your gunicorn systemd unit file seems OK. Your nginx is generally OK too. You have posted too little info to get an appropriate diagnostic. I'm guessing you are missing passing the X-Forwarded-Proto header to gunicorn, but it could be something else. Here's an nginx configuration file that works for me:
upstream gunicorn{
# 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).
# for UNIX domain socket setups:
server unix:/path/to/project/project.sock fail_timeout=0;
# for TCP setups, point these to your backend servers
# server 127.0.0.1:9000 fail_timeout=0;
}
server {
listen 80;
listen 443 ssl http2;
server_name server_domain;
ssl_certificate /etc/ssl/server_domain.crt;
ssl_certificate_key /etc/ssl/server_domain.key;
# path for static files
root /path/to/collectstatic/dir;
location / {
# checks for static file, if not found proxy to app
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When Nginx is handling SSL it is helpful to pass the protocol information
# to Gunicorn. Many web frameworks use this information to generate URLs.
# Without this information, the application may mistakenly generate http
# URLs in https responses, leading to mixed content warnings or broken
# applications. In this case, configure Nginx to pass an appropriate header:
proxy_set_header X-Forwarded-Proto $scheme;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
proxy_pass http://gunicorn;
}
}