What is gunicorn.sock? - django

I am a newbie following the gunicorn-django tutorial by Michal Karzynski. I am using Django 1.7.4 on Ubuntu 14 and my setup for the gunicorn script is as follows
#!/bin/bash
NAME="mytestapp" # Name of the application
DJANGODIR=/var/www/testapp/src # Django project directory
SOCKFILE=/var/www/testapp/run/gunicorn.sock # we will communicte using this unix socket
USER=ubuntu # the user to run as
GROUP=ubuntu # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=testapp.settings # which settings file should Django use
DJANGO_WSGI_MODULE=testapp.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
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 gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=0.0.0.0:8000 \
--log-level=debug \
--log-file=-
When I change the bind setting to unix:$SOCKFILE, my script still runs but I am unable to connect with my browser. In this question I have read that it's not wise to deploy 0.0.0.0:8000 on a production server.
I know a bit about unix sockets, but I don't know understand how I can use the unix socket file to serve my site. I have tried to edit the socket file as the superuser, but the OS doesn't let me open it.
How can I setup the socket file to allow me to serve my pages?
PS: Here is my nginx configuration file
upstream hello_app_server {
# 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 127.0.0.1:8000 fail_timeout=0;
}
server {
listen 80;
server_name test.com;
client_max_body_size 4G;
access_log /var/www/testapp/src/logs/nginx-access.log;
error_log /var/www/testapp/src/logs/nginx-error.log;
location /static/ {
alias /var/www/testapp/src/static/static_dirs/;
}
location /media/ {
alias /var/www/testapp/src/static/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://hello_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/testapp/src/static/;
}
}

You're supposed to use a reverse proxy like nginx to sit in front of gunicorn, and that's what actually serves your site. They communicate via the socket.
The gunicorn docs have a sample nginx configuration which does exactly that, although obviously you should make the sockfile match what you've put in your gunicorn config.

Sockets are a much faster, more efficient alternative to network ports if you are working locally on a server. However if your nginx server and your django app are on different servers then your would need to open up specific ip connections.
For your example if you want to use sockets you just need to point the upstream server address to your socket file.
Change the nginx configuration as
upstream hello_app_server {
# 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 unix:/var/www/testapp/run/gunicorn.sock fail_timeout=0;
}
server {
.
.
.
# Rest of your file...

Related

Nginx: 403 Forbidden nginx/1.12.1 (Ubuntu)

I've never before configured any production server, I'm trying to configure nginx and keep getting the 403 Forbidden error. I can't figure out the reason why it's happening.
Here is a complete error report:
[crit] 25145#25145: *1 connect() to unix:/home/albert/deploy_test/django_env
/run/gunicorn.sock failed (13: Permission denied) while connecting to
upstream, client: 192.168.1.118, server: 192.168.1.118, request: "GET /
HTTP/1.1", upstream: "http://unix:/home/albert/deploy_test/django_env
/run/gunicorn.sock:/", host: "192.168.1.118"
Here is my /etc/nginx/sites-available/deployproject.conf:
(I removed the default config and created a symlink as follows: sudo ln -s /etc/nginx/sites-available/deployproject.conf /etc/nginx/sites-enabled/deployproject.conf)
upstream sample_project_server {
# 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 unix:/home/albert/deploy_test/django_env/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name 192.168.1.118;
client_max_body_size 4G;
access_log /home/albert/logs/nginx-access.log;
error_log /home/albert/logs/nginx-error.log;
location /static/ {
alias /home/albert/static/;
}
location /media/ {
alias /home/albert/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://sample_project_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/albert/static/;
}
}
Here is the complete tutorial I'm using to deploy my app. Here I'm just trying to deploy the most primitive,default django app but in my real app I'm using django as a serverside, so there seems to be no need for nginx to serve static and all that.
File Permissions. Incorrect file permissions are another cause of the "403 Forbidden" error. The standard setting of 755 for directories and 644 for files is recommended for use with NGINX. The NGINX user also needs to be the owner of the files
Try to change the permissions on your web dir
sudo chown -R albert:www-data /webdirectory
sudo chmod -R 0755 /webdirectory
Move all your sites inside the webdirectory do not leave the dir and files in your root home.
Have you taken a look at the gunicorn docs here which has example of how to configure nginx
http://docs.gunicorn.org/en/stable/deploy.html
Can you try running gunicorn via TCP instead of unix socket, in your upstream sample_project_server replace server with:
server 192.168.0.7:8000 fail_timeout=0;
What are the settings in gunicorn? You can bind to localhost via TCP with the following, to check that it isn't a problem with your unix socket:
--bind 127.0.0.1:8000

Doesn't Nginx support Django admin static files

My django site user-end is running good with the static files but don't know why all the admin panel static files is not working. While it's working normally but not with linux any idea ??
nginx .conf file
upstream sample_project_server {
# 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 unix:/home/me/SPEnv/run/gunicorn.sock fail_timeout=0;
}
server {
listen 800;
server_name <your domain name>;
client_max_body_size 4G;
access_log /home/me/logs/nginx-access.log;
error_log /home/me/logs/nginx-error.log;
location /static {
root /home/me/DjangoProjects/SP/SP;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# 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;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://sample_project_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/me/DjangoProjects/SP/SP;
}
}
and settings.py
Static files (CSS, JavaScript, Images)
https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/home/me/DjangoProjects/SP/SP/static/'
STATICFILES_DIRS = (
# os.path.join(BASE_DIR, 'SP','static/admin'),
'/home/me/DjangoProjects/SP/SP/static/',
'/home/me/SPEnv/lib/python2.7/site-packages/django/contrib/admin/static'
)
You need to add the directory for the admin static files to your STATICFILES_DIRS list before you run collectstatic. Something like this:
STATICFILES_DIRS = [
'/project/src/static',
'/usr/local/lib/python3.6/site-packages/django/contrib/admin/static',
]
Where the first entry is the path to your app's static files and the second is the location of the django admin package.
I have the same problem. My nginx server on Centos 7.6 can't access to static folder in path /home/user/app/mysyte/static/. In /var/log/nginx/error.log same error
open() "/home/user/app/mysyte/static/*.css" failed (13: Permission denied)
For solving and understanding this problem :=*
run command getenforce
if enforcing - cat /var/log/audit/audit.log | grep nginx
for me string with errrors looks like
type=AVC msg=audit(1558033633.723:201): avc: denied { read } for pid=7758 comm="nginx" name="responsive.css" dev="dm-0" ino=17312394 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
type=SYSCALL msg=audit(1558033633.723:201): arch=c000003e syscall=2 success=no exit=-13 a0=564f710dd55d a1=800 a2=0 a3=68632f656d6f682f items=0 ppid=7757 pid=7758 auid=4294967295 uid=998 gid=996 euid=998 suid=998 fsuid=998 egid=996 sgid=996 fsgid=996 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)
copy id of audit msg 1558033633.723:201
run command grep yours_audit_id /var/log/audit/audit.log | audit2why
output for me
[root#uwsgi ~]# grep 1558034479.384:221 /var/log/audit/audit.log | audit2why
type=AVC msg=audit(1558034479.384:221): avc: denied { read } for pid=7758 comm="nginx" name="responsive.css" dev="dm-0" ino=17312394 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
Was caused by:
The boolean httpd_read_user_content was set incorrectly.
Description:
Allow httpd to read user content
Allow access by executing:
# setsebool -P httpd_read_user_content 1
So as you can see answer here setsebool -P httpd_read_user_content 1 when you run this command you see your static content

How can I test if gunicorn is working and communicating with nginx?

I'm deploying my first attempt at using django+gunicorn+nginx.
I have django working (curl -XGET http://127.0.0.0.1:8000 works fine if I run the development server).
I have nginx working for static content (for example I can retrieve http://example.com/static/my_pic.png in my browser).
I'm not getting any wsgi content from my website, and I haven't been able to find a good troubleshooting guide (does it just work for everyone else?!). I start gunicorn using supervisor, which reports that it is indeed running:
(in shell:)
supervisorctl status my_app
my_app RUNNING pid 1002, uptime 0:29:51
Here's the boilerplate script I used to start it:
#!/bin/bash
#script variables
NAME="gunicorn_myapp" # Name of process
DJANGODIR=/webapps/www/my_project # Django project directory
SOCKFILE=/webapps/www/run/gunicorn.sock # communicte using this socket
USER=app_user # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=my_project.settings # settings file
DJANGO_WSGI_MODULE=my_project.wsgi # WSGI module name
# Activate the virtual environment
cd $DJANGODIR
source ../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
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE
Here's the (condensed) nginx config file:
upstream my_server {
server unix:/webapps/www/run/gunicorn.sock fail_timeout=10s;
}
server {
listen 80;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
client_max_body_size 4G;
access_log /webapps/www/logs/nginx-access.log;
error_log /webapps/www/logs/nginx-error.log;
location /favicon.ico { access_log off; log_not_found off; }
location /static/ {
autoindex on;
alias /webapps/www/my_project/my_app/static/;
}
location /media/ {
autoindex on;
alias /webapps/www/my_project/my_app/media/;
}
location / {
proxy_pass http://my_server;
proxy_redirect off;
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://example.com;
break;
}
}
location /robots.txt {
alias /webapps/www/my_project/my_app/static/robots.txt ;
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/www/my_project/my_app/static/;
}
}
So: gunicorn is running, nginx is running ... what tests (and how?) should I perform to determine if gunicorn is doing the wsgi stuff properly (and if nginx is proxying the said stuff through correctly)?
Edit: I've narrowed the problem down to the communication between gunicorn and nginx via the unix socket. If I change the $SOCKFILE to be bound to 0.0.0.0:80 and stop nginx, then the app's pages are served from my website. The bad news is that the socket file strings are exactly the same between the two conf files, so I don't know why they aren't communicating. I suppose this means nginx isn't correctly fetching and passing the data through then?
Go to project directory :
cd projectname
gunicorn --log-file=- projectname.wsgi:application
and
sudo systemctl status gunicorn

Gunicorn is not binding my domain by using ".sock" file

I am trying to host multiple sites on VPS using sock file but the problem is that I can't see the website up and running using gunicorn sock. But I can't see my website live. I need to know how do I change the following screen showing my app binds with particular port instead of sock file or if it has to be a sock file then why I can't see it in browser at mydomain.com.
Gunicorn upscript is as follows:
#!/bin/bash
NAME="dressika" # Name of the application
DJANGODIR=/django/mydomain # Django project directory
SOCKFILE=/django/mydomain/run/gunicorn.sock # we will communicte using this unix socket
USER=django # the user to run as
GROUP=django # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=mydomain.settings # which settings file should Django use
DJANGO_WSGI_MODULE=mydomain.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source ../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 ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--bind=unix:$SOCKFILE \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--log-level=debug \
--log-file=-
With above settings gunicorn startup script runs fine but I couldn't see my site live on browser or client end. I guess I need to bind it with some port. I am not sure if my assumption is correct. My app settings.py shows in ALLOWED_HOSTS=['mydomain.com', 'www.mydomain.com]. Still the url isn't working.
My Nginx settings are:
upstream mydomain_server {
server 127.0.0.1:9500 fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
root /home/django/mydomain;
index index.html index.htm;
client_max_body_size 4G;
server_name mydomain.com www.mydomain.com;
keepalive_timeout 5;
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|woff|ttf)$ {
expires 365d;
}
# Your Django project's media files - amend as required
location /media {
alias /home/django/mydomain/media/;
}
# your Django project's static files - amend as required
location static/static-only {
alias /home/django/mydomain/static-only/;
}
# Django static images
location /static/mydomain/images {
alias /home/django/mydomain/static-only/images/;
}
# Proxy the static assests for the Django Admin panel
location /static/admin {
alias /usr/lib/python2.7/dist-packages/django/contrib/admin/static/admin;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://mydomain_server;
proxy_connect_timeout 60s;
}
}
I've also tried binding /home/django/mydomain/run/gunicorn.sock with upstream server instead of IP:Port but still couldn't see the site up and running.
I have the same problem, .sock doesn't create. This method helps me.
Prerequests:
Installed nginx: when you type in browser 127.0.0.1 - obtain "Wellcome to nginx...".
You install python2 or 3 no matter, and other stuffs: pip, django, gunicorn...
You installed and settled virtualenv. (in my case, I use virtualenvwrapper - this is good staffs, saves all you env in one folder: /home/user/.virtualenvs/)
You created django project, and when: python manage.py runserver -
you obtain "It works..." - this good news.
When you type gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application - you have the same result, as a step 4.
Next step for setting you dj.project throgh gunicorn to nginx:
You create file in /etc/systemd/system/any_file_name.service - you can named this file as you want, at DO - it names as gunicorn.service.
my method:
$cd /etc/systemd/system
$sudo touch gunicorn.service
and open it your favorite text editor
$sudo subl gunicorn.service
Inside it you write:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=vetal
Group=www-data
WorkingDirectory=/var/www/apple.net
ExecStart=/home/vetal/.virtualenvs/univ/bin/gunicorn --workers 3 --bind unix:/var/www/apple.net/mysite/mysite.sock mysite.wsgi:application
[Install] WantedBy=multi-user.target
ExecStart - what will be started by nginx, when your virualenv will be turned off. Do you remember, gunicorn was install through pip, when your env was turn on ?
-- bind unix:... - this address WHERE your .sock will created! Pay attention for this!
CHECK EVERY LETTER!TWISE!!! (of course with you links..)
Type:
$ls -l
if you see in attributes to your 'gunicorn.service' something:
-rw-r--r-- 1 root root 0 Янв 12 11:48 gunicorn.service
this means - this file is not executable, and you .sock - file will never created! Make next:
$sudo chmod 755 gunicorn.service
and check:
$ls -l
if you get:
-rwxr-xr-x 1 root root 305 Янв 11 19:48 gunicorn.service
this good! Everything allright!
Then you created nginx block, in /etc/nginx/site-available/ it likes next:
server {
listen 80;
root /var/www/apple.net;
server_name apple.net;
location = /favicon.ico { access_log off; log_not_found off; }
location = /static/ {
alias /var/www/apple.net/static/;
}
location / {
include proxy_params;
proxy_pass http://unix:/var/www/apple.net/mysite/mysite.sock;
} }
Notice: proxy_pass - must be identicaly correct with folder where .sock file created in gunicorn.service!
Copies this file to /sites-enable
$ sudo cp /etc/nginx/site-avaliable/apple.net /etc/nginx/site-enable
I don't have any domaine, so I modify my /etc/hosts file, add row:
127.0.0.10 apple.net
Very important steps!!!
$pkill gunicorn - this step kill daemon, which you may started before. gunicorn in this case, means name of file which you created before with .service extention, in /etc/systemd/system - folder.
Start gunicorn.service daemon:
$sudo systemctl start gunicorn
$sudo systemctl enable gunicorn
Start(or restart nginx)
$sudo /etc/init.d/nginx (re)start
Check your domane name in browser.
Since gunicorn is running on a socket, you need to bind to that socket, not to a port, in the upstream section.
upstream mydomain_server {
server unix:/home/django/mydomain/run/gunicorn.sock fail_timeout=0;
}
I have nginx serving up a .sock file from gunicorn. My typical gunicorn call looks like this:
exec gunicorn \
--pid /web/gunicorn.pid \
--workers '4' \
--name myapp \
--chdir /src/myapp \
--bind unix:/web/.sock \
--log-file=- \
myapp.wsgi:application
My nginx conf for / looks like this; the main difference seems to be that your proxy_pass statement doesn't point to the .sock file:
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:/web/.sock;
}

What's should Django ALLOWED_HOSTS be when using a unix socket?

I'm using a unix socket instead of a TCP port for gunicorn to serve my Django app from. However, when debug is off I get a 400 response unless I set ALLOWED_HOSTS = ['*']. What is a safer option than '*' in this scenario?
Here's my Gunicorn startup script(/opt/example.com/bin/gunicorn_start):
#!/bin/bash
NAME="myapp" # Name of the application
DJANGODIR=/opt/example.com/myapp # Django project directory
SOCKFILE=/opt/example.com/run/gunicorn.sock # we will communicate using this unix socket
USER= myuser # the user to run as
GROUP=mygroup # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=myapp.settings # which settings file should Django use
DJANGO_WSGI_MODULE=myapp.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source ../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 ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--log-level=debug \
--bind=unix:$SOCKFILE
Turns out I just needed to add my server's hostname. I had been using ['localhost', '127.0.0.1'] but since I added the following nginx config too, the app needed to allow the website's URL.
upstream blog_app_server {
# 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 unix:/opt/example.com/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name www.example.com example.com;
server_tokens off;
access_log /opt/example.com/logs/nginx-access.log;
error_log /opt/example.com/logs/nginx-error.log;
location /static/ {
alias /opt/example.com/static/;
}
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://blog_app_server;
break;
}
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Specifically I think it was the line proxy_set_header Host $http_host; that meant I needed to add the site's name to ALLOWED_HOSTS.