TheWSGI specification provides a standard and efficient method fordynamic web applications to communicate with web servers. mod_wsgiprovides a method for simply deploying WSGI applications with Apache.WSGI is used to deploy applications written with frameworks and toolslike Django,Bottle,Web.py,Werkzug, Chery.py, TurboGears, and Flask. These guides outline thisinstallation and configuration process for deploying WSGIapplications.
Contents
Setthe Hostname
sudo vi /etc/hosts
Addseveral items, for example:
127.0.1.1 wsgiserver 127.0.0.1 webpyserver 127.0.0.1 bottleserver 127.0.0.1 djangoserver
Beforeyou begin installing and configuring the components described inthis guide, please make sure you've followed our instructions forsettingyour hostname.Issue the following commands to make sure it is set properly:
hostname hostname -f
Thefirst command should show your short hostname, and the second shouldshow your fully qualified domain name (FQDN).
InstallDependencies
Issuethe following commands to ensure that your system's packagerepositories and installed programs are up to date and that allrequired software is installed:
apt-get update apt-get upgrade apt-get install apache2 python-setuptools libapache2-mod-wsgi
Yourapplication may require additional dependencies. Install theseeither using the Ubuntu package tools or by using the easy_installcommand included in python-setuptoolsbefore proceeding.
ConfigureWSGI Handler
Inorder formod_wsgito be able to provide access to your application, you will need tocreate a application.wsgifile inside of your application directory. The application directoryshould be locatedoutsideof yourDocumentRoot.The following three sections each present a differentapplication.wsgiexample file to illustrate the basic structure of this file:
BasicHello World WSGI Configuration
Inthis example, the application is stored in/var/www/testwsgi/directory. Modify this example and all following examples toconform to the actual files and locations used in your deployment.
File:/var/www/testwsgi/main.wsgi
import os import sys sys.path.append('/var/www/testwsgi') os.environ['PYTHON_EGG_CACHE'] = '/var/www/testwsgi/.python-egg' def application(environ, start_response): status = '200 OK' output = 'Hello World!' response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))] start_response(status, response_headers) return [output]
Youmust append the path of your application to the system path asabove. The declaration of the PYTHON_EGG_CACHEvariable is optional but may be required for some applications whenWSGI scripts are executed with the permissions of the web server.The WSGI application must be callable as "application",regardless of how the application code is structured.
Createa new apache site
sudo vi /etc/apache2/sites-available/testwsgi
Andadd the content
<VirtualHost *:80> ServerAdmin songguo.hit@gmail.com ServerName wsgiserver # ServName is configured in /etc/hosts # DocumentRoot /var/www/testwsgi <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/testwsgi> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> # ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ WSGIScriptAlias /wsgitest /var/www/testwsgi/main.py <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Andactivate the site
sudo a2ensite testwsgi sudo /etc/init.d/apache2 reload
Thenopen your web browser and browse to
http://wsgiserver/wsgitest
Youshould see a ‘Hello World!’ message
Web.pyWSGI Configuration
Considerthe following example Web.pyapplicationwhich is embeded in a application.wsgifile. The Web.pyFrameworkmust be installed in order for the following application to runsuccessfully.
Fileexcerpt:/srv/www/ducklington.org/application/application.wsgi
import web
urls = (
'/(.*)', 'hello'
)
class hello:
def GET(self, name):
if not name:
name = 'World'
return 'Hello, ' + name + '!'
if __name__ == "__main__":
app.run()
app = web.application(urls, globals(), autoreload=False)
application = app.wsgifunc()
Configureapache is similar to WSGI configuration above.
Bottle WSGI Configuration
Considerthe following exampleapp.wsgifile for Django applications:
Fileexcerpt:/home/songguo/bottle2/app.wsgi
import os, sys, bottle # must be sys.path = ['/home/songguo/bottle2/'] + sys.path os.chdir(os.path.dirname(__file__)) # This loads your application import file_download, hello application = bottle.default_app()
Fileexcerpt:/home/songguo/bottle2/file_download.py
from bottle import route, static_file, run, template @route('/download/<filename:path>') def download(filename): return static_file(filename, root='/home/songguo/Downloads', download = filename) @route('/images/<filename:re:.*\.png>') def send_image(filename): return static_file(filename, root = '/home/songguo/Pictures/pngs', mimetype = 'image/png') @route('/') @route('/hello') def hello(): return "Hello World!" # return template('hello') # run(host = 'localhost', port = 8000)
Whenyou run your application via mod_wsgi, it is imperative to removethe run()statement from your code, otherwise it won’t work here.
Fileexcerpt:/home/songguo/bottle2/hello.pyomitted.
Createa new apache site
sudo vi /etc/apache2/sites-available/testbottle
Andadd the content
<VirtualHost *:80> ServerAdmin songguo.hit@gmail.com ServerName bottleserver # ServName is configured in /etc/hosts <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /home/songguo/bottle2> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> # ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ WSGIDaemonProcess bottleserver processes=2 threads=15 display-name=%{GROUP} WSGIProcessGroup bottleserver WSGIScriptAlias / /home/songguo/bottle2/app.wsgi <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Andactivate the site
sudo a2ensite testbottle sudo /etc/init.d/apache2 reload
DjangoWSGI Configuration
Considerthe following exampleapplication.wsgifile for Django applications:
Fileexcerpt:/home/songguo/django/songuo/apache/django.wsgi
import os import sys path = '/home/songguo/django/songuo' if path not in sys.path: sys.path.insert(0, path) os.environ['DJANGO_SETTINGS_MODULE'] = 'songuo.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
Djangoapplication directory structrue:
Djangomust be installed on your system and a working Django applicationbefore this example will function. The "DJANGO_SETTINGS_MODULE"points to the "settings.pyfile for your application, which would be located in the"/home/songguo/django/songuo/songuo/settings.pyin the case of this example.
Createa new apache site
sudo vi /etc/apache2/sites-available/testdjango
Andadd the content
<VirtualHost *:80> ServerAdmin songguo.hit@gmail.com ServerName djangoserver # ServName is configured in /etc/hosts DocumentRoot /home/songguo/django/songuo <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /home/songguo/django/songuo> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> # ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ WSGIDaemonProcess djangoserver processes=2 threads=15 display-name=%{GROUP} WSGIProcessGroup djangoserver WSGIScriptAlias / /home/songguo/django/songuo/apache/django.wsgi Alias /static /home/songguo/django/songuo/static <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Andactivate the site
sudo a2ensite testdjango sudo /etc/init.d/apache2 reload
ConfigureApache
Deploythe followingVirtualHostconfiguration and modify the paths and domains to reflect therequirements of your application:
Fileexcerpt:Apache``VirtualHost`` Configuration
/etc/apache2/sites-available/name
<VirtualHost *:80> ServerAdmin [songguo.hit@gmail.com] # ServName is configured in /etc/hosts ServerName [server name in /etc/hosts] # DocumentRoot /path/to/your/document/root <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /path/to/your/app> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> # ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ WSGIDaemonProcess [server name] processes=2 threads=15 display-name=%{GROUP} WSGIProcessGroup [server name] WSGIScriptAlias /[access prefix path] /path/to/your/app/name.wsgi # Alias /static /path/to/your/app/static <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Inthis example, theWSGIScriptAliasdirective tells Apache that for this VirtualHost,all requests below /should be handled by the WSGI script specified. The series of fourAliasdirectives allow Apache to serve therobots.txtandfavicon.icofiles as well as all resources beneath the /imagesand/staticlocations, directly from the DocumentRootwithout engaging the WSGI application. You can add as manyAliasdirectivesas you require.
Whenyou have configured your ApacheVirtualHost,issue the following command to restart the web server:
/etc/init.d/apache2 restart
Youwill need to restart the web server every time theapplication.wsgifile changes. However, all other modifications to your applicationdo not require a web server restart. Congratulations! You have nowsuccessfully deployed a WSGI application usingmod_wsgi.