Nginx & Django on Webfaction (Part 1b) – Configuring

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 , and with your actual values.

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:

Django Welcome Screen

Django Welcome Screen

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: , , ,

9 Responses to “Nginx & Django on Webfaction (Part 1b) – Configuring”

  1. Richard Cooper Says:
    September 8th, 2009 at 18:02

    Fixed a small problem with the path to the django.sock file. It should work now.

  2. tim Says:
    September 18th, 2009 at 16:10

    So far so good….can’t wait till the next part.

  3. Computers & Tech Says:
    September 20th, 2009 at 22:59

    Hello there,
    Cool post, I just found it and I am already a fan.

  4. Nginx & Django on Webfaction - Part 2 | Fighting Rabbits Says:
    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 […]

  5. Chikiro Says:
    November 30th, 2009 at 09:37

    I don’t have django.sock in my project directory. Where can I find it?

  6. Chikiro Says:
    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.

  7. Gordon Swanston Says:
    May 28th, 2010 at 04:25

    Very nice thread, thank you for investing the time to help others here

  8. Matt Schick Says:
    April 26th, 2011 at 01:35

    Not sure how no one has hit this issue, perhaps it’s because I’m running nginx 1.0.0, but I had to configure nginx to not run in daemon mode. Anything that supervisord launches cannot run as a daemon because it will assume that the process needs to be restarted. I added the following at the top level of my nginx.conf:

    daemon off;

  9. Nginx Webfaction HOWTO | Nginx Lighttpd Tutorial Says:
    June 3rd, 2011 at 15:16

    […] Nginx & Django on Webfaction (Part 1b) – Configuring […]

Leave a Reply