• Skip to main content

zoiaorg

Tech, Strategy, and other interesting things by Roberto Zoiaby Roberto Zoia

  • Articles
  • Book Reviews
  • Effective Goal Setting
  • What I’m Reading
  • Archive
  • About

Cómo correr Django (y Python) usando Apache y FastCGI

2006-12-15 by Roberto Zoia

Resumo en este post como hacer funcionar Django en un servidor Linux con CentOS 4.4 usando Apache 2 y FastCGI. Estas cosas están dispersas en Internet, la principal finalidad del post es tenerlas juntas en algún sitio.

Por qué FastCGI y no mod_python

El problema real es que mod_python y mod_php no se llevan bien, y de hecho en CentOS 4.4, usando mod_php, MySQL y mod_python, este último no funciona. Aquí y aquí (If you get a segmentation fault) se explican las posibles causas. Al parecer tiene que ver con el hecho de Apache usa la librería expat del sistema (y la precarga cuando se inicia el servidor de web), mientras que mod_python usa la versión de expat que fue compilada en la distribución de Python que tenga el sistema operativo. Si las dos versiones no coinciden, se produce un segmentation fault. También puede deberse a un cruce similar entre las librerías de MySQL, mod_php y mod_python, pero el resultado final es similar.

En los dos casos Apache sigue corriendo y mod_python se reinicia, pero nuestro programa en Python no se ejecuta. El segfault queda registrado en el log de errores de Apache (/var/log/httpd/error_log o algún lugar cercano, dependiendo de esté instalado Apache) y el navegador queda en blanco.

Y por eso la necesidad de usar fastcgi para correr Django.

Algunas consideraciones preliminares

  • El sistema en el que he hecho la instalación es un servidor con CentOs 4.4 y Python 2.3.4. (Al parecer no hay modo fácil de actualizar el Python del CentOs a 2.5 o por lo menos a 2.4 sin que se rompan muchas cosas). Estamos usando Apache2.

  • Se supone que este servidor ya tiene Django instalado, y que nuestra aplicación no tiene problemas con el servidor de desarrollo que trae Django. (Esto no es un tutorial de Django… la documentación de Django explica perfectamente como instalarlo).

  • Si buscamos un poco en Google, muchas páginas insisten en que si queremos instalar fastcgi y python, necesitamos instalar una librería de python llamada flup; y, si la versión de python es 2.3 o menor, también necesitamos instalar una librería llamada eunuchs. Porque a Python 2.3 le falta algo… la capacidad de escribir socket pairs, un tema que no viene al caso ahora.
    Bien, si lo que queremos es instalar Django, ninguna de estas dos librerías es necesaria. Django, a partir de la versión 0.95, trae su propia implementación de flup, y no necesita instalar eunuchs.

Aclarémonos dónde están las cosas

Estamos instalando django con la siguiente configuración, quizá no muy usual:

  • El DocumentRoot de nuestro servidor Apache es /var/www/html.
  • El directorio con el proyecto de Django es /home/django/prog.
  • El directorio con los archivos .css, imágenes, y demás que necesitan las páginas web es, para el proyecto de Django, /home/django/progmedia.
  • El archivo settings.py está en /home/django/prog/settings.py, que es lo normal.
  • Se accede a nuestro programa a través del URL http://example.com/prog.

Instalar FastCGI

  • Para fastcgi con CentOS es necesario usar la opción top_dir, porque por defecto fastcgi (como debe ser) trata de instalarse en /usr/local/lib en vez de en /usr/lib.
$ make top_dir=/usr/lib/httpd[/bash]
  • Si la compilación terminar sin errores, instalamos fastcgi con el comando
# make top_dir=/usr/lib/httpd install

La solución es crear un directorio en /tmp:

# mkdir -p /tmp/fcgi/dynamic
# chown apache:apache -R /tmp/fcgi
# chmod 755 -R /tmp/fcgi
  • Ahora hay que decirle a Apache que queremos usar el módulo fastcgi que acambamos de instalar. Creamos el archivo /etc/httpd/conf.d/fastcgi.conf:
LoadModule fastcgi_module modules/mod_fastcgi.so
<IfModule mod_fastcgi.c>;
    # Tenemos que decirle a fastcgi dónde puede guardar la información de sus conexiones, porque
    # no estamos usando el directorio por defecto.
        FastCgiIpcDir       /tmp/fcgi/
    # Asociamos los archivos de extensión .fcgi a fastcgi
        AddHandler      fastcgi-script .fcgi
</IfModule>

Recargamos la configuración de Apache y vemos en el /var/log/httpd/error_log si todo ha ido bien.

# tail -f /var/log/httpd/error_log

(esta ventana se pude quedar abierta hasta que estemos seguros que el fastcgi funciona y bien)
En otra ventana:

# service httpd reload

RewriteEngine y ExecCGI

Para poder usar el RewriteEngine en el directorio raíz (más abajo se explica para qué lo necesitamos), añadimos la opción FileInfo a la directiva AllowOverride del directorio raíz del servidor web.

#
<Directory "/var/www/html">
#
# (... aquí he borrado los comentarios)
#
#  Añadimos ExecCGI a las opciones
     Options Indexes FollowSymLinks IncludesNoExec <strong>ExecCGI</strong>
# (... más comentarios)
# Añado el FileInfo para que me deje usar mod_rewrite en /home/www
     AllowOverride AuthConfig <strong>FileInfo</strong>

Nuevamente recargo Apache y veo en el error_log si todo va bien.

Un puente entre Apache y Python

  • Copiamos fcgi.py a la raíz del servidor web, cambiarmos propietario a apache y nos aseguramos de que apache pueda leer el archivo:
# cp fcgi.py /var/www/html
# chown apache:apache /var/www/html/fcgi.py
# chmod 755 /var/www/html/fcgi.py
#!/usr/bin/python
import sys, os
# Add a custom system path
sys.path.insert(0,"/home/django")
# switch to user project
os.chdir("/home/django/prog")
os.environ['DJANGO_SETTINGS_MODULE'] = "prog.settings"
from fcgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler
WSGIServer(WSGIHandler()).run()

Idem, le cambio el propietario y permisos para que pueda ser ejecutado por Apache.

# chown apache:apache /var/www/html/prog.fcgi
# chmod 755 /var/www/html/prog.fcgi

Rewrite rules

Como dice el manual de Apache, ”Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo.” — Brian Moore, bem@news.cmc.net
A continuación vamos a escribir unas reglas (”Rewrite rules”) de modo que cuando el usuario escriba el URL de nuestro programa en el navegador, Apache realmente redireccione la llamada al script prog.fcgique acabamos de escribir. Este script, a su vez, llamará al programa escrito con Django en /home/django/prog.

Explico esto en detalle porque aunque al final el resultado sea solamente dos o tres líneas en un archivo de configuración, si no entendemos qué estamos haciendo, después tendremos problemas… causados por nosotros mismos.

Dentro del programa en Django, los distintos añadidos al URL a la derecha de sccr/ sirven para direccionar al usuario, a través del módulo urls.py, a las distintas partes de nuestro programa.

Por ejemplo,

        http://example.com/prog/admin
        http://example.com/prog/correo
        http://tierramedia.oficinas/prog.fcgi/prog/admin/
        http://tierramedia.oficinas/prog.fcgi/prog/correo/

Los rewrite rules se pueden poner en muchos sitios distintos. Por ejemplo, en el archivo .htaccess en la raíz del servidor web:

RewriteEngine On
RewriteRule ^(prog\.fcgi/.*)$ - [L]
RewriteRule ^(prog/.*)$ prog.fcgi/$1 [L]

Con estas reglas, estamos diciendo dos cosas:
Como anteriormente hemos indicado a Apache en el archivo fastcgi.conf que toda extensión .fcgi en el directorio raíz debe procesarse con el módulo fastcgi, una vez reescrito el URL Apache ejecutará el script sccr.fcgi.

<Directory /var/www/html>
   RewriteEngine On
   RewriteRule ^(prog\.fcgi/.*)$ - [L]
   RewriteRule ^(prog/.*)$ prog.fcgi/$1 [L]
</Directory>

Otros directorios de Django

Por último, si tenemos un directorio dentro del proyecto para el media, necesitamos decirle a Apache que asocie el URL con el directorio>. Por ejemplo, http://example.com/progmedia con el directorio /home/django/progmedia. Para eso creamos o añadimos al archivo /etc/httpd/conf.d/prog.conf:

Alias /progmedia /home/django/progmedia

Y listo. Ahora deberíamos tener nuestro servidor Apache funcionando con Python, Django y FastCGI.

Filed Under: Legacy

Did you like this article?

Join our FREE Newsletter and receive updates directly to your inbox.

We hate SPAM. We'll keep your email address safe.

  • What I’m Focused on Now
  • Español
  • Privacy Policy

Copyright © 2021 Roberto Zoia
zoia.org runs on WordPress using a customized version of the Parallax Pro Theme for the Genesis Framework.

This website uses cookies to improve your experience.Accept
Privacy & Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled

Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.

Non-necessary

Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.