Nginx & Django on Webfaction (Part 1b) – Configuring
Posted by Richard Cooper | Filed under Coding, Random, Setup, webfaction
In Part 1a of this series we compiled Nginx and Installed Django in this next part we are going to configure nginx and Django and get our welcome page displaying.
First lets configure nginx, the default conf file looks like this:
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443; # server_name localhost; # ssl on; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_timeout 5m; # ssl_protocols SSLv2 SSLv3 TLSv1; # ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
Now that we have seen the default file let’s back it up and start from scratch :)
cd ~/webapps/<myapp>/conf mv nginx.conf nginx.conf.bak nano nginx.conf
First we need to set our basic Nginx properties:
#2 workers x 1024 connections gives us some resiliance and should be enough for most sites. worker_processes 2; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server { listen myport; server_name mydomain; #You will need to change the next line to something bigger if you want to accept uploads over 5Mb client_max_body_size 5m; } }
Remember to replace myport and mydomain with your actual values from Part 1a!
Next let’s setup our http server config to serve our static media (You could setup a static only app to serve your media from the main Apache Instance, but let’s do it this way as a learning exercise.) We are going to add one location for all our static media, and one location just to serve the favicon. Edit the http section to look like this:
http { include mime.types; default_type application/octet-stream; server { listen myport; server_name mydomain; client_max_body_size 5m; location /media/ { alias /home/<myusername>/webapps/<myapp>/<myproject>/media/; } location ~* /favicon.ico { root /home/<myusername>/webapps/<myapp>/<myproject>/media/img/; #Let's not waste time logging this access... access_log off; } } }
Again remember to replace
Right now let’s setup nginx to talk to our fastcgi django process add this section into the configuration file after the favicon.ico location:
location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; fastcgi_pass unix:/home/<myusername>/webapps/<myapp>/<myproject>/django.sock; fastcgi_pass_header Authorization; fastcgi_hide_header X-Accel-Redirect; fastcgi_hide_header X-Sendfile; fastcgi_intercept_errors off; include fastcgi_params; }
Our nginx.conf should now look like this:
#2 workers x 1024 connections gives us some resiliance and should be enough for most sites. worker_processes 2; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server { listen myport; server_name mydomain; client_max_body_size 5m; location /media/ { alias /home/<myusername>/webapps/<myapp>/<myproject>/media/; } location ~* /favicon.ico { root /home/<myusername>/webapps/<myapp>/<myproject>/media/img/; #Let's not waste time logging this access... access_log off; } location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; fastcgi_pass unix:/home/<myusername>/webapps/<myapp>/<myproject>/django.sock; fastcgi_pass_header Authorization; fastcgi_hide_header X-Accel-Redirect; fastcgi_hide_header X-Sendfile; fastcgi_intercept_errors off; include fastcgi_params; } } }
We need to make a slight change to the fastcgi_params file that is being included so that it works correctly with Django. Comment out the following line by placing a # in front of it:
fastcgi_param SCRIPT_NAME $fastcgi_script_name;and add this just above it:
fastcgi_param PATH_INFO $fastcgi_script_name;You can download the complete sample files here zip / gz
Django configuration is pretty simple as we can use the default settings file for now:
# Django settings for myproject project. DEBUG = True TEMPLATE_DEBUG = DEBUG ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) MANAGERS = ADMINS DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. DATABASE_NAME = '' # Or path to database file if using sqlite3. DATABASE_USER = '' # Not used with sqlite3. DATABASE_PASSWORD = '' # Not used with sqlite3. DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # although not all choices may be available on all operating systems. # If running in a Windows environment this must be set to the same as your # system time zone. TIME_ZONE = 'America/Chicago' # Language code for this installation. All choices can be found here: # http://www.i18nguy.com/unicode/language-identifiers.html LANGUAGE_CODE = 'en-us' SITE_ID = 1 # If you set this to False, Django will make some optimizations so as not # to load the internationalization machinery. USE_I18N = True # Absolute path to the directory that holds media. # Example: "/home/media/media.lawrence.com/" MEDIA_ROOT = '' # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash if there is a path component (optional in other cases). # Examples: "http://media.lawrence.com", "http://example.com/media/" MEDIA_URL = '' # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". ADMIN_MEDIA_PREFIX = '/media/' # Make this unique, and don't share it with anybody. SECRET_KEY = '4#(%&p)^37k2ihr-q-k73qau44ec&8k==gyxb)1+$pck@4+qp=' # List of callables that know how to import templates from various sources. TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', # 'django.template.loaders.eggs.load_template_source', ) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', ) ROOT_URLCONF = 'myproject.urls' TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. ) INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', )
Finally we need to start our servers:
cd ~/webapps/<myapp>/ ./sbin/nginx cd <myproject> python2.5 manage.py runfcgi maxchildren=1 maxspare=1 method=prefork socket=$PWD/django.sock pidfile=$PWD/django.pid > /dev/null 2>&1 $
If you haven’t done it already mount your app in a domain from the webfaction control panel and then browse to the correct url and you should see the following:
So there you have it – we have installed and configured Nginx + Django however we still have a few thing’s to do… In Part 2 I’ll show you a couple of ways to make sure that our site isn’t down for long if the web-server is rebooted or Django crashes.
In Part 3 I’ll show you how to hand off file uploads to Nginx and get a fancy upload progress bar into the bargin :D
This post was brought to you by the letters L and A and the following websites.
http://forum.webfaction.com/viewtopic.php?id=1981
https://calomel.org/nginx.html
Tags: django, installation, nginx, webfaction

September 8th, 2009 at 18:02
Fixed a small problem with the path to the django.sock file. It should work now.
September 18th, 2009 at 16:10
So far so good….can’t wait till the next part.
September 20th, 2009 at 22:59
Hello there,
Cool post, I just found it and I am already a fan.
September 21st, 2009 at 19:18
[...] after finishing Part 1a and Part 1b you have a working Nginx + Django install on Webfaction. In this installment I’m going to [...]
November 30th, 2009 at 09:37
I don’t have django.sock in my project directory. Where can I find it?
November 30th, 2009 at 11:58
It was a flups problem, not nginx or django at all. I reinstalled flups and now it works :)
Thank you for a very good tutorial.
May 28th, 2010 at 04:25
Very nice thread, thank you for investing the time to help others here