Django Installation & Configuration using Nginx+FastCGI+PosgtreSQL

Django box

Configuring PostgreSQL

  1. Install PostgreSQL
  2. Create a django user

    sudo -u postgres createuser -P django_user

    Also you can alter the user attributes as follow:

    sudo su -
      passwd postgres
      su postgres
      psql template1
      ALTER USER django_user WITH ENCRYPTED PASSWORD 'mypassword';
      
  3. Create the Django project database::
    sudo -u postgres psql template1
    CREATE DATABASE django_db OWNER django_user ENCODING ‘UTF8’;
  4. Give comoda access (pg_hba.conf):
  5. local   django_db        django_user                      md5
    

Configuring access to PostgreSQL

  1. Install psycopg2 Python package.
  2. Verify the installation

    You should be all set now, but let’s verify this right away. Open the
    shell and run the following instructions inside the python shell (start
    off with the python command):

    >>> import django
    >>> print django.VERSION
    (0, 97, 'pre')
    >>> import psycopg2
    >>> psycopg2.apilevel
    '2.0'
  3. Configure Django project settings (settings.py on the project directory):
    DATABASE_ENGINE = 'postgresql_psycopg2'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
    DATABASE_NAME = 'django_db'             # Or path to database file if using sqlite3.
    DATABASE_USER = 'django_user'             # Not used with sqlite3.
    DATABASE_PASSWORD = 'XXXXXX'         # Not used with sqlite3.
    DATABASE_HOST = 'localhost'             # Set to empty string for localhost. Not used with sqlite3.
    DATABASE_PORT = '5432'             # Set to empty string for default. Not used with sqlite3.
  4. Install Django Python package.
  5. Run syncdb from Django project directory:
    python manage.py syncdb

Running Django project like FastCGI

  1. Install Django and Flup Python packages.
  2. You need also to start Django fastcgi server (from the project folder):
    python manage.py runfcgi host=127.0.0.1 port=8000 --settings=settings

    If you need to add something to pythonpath:

    python manage.py runfcgi host=127.0.0.1 port=8000 --settings=settings --pythonpath=/a/path/to/somewhere/

Configuring Nginx to serve the Django FastCGI service

  1. Configure Nginx:
    server {
    listen   80;
    #server_name  localhost;
    location / {
    root   html;
    rewrite  ^ https://172.2.30.31$request_uri  redirect;
    }
    access_log  /var/log/nginx/localhost.access.log;
    }
    server {
    listen   443;
    # server_name  localhost;
    access_log  /var/log/nginx/localhost-ssl.access.log;
    ssl_prefer_server_ciphers   on;
    ssl  on;
    ssl_certificate      /etc/nginx/ssl/all_com.crt;
    ssl_certificate_key  /etc/nginx/ssl/all_com.key;
    ssl_session_timeout  5m;
    #ssl_protocols  SSLv2 SSLv3 TLSv1;
    #ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    location / {
    # host and port to fastcgi server
    fastcgi_pass 127.0.0.1:8000;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;
    fastcgi_pass_header Authorization;
    fastcgi_intercept_errors off;
    }
    #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   /var/www/nginx-default;
    }
    }
  2. Access to http://<django-server>/.

Debian package guide: Latest Python policy

From a couple of days ago, I has been recycling my knowledge about Debian-Python packages. Debian 6.0 is currently next to be released and we’ll need effort to adapt many of own packages from etch to squeeze.

I’ve been following the Debian-Python mailling list from one year ago and I know many several troubles, changes or  improvements  which was occurred during this period.

As a brief resume, many things has changed: default Python interpreter for Debian 6.0,  the backend frameworks to build packages (CDBS with python-distutils.mk, Python-central or Python-support) …

All these changes have been discussed on Debian Wiki and have been formalized as the new Python Policy. This policy is already accessible on http://www.debian.org/doc/packaging-manuals/python-policy/.

Flushing ARP table entries for one specific IP

In some cases, the network elements use caching strategies in order to improve the network throughput. In this enviroment, is frequently that we are using subsystems like LVS with purpose of balance one service IP between a couple of hosts. In this cases, we can have several problems when we want use HA system because some network switch don’t releases  the old ARP entry of the service IP (due to caching effect). To avoid this aim, we’d use arping to force releases of  the old ARP entry.

  arping -v -c 1 -i eth0 -S 192.40.0.200 -t ff:ff:ff:ff:ff:ff 192.40.0.200
  arping: invalid option -- '-'
  Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination
   -f : quit on first reply
   -q : be quiet
   -b : keep broadcasting, don't go unicast
   -D : duplicate address detection mode
   -U : Unsolicited ARP mode, update your neighbours
   -A : ARP answer mode, update your neighbours
   -V : print version and exit
   -c count : how many packets to send
   -w timeout : how long to wait for a reply
   -I device : which ethernet device to use (eth0)
   -s source : source ip address
   destination : ask for what ip address

For example, we can use this tip in the network/intefaces conffile:

auto eth0
iface eth0 inet static
  address 10.240.97.99
  netmask 255.255.255.0
  post-up arping -v -c 1 -i eth0 -S 192.40.0.99 -t ff:ff:ff:ff:ff:ff 192.40.0.99

Proxying with Nginx

nginx logo

Today, something refer to Nginx and proxy rules. The tips showed bellow aren’t a advanced rules but should be valid for 80% of all cases that we should want to us.

server {
  listen   8008;
  server_name server.net;
  access_log  /var/log/nginx/server.net.access.log;

  location /reflector/mcast {
    proxy_pass        http://93.37.29.30:80;
    include /etc/nginx/include-enabled/proxy_settings.conf;
    # Other settings related to proxy: headers, timeouts ...
    rewrite  ^/reflector/mcast/8$  http://93.37.29.30:80/video.php?channel=8 redirect;
    rewrite  ^/reflector/mcast/12$  /video.php?channel=12  break;
  }
  ...
}

The /etc/nginx/include-enabled/proxy_settings.conf would be something like this:

proxy_set_header  X-Real-IP  $remote_addr;
proxy_set_header  X-Forwarded-For  $remote_addr;
proxy_read_timeout 300;

The first rewrite rule defines a 302 redirection behavior. The server respond to client a 302 response refer to http://93.37.29.30:80/video.php?channel=8. The second one, respond a 20X response. Petition will be rewrite to /video.php?… and it’ll be delegate to proxy_pass module. In this case, the server implement a reverse proxy behavior.
Observe next items:

  • All petitions like /videos/ are proxified to http://10.13.30.26:8004/videos/:
    location /videos/ {
      proxy_pass        http://10.13.30.26:8004;
      include /etc/nginx/include-enabled/proxy_settings.conf;
    }
  • All petitions like /media/video.mpeg are proxified to http://10.14.20.41:8004/videos/video.mpeg:
    location /media/ {
      proxy_pass        http://10.14.20.41:8004/;
      include /etc/nginx/include-enabled/proxy_settings.conf;
      rewrite  ^/media/(.*)$ /videos/$1  break;
    }
  • All petitions like /media/8 are proxified to http://10.14.20.42:8004/?video=8:
    location /media/ {
      proxy_pass        http://10.14.20.42:8004/;
      include /etc/nginx/include-enabled/proxy_settings.conf;
      rewrite  ^/media/(.*)$ /?video=$1  break;
    }

Finally, next rule uses $arg_ special var to refer the get parameters in the URI. In this case, this server expect URLs like “/play?mo=video.mpeg” and it’ll try to serve video.mpeg storaged on /var/www.

location /play {
  root /var/www/;
  rewrite ^/play /$arg_mo redirect;
}

Enjoy it!.