Personal tools
You are here: Home Documentation Tutorials Installing and setting up Grok under mod_wsgi Configuring a Grok site under mod_wsgi

Configuring a Grok site under mod_wsgi

Grok can be installed with setup tools and a Grok site can be easily created using the included grokproject tool.
Grok can run behind any WSGI server. This tutorial will show how to install Grok behind the Apache web server and mod_wsgi on a brand new Linux virtual server.
Page 5 of 5.

As mentioned before, Grok can run behind any WSGI server, not just the paster server used by default. Now that we have a working mode_wsgi, we will show how to run Grok behind it.

We assume that you may already have a working application that you want to integrate with mod_wsgi. If that's not the case, please create one following the installation tutorial that you can find elsewhere on this site. For the purposes of this example, we'll assume that a Grok application named 'hello' was just created and that we want to serve it from behind Apache using mod_wsgi.

Getting the Grok application ready for mod_wsgi

WSGI applications use 'entry points' to let the WSGI server how to run the program. The entry point is usually a simple Python script that provides a function for calling the application and passing in the appropriate initialization file to the server. Some servers, like the paster server, need just the path to the .ini file, which is what we normally use to start up a Grok application. That doesn't mean there's no entry point script for paster. The entry point in fact is defined in the setup.py file that is created by grokproject when a new project is initialized. Take a look at the last few lines of the file:

[paste.app_factory]
main = grokcore.startup:application_factory
debug = grokcore.startup:debug_application_factory

The heading paste.app_factory tells the server where to find the factory functions for each section of the .ini file. In Grok, a general application factory function is defined in the grokcore.startup package, which is what paster uses to start applications.

However, mod_wsgi requires a path to the factory, which would be cumbersome to include in our configuration, because that would mean that it would need to point to a file inside the grokcore.startup egg, and since eggs include the version number, a simple update could crash our site if the old egg is removed. It would be better to have our own factory defined inside the application package.

Given that the factory code can be almost identical from project to project, it would be good to have it included automatically when we create the project, to avoid having to recreate the same script every time. Fortunately for us, Grok's use of buildout turns out to be very helpful in this case, since there is a buildout recipe available that creates the WSGI application factory for us.

The recipe is called collective.recipe.modwsgi. To use it, simply add a part to the buildout named, for example, wsgi_app. The recipe requires two parameters, the first being the eggs that have to be made available to the Python process that will run the app under WSGI and the second the path to the configuration file that will be used for the site. This last parameter value is the usual parts/etc/deploy.ini path we have been using for running the application under paster. That's it. Edit the buildout.cfg file parts list to look like this:

parts =
    eggbasket
    app
    i18n
    test
    mkdirs
    zpasswd
    zope_conf
    site_zcml
    zdaemon_conf
    wsgi_app
    deploy_ini
    debug_ini

Next, add the following section anywhere on the file:

[wsgi_app]
recipe = collective.recipe.modwsgi
eggs = ${app:eggs}
config-file = ${buildout:directory}/parts/etc/deploy.ini

There. Note that the eggs parameter simply points back to the main egg section defined at the start of the buildout, to avoid repetition.

When the buildout is run again, we'll find a parts/wsgi_app directory (or whichever name we used for the buildout part. Inside that directory, there will be a wsgi file that can be used as is by mod_wsgi to run the application.

Configuring an Apache site to use mod_wsgi

The last step is to add a site to the Apache server that uses mod_wsgi to serve our application. This is standard mod_wsgi configuration, we'll just add the path to the application factory that we created in the previous section.

To set up the virtual host, create a file in the /etc/apache2/sites-available directory and call it, for example, grok. Put the following in it, assuming your Grok application is at /home/cguardia/grok/hello:

WSGIPythonHome /usr
WSGIDaemonProcess grok user=cguardia group=cguardia threads=4 maximum-requests=10000

<VirtualHost *:80>
  ServerName wsgi.example.com
  WSGIScriptAlias /hello /home/cguardia/grok/hello/parts/wsgi_app/wsgi
  WSGIProcessGroup grok
  WSGIPassAuthorization On
  WSGIReloadMechanism Process
  SetEnv HTTP_X_VHM_HOST http://wsgi.example.com/hello
</VirtualHost>

This will run mod_wsgi in 'daemon' mode, which means it will launch a number of processes to run the configured WSGI application instead of using the apache process. If you are using virtualenv, the site-packages directory of the virtual Python used to run it needs to be passed in the WSGIPythonHome variable. To tell mod_wsgi which WSGI application to run, we use the WSGIScriptAlias directive and pass it the path to application factory that we created earlier.

Note that we assign a user and group to run the process. It is required that this user has access to the application directory.

The PYTHON_EGG_CACHE directory

Note that when the application is started, all eggs will be automatically extracted in the PYTHON_EGG_CACHE directory, normally "~/.python-eggs". This directory depends of the HOME environment variable. The HOME apache user www-data is /var/www. You may get the error "[Errno 13] Permission denied: '/var/www/.python-eggs'" in your error.log apache file if you don't configure the user or python-eggs variable in the WSGIDaemonProcess directive. You can also add a python-eggs parameter to tell mod_wsgi to use an alternative directory for the egg cache:

WSGIDaemonProcess grok threads=4 maximum-requests=10000 python-eggs=/tmp/python-eggs

In this example, the process belongs to www-data.www-data and python-eggs cache directory will be "/tmp/python-eggs".

Running the application

Once the configuration is ready, we need to enable the site in Apache, since we just created it. This is only necessary the first time we run it:

$ sudo a2ensite grok

Then, we can start serving our application from Apache, simply by reloading the configuration for the server:

$ sudo /etc/init.d/apache2 reload

When you visit the site in a browser (http://wsgi.example.com/hello), you should see the Grok Admin UI. You should be able to log in using the admin login name and password (found in 'etc/users.zcml').

Adding a ZEO server

By default, mod_wsgi will use a single process to run the application. Since this configuration is intended for production use, it may be desirable to have a higher number of processes available to serve the application. The ZODB that Grok uses comes with a server named ZEO (Zope Enterprise Objects) that allows us to add as many processes to our configuration as our system permits, providing unlimited horizontal scalability. Typically, the recommended number of processes is one for each core in the system's processors. Let's set up a ZEO server and configure the Grok process to connect to it.

Once again, the easiest way to get ZEO running is to use an existing buildout recipe. This time we'll use one named zc:zodbrecipes. Add a zeo_server part to your buildout.cfg file, like this:

parts =
    eggbasket
    app
    i18n
    test
    mkdirs
    zpasswd
    zope_conf
    site_zcml
    zdaemon_conf
    zeo_server
    wsgi_app
    deploy_ini
    debug_ini

Next, add a zeo_server section like the following:

[zeo_server]
recipe = zc.zodbrecipes:server
zeo.conf =
    <zeo>
      address 8100
    </zeo>
    <blobstorage 1>
         blob-dir ${buildout:directory}/var/blobstorage
      <filestorage 1>
        path ${buildout:directory}/var/filestorage/Data.fs
      </filestorage>
    </blobstorage>
    <eventlog>
      level info
      <logfile>
        path ${buildout:directory}/parts/log/zeo.log
      </logfile>
    </eventlog>

This will add the ZEO server and configure it to listen on port 8100. The rest of the configuration is pretty much boilerplate, so just copy it to new projects when you need ZEO there.

Next, we need that the buildout add scripts for starting and stopping ZEO. This is easily accomplished by adding the ZODB3 egg to our app section:

[app]
recipe = zc.recipe.egg
eggs = gwsgi
   z3c.evalexception>=2.0
   Paste
   PasteScript
   PasteDeploy
   ZODB3

Configuring the ZEO client

Currently, the Grok application that we are using is working with the regular Zope server. To use ZEO, we need to change the configuration to connect to the server at port 8100. Fortunately, the required changes already come inside the regular zope.conf file that is created inside the grok project, so we only need to uncomment those lines. Uncomment the following lines inside the zope.conf.in file in the etc directory of your Grok project:

# Uncomment this if you want to connect to a ZEO server instead:
  <zeoclient>
    server localhost:8100
    storage 1
    # ZEO client cache, in bytes
    cache-size 20MB
    # Uncomment to have a persistent disk cache
    #client zeo1
  </zeoclient>

The important line in there is the one with the ZEO server address, in this case the same host as the Grok application and the port we defined in our ZEO configuration in the previous section.

Launching the ZEO server

After running the buildout again, we'll be ready to start the ZEO server in the background. To do that, we only have to run the server script that was automatically created for us. The name of the script is the same as the name of the part in the buildout where we configured the server:

$ bin/zeo_server start

Our Grok application is running. To stop it:

$ bin/zeo_server stop

Augmenting the number of processes

Recall that we mentioned earlier that mod_wsgi runs the application in a single process by default. To really take advantage of ZEO, we want to have more processes available. We need to make a small addition to our mod_wsgi Apache virtual host configuration for that. Change the WSGIDaemonProcess line near the top to look like this:

WSGIDaemonProcess grok user=cguardia group=cguardia processes=2 threads=4 maximum-requests=10000

In this example, we'll have two processes running, with four threads each. Using ZEO and mod_wsgi, we now have an escalable site.

 

Formatting problem

Posted by http://mgedmin.myopenid.com/ at Feb 19, 2009 05:58 PM

Unfortunately this page is so wide as to be unreadable on a 1280-pixel-wide screen.