Django FastCGI 설정하기

기본적인 내용은 Django의 공식 매뉴얼을 참고하면 되는데, FastCGI 설정 중 삽질한 부분이 있어 메모를 남겨두고자 한다.

 

Rewrite 모듈 설정

  1. <VirtualHost 12.34.56.78>
    ServerName example.com
    DocumentRoot /home/user/public_html
    Alias /media /home/user/python/django/contrib/admin/media
    RewriteEngine On
    RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
    </VirtualHost>

 매뉴얼을 보면 위와 같이 작성하라고 나오는데, 여기서 /home/user/public_html/media 디렉토리가 존재한다면 굳이 Alias를 해줄 필요는 없다. 필자의 경우 media_admin으로 따로 관리자용 미디어 파일들을 연결해 쓰고 있다.
한가지 주의할 점은, RewriteRule의 두번째 인자로 써주는 "/$1"이 실제로는 서버의 루트 디렉토리에서 먼저 찾고 거기에 없으면 DocumentRoot 안에서 찾도록 되어 있다는 점이다. Ubuntu와 같은 배포판의 경우 /media 디렉토리에 cdrom 및 usb 장치들을 마운트하게끔 되어 있기 때문에, DocumentRoot가 하위의 media 디렉토리가 아닌 엉뚱한 곳에서 파일을 찾게 되는 문제가 있다.
따라서 설정파일에는 절대경로를 다 써주는 것이 좋다.

UNIX Socket 권한 문제

FastCGI 서버를 어떤 방식으로 이용하느냐에 따라 다른데, UNIX Socket 방식(파일로 소켓을 만드는 것)을 이용할 경우 Apache가 이 소켓 파일에 read/write 할 수 있는 권한이 있어야 한다.
그런데 Django에서 사용하는 flup 파이썬 패키지는 기본적으로 755 퍼미션으로 소켓 파일을 생성하기 때문에 퍼미션 에러로 인해 작동하지 않는 불상사가 생긴다.

 

이를 위해서는 flup 패키지 디렉토리(우분투의 경우 /var/lib/python-supported/python2.5/flup) 하위의 server/fcgi_base.py 파일을 수정하고, 소켓 파일을 담을 디렉토리의 그룹을 아파치와 동일하게 해주어 자기가 fcgi 서버를 띄워 소켓을 생성할 때 자동으로 아파치를 그룹으로 가지게끔 생성되도록 하면 된다.
필자의 경우 drwxrwsr-x  2 daybreaker www-data mysite.sock 이렇게 설정하였고(이 디렉토리 아래에 mysite.sock이 생성되게 설정함), fcgi_base.py 파일의 1012번째 줄 근처를 다음과 같이 수정하였다.

  1. sock.bind(self._bindAddress)
    if type(self._bindAddress) is str:
        os.chmod(self._bindAddress, 0775)

    sock.listen(socket.SOMAXCONN)

 mod_fastcgi 대신 mod_fcgid 이용하기

Apache 모듈인 mod_fastcgi는 역사적으로(?) 많은 비판을 받고 있는 모듈이다. 이에 대한 대안으로 mod_fcgid라는 것이 나왔고 Apache 2.x 이상에서는 이것이 더 권장되기도 하는데, 기본적으로 하는 일은 똑같지만 설정할 수 있는 옵션의 폭이 좀더 크다. 차이점으로는 mod_fastcgi가 좀더 다양한 형태의 셋업을 지원하지만, mod_fcgi가 좀더 폭넓은 파라메터 설정을 지원하고, 스스로 dispatcher 역할을 한다는 점이 다르다. 실제 사용해본 결과, mod_fastcgi를 이용할 때는 처음 실행할 때 (prefork 형태의 경우) 미리 설정된 수만큼의 프로세스가 다 떠있지만, mod_fcgid를 쓰면 이 모듈이 필요에 따라 알아서 그 갯수를 늘렸다 줄였다 하는 것을 볼 수 있었다.

 

위의 mod_fastcgi용 설정을 거의 그대로 쓰되, socket을 이용할 수 없기 때문에 FastcGIExternalServer directive는 사용할 수 없고 대신 dispatcher로부터 호출되는 mysite.fcgi 파일을 실제로 만들어주어야 한다. (위의 예에서는 이 파일이 없어도 socket을 통해 통신하고 flup 패키지가 알아서 dispatching을 해주는 방식)
다음과 같은 코드를 작성하여 mysite.fcgi로 저장하면 된다. 여기서 mysite.fcgi가 있는 디렉토리에 Django project 디렉토리인 mysite 디렉토리도 존재한다고 가정했다.

  1. #!/usr/bin/python
    from flup.server.fcgi import WSGIServer
    from django.core.handlers.wsgi import WSGIHandler
    import sys, os

    sys.path += [os.path.join(os.path.dirname(__file__))]
    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
    WSGIServer(WSGIHandler()).run()