<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title></title>
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:Date: $Date: 2005-12-18 01:56:14 +0100 (Sun, 18 Dec 2005) $
:Revision: $Revision: 4224 $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

tt.docutils {
  background-color: #eeeeee }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document">
<p>This tutorial is a compilation of my experience and several documentation I read:</p>
<ul class="simple">
<li><a class="reference" href="http://repoze.org/quickstart.html">http://repoze.org/quickstart.html</a></li>
<li><a class="reference" href="http://grok.zope.org/documentation/tutorial/installing-and-setting-up-grok-under-mod-wsgi/tutorial-all-pages">http://grok.zope.org/documentation/tutorial/installing-and-setting-up-grok-under-mod-wsgi/tutorial-all-pages</a></li>
<li><a class="reference" href="http://www.modwsgi.org">http://www.modwsgi.org</a></li>
</ul>
<div class="section">
<h1><a id="installing-mod-wsgi" name="installing-mod-wsgi">Installing mod_wsgi</a></h1>
<p>Instructions to install mod_wsgi:</p>
<pre class="literal-block">
sudo apt-get install python2.4 python2.4-dev build-essential apache2
sudo apt-get install apache2-prefork-dev  # if you have apache2-mpm-prefork installed (default normally, you can verify with `dpkg -l|grep apache2`)
sudo apt-get install apache2-threaded-dev # if you have apache2-mpm-worker installed
</pre>
<p>Personnaly, I don't install setuptools with the python-setuptools package because it's not always the latest version.
Download manually setuptools-0.6c8-py2.4.egg (or latest version, choose py2.4) at <a class="reference" href="http://pypi.python.org/pypi/setuptools">http://pypi.python.org/pypi/setuptools</a> and execute the command:</p>
<pre class="literal-block">
sudo sh setuptools-0.6c8-py2.4.egg
</pre>
<p>Then install virtualenv:</p>
<pre class="literal-block">
sudo easy_install-2.4 virtualenv
</pre>
<p>Install mod_wsgi:</p>
<pre class="literal-block">
wget http://modwsgi.googlecode.com/files/mod_wsgi-2.1.tar.gz
tar xzf mod_wsgi-2.1.tar.gz
cd mod_wsgi-2.1
./configure --with-python=/usr/bin/python2.4
make
sudo make install
</pre>
<p>Create a file /etc/apache2/mods-available/wsgi.load with in it:</p>
<blockquote>
LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so</blockquote>
<p>Then activate the module with:</p>
<pre class="literal-block">
a2enmod wsgi
</pre>
<p>Note: a2enmod stands for &quot;apache2 enable mod&quot;, this executable create the symlink for you.
Actually <cite>a2enmod wsgi</cite> is equivalent to:</p>
<pre class="literal-block">
cd /etc/apache2/mods-enabled
ln -s ../mods-available/wsgi.load
ln -s ../mods-available/wsgi.conf # if it exists
</pre>
</div>
<div class="section">
<h1><a id="creating-the-sandbox" name="creating-the-sandbox">Creating the sandbox</a></h1>
<p>In the grok tutorial, the site is configured in mods-available/wsgi.conf.
IMHO it's not a good idea, a file should be created in sites-available and activated with a2ensite command. We will go this way in the following.</p>
<p>Create a virtualenv (please replace ${sandbox} by a real path):</p>
<pre class="literal-block">
virtualenv --no-site-packages ${sandbox}
cd ${sandbox}
. bin/activate # at the end of this tutorial, type `deactivate` if you want to leave the virtual environment
</pre>
<p>Personnaly, I'll don't use --no-site-packages for repoze.plone for example to have the installed system-wide PIL package available.
I never install eggs system-wide, except setuptools and virtualenv.
I install PIL, PyXML and libxml2 with: <cite>apt-get install python-imaging python-xml python-libxml2</cite>.</p>
<div class="section">
<h2><a id="installing-repoze-grok" name="installing-repoze-grok">Installing repoze.grok</a></h2>
<p>repoze.grok 0.1.6 ships with grok 0.11, here we edit the setup.py to include grok 0.12.1:</p>
<pre class="literal-block">
easy_install -b . -e -i http://dist.repoze.org/grok/latest/simple repoze.grok
cd repoze.grok
vi setup.py # set GROK_VERSION = '0.12.1'
vi setup.cfg # comment easy_install section
python setup.py develop
cd ..
</pre>
<p>Generate a grok instance:</p>
<pre class="literal-block">
mkgrokinstance .
cp etc/sample-users.zcml etc/users.zcml
</pre>
<p>and edit the password in etc/users.zcml</p>
<p>Copy the virtualhost site sample:</p>
<pre class="literal-block">
sudo cp etc/apache2.conf /etc/apache2/sites-available/grok
</pre>
<p>Note: in the etc/apache2.conf file included in the repoze.grok 0.1.6 package, PASTE_CONFIG should be grok.ini, not zope2.ini. Don't forget to correct it.</p>
</div>
</div>
<div class="section">
<h1><a id="configuration-of-the-site-in-etc-apache2-sites-available-grok" name="configuration-of-the-site-in-etc-apache2-sites-available-grok">Configuration of the site in /etc/apache2/sites-available/grok</a></h1>
<div class="section">
<h2><a id="paste-config-variable" name="paste-config-variable">PASTE_CONFIG variable</a></h2>
<p>modify PASTE_CONFIG to look for grok.ini, not zope2.ini</p>
</div>
<div class="section">
<h2><a id="note-on-python-egg-cache-directory" name="note-on-python-egg-cache-directory">Note on PYTHON_EGG_CACHE directory</a></h2>
<p>simplejson-1.7.1-py2.4-linux-i686.egg was installed as a zipped egg, so when the application will be started, this egg will be automatically extracted in the PYTHON_EGG_CACHE, normally &quot;~/.python-eggs&quot;.
see <a class="reference" href="http://code.google.com/p/modwsgi/wiki/ApplicationIssues">http://code.google.com/p/modwsgi/wiki/ApplicationIssues</a> sections:</p>
<ul class="simple">
<li>&quot;Access Rights Of Apache User&quot;</li>
<li>&quot;User HOME Environment Variable&quot;</li>
</ul>
<p>This directory depends of the HOME environment variable. The HOME apache user www-data is /var/www. You will get the error &quot;[Errno 13] Permission denied: '/var/www/.python-eggs'&quot; in your error.log apache file if you don't configure the user or python-eggs variable in the WSGIDaemonProcess directive. Tip: use <cite>tail -f /var/log/apache2/error.log</cite> in another console.
Example:
Please replace ${sandbox} by the path where you have created your sandbox, i.e your virtualenv directory.
The file included in repoze.grok contains:</p>
<blockquote>
WSGIDaemonProcess grok threads=1 processes=1 maximum-requests=10000 python-path=${sandbox}/lib/python2.4/site-packages</blockquote>
<p>The process belongs to www-data.www-data and python-eggs cache directory will be &quot;/var/www/.python-eggs&quot;.</p>
<p>You can add python-eggs variable:</p>
<blockquote>
WSGIDaemonProcess grok threads=1 processes=1 maximum-requests=10000 python-path=${sandbox}/lib/python2.4/site-packages python-eggs=/tmp/python-eggs</blockquote>
<p>The process belongs to www-data.www-data and python-eggs cache directory will be &quot;/tmp/python-eggs&quot;.</p>
<p>Or you can specify user and group variable:</p>
<blockquote>
WSGIDaemonProcess grok user=${youruser} group=${youruser} threads=1 processes=1 maximum-requests=10000 python-path=${sandbox}/lib/python2.4/site-packages</blockquote>
<p>The process belongs to youruser.youruser and python-eggs cache directory will be &quot;/home/youruser/.python-eggs&quot;.</p>
<p>You can set both variables:</p>
<blockquote>
WSGIDaemonProcess grok user=${youruser} group=${youruser} threads=1 processes=1 maximum-requests=10000 python-path=${sandbox}/lib/python2.4/site-packages python-eggs=/tmp/python-eggs</blockquote>
<p>The process belongs to youruser.youruser and python-eggs cache directory will be &quot;/tmp/python-eggs&quot;.</p>
<p>Be careful, var/ directory and all files in it have to be writable by the user of the process.
I use the third. It allows me to test with <cite>paster serve</cite> and mod_wsgi (not at the same time of course!) without changing var/ permissions.</p>
</div>
<div class="section">
<h2><a id="reload-mechanism" name="reload-mechanism">Reload mechanism</a></h2>
<p>&quot;WSGIReloadMechanism Process&quot; is the default for daemon mode when running mod_wsgi 2.0c5 or later. It was previously &quot;WSGIReloadMechanism Module&quot;.
Configure it explicitly doesn't hurt.
For more details of the different reload mechanism, see:
<a class="reference" href="http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode">http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode</a>
and in particular &quot;Process Reloading Mechanism&quot; section.
&quot;The way that the restart is performed does not affect the handling of the request, with it still being processed once the daemon process has been restarted.&quot;
Cool, isn't it?</p>
</div>
<div class="section">
<h2><a id="final-file" name="final-file">Final file</a></h2>
<p>Here the file:</p>
<pre class="literal-block">
WSGIPythonHome ${sandbox}
WSGIDaemonProcess grok user=${youruser} group=${youruser} threads=1 processes=4 maximum-requests=10000 python-path=${sandbox}/lib/python2.4/site-packages
# python-eggs=/tmp/python-eggs
# please set processes=1 if you don't use a ZEO server!

&lt;VirtualHost *:80&gt;
  ServerName my.machine.local
  WSGIScriptAlias /site ${sandbox}/bin/grok.wsgi
  WSGIProcessGroup grok
  WSGIPassAuthorization On
  WSGIReloadMechanism Process
  SetEnv HTTP_X_VHM_HOST http://my.machine.local/site
  SetEnv PASTE_CONFIG ${sandbox}/etc/grok.ini
&lt;/VirtualHost&gt;
</pre>
</div>
</div>
<div class="section">
<h1><a id="launch-the-server" name="launch-the-server">Launch the server</a></h1>
<div class="section">
<h2><a id="in-developement" name="in-developement">In developement</a></h2>
<p>In developement, use paster serve:</p>
<pre class="literal-block">
bin/paster serve etc/grok.ini
</pre>
<p>To use auto-reload functionnality:</p>
<pre class="literal-block">
bin/paster serve --reload etc/grok.ini
</pre>
</div>
<div class="section">
<h2><a id="in-production" name="in-production">In production</a></h2>
<p>In production, use mod_wsgi.</p>
<p>If processes &gt; 1 in the WSGIDaemonProcess directive, you have to use a ZEO server, start it before reloading apache2:</p>
<pre class="literal-block">
bin/zeoctl -C etc/zeo.conf start
</pre>
<p>And don't forget to configure your etc/zope.conf file to use the ZEO server.</p>
<p>The first time, enable your site and reload apache2:</p>
<pre class="literal-block">
a2ensite grok
/etc/init.d/apache2 reload
</pre>
<p>To stop your site:</p>
<pre class="literal-block">
a2dissite grok
/etc/init.d/apache2 reload
</pre>
<p>To reload your site:</p>
<pre class="literal-block">
touch ${sandbox]/bin/grok.wsgi
</pre>
<div class="section">
<h3><a id="note-on-restarting-apache2" name="note-on-restarting-apache2">Note on restarting Apache2</a></h3>
<p>I suppose that you have other applications configured with apache, maybe PHP applications, so we don't want to stop currently opened connections.
If you want currently open connections not to be aborted, don't use 'apache2ctl restart' or 'apache2ctrl stop'. Use instead 'apache2ctl graceful' and 'apache2ctl graceful stop' respectively. See <cite>man apache2ctl</cite> for more details.
Note on Ubuntu Hardy Heron, you can use this too:</p>
<pre class="literal-block">
/etc/init.d/apache2 reload
/etc/init.d/apache2 stop
</pre>
<p>Currently open connections are not aborted.</p>
</div>
</div>
</div>
<div class="section">
<h1><a id="troubleshooting" name="troubleshooting">Troubleshooting</a></h1>
<div class="section">
<h2><a id="lockerror-couldn-t-lock-sandbox-var-data-fs-lock" name="lockerror-couldn-t-lock-sandbox-var-data-fs-lock">LockError: Couldn't lock '${sandbox}/var/Data.fs.lock'</a></h2>
<p>If you have this error in your error.log apache file, it means you have more than one process trying to Lock your Data.fs.
Please configure zope.conf to use ZEO server as the main storage or use processes=1 in the WSGIDaemonProcess directive.
In production, the use of a ZEO server is recommended.
Before starting apache2 (or enable site and reload apache2), issue the following command:</p>
<pre class="literal-block">
bin/zeoctl -C etc/zeo.conf start
#. daemon process started, pid=7538
</pre>
<p>But zeo dies and I don't know why.
log/zeo.log gives me:</p>
<pre class="literal-block">
2008-07-28T15:32:06 INFO root daemon manager started
2008-07-28T15:32:06 INFO root spawned process pid=7525
2008-07-28T15:32:06 INFO root sleep 1 to avoid rapid restarts
2008-07-28T15:32:06 INFO root pid 7525: exit status 2; exiting now
</pre>
<p>For now I use no ZEO and only one process in the WSGIDaemonProcess directive.</p>
</div>
</div>
<div class="section">
<h1><a id="configuring-a-grok-project" name="configuring-a-grok-project">Configuring a grok project</a></h1>
<p>In grokproject 0.6, there was a --no-buildout to not execute zc.buildout after created the project. In grokproject 0.8, it was replaced by --run-buildout=no.</p>
<p>Create a new grok project:</p>
<pre class="literal-block">
easy_install -U grokproject # to be sure we have the latest version (here 0.8)
grokproject --run-buildout=no helloworld
cd helloworld
python2.4 setup.py develop # be careful, your virtual environment have to be activated to use the good python
</pre>
<p>helloworld/buildout.cfg and helloworld/bootstrap.py files will not be used.</p>
<p>Then create a ZCML slug, a file ${sandbox}/etc/grok-apps/helloworld-configure.zcml with only one line:</p>
<blockquote>
&lt;include package=&quot;helloworld&quot; /&gt;</blockquote>
<p>To use an existing grok project, enter in your project, develop the egg and create a ZCML slug like above.
For Grokstar I added &lt;includeDependencies package=&quot;.&quot; /&gt; after &lt;include package=&quot;grok&quot; /&gt; in the configure.zcml.
You don't use the buildout.cfg of grokstar here, but if your use it and have added includeDependencies, you should remove from buildout.cfg the following lines:</p>
<pre class="literal-block">
&lt;include package=&quot;zope.sendmail&quot; file=&quot;meta.zcml&quot; /&gt;
&lt;include package=&quot;zope.sendmail&quot; /&gt;
</pre>
</div>
</div>
</body>
</html>