StoWiki/ blog/ sysadmin/ Tips & Tricks: plone, nginx and path rewriting

The problem

On a couple of Debian Etch systems we have a plone-site that is published using a backport of the nginx web server.

The Zope instance is running on the standard port and serves the Plone contents under the /plone path.

Initially we were publishing the site to the external world using an https site served by nginx using the following entry on the configuration:

  location /plone/ {
    proxy_pass http://plone:9673;
    include    /etc/nginx/proxy.conf;
  }

The proxy.conf contents are quite standard:

  # proxy.conf
  proxy_redirect                  off;
  proxy_set_header                Host $host;
  proxy_set_header                X-Real-IP $remote_addr;
  proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;
  client_max_body_size            0;
  client_body_buffer_size         128k;
  proxy_connect_timeout           90;
  proxy_send_timeout              90;
  proxy_read_timeout              90;
  proxy_buffer_size               4k;
  proxy_buffers                   4 32k;
  proxy_busy_buffers_size         64k;
  proxy_temp_file_write_size      64k;

With this settings we see the /plone contents using the same path that is used by the Zope instance, but after testing we have decided to change the /plone path and server the contents under the /web path.

The Wrong Solution

The fist option I though about was quite simple, rename the Zope's plone object to web.

Seems reasonable and simple for someone without Zope experience (I don't administer the internals of the Zope/Plone site), but now I know that it is a very big mistake, because renaming objects in Zope in not cheap, as it implies that the server has to modify all the contents of the renamed object and the operation can take a very long time.

With my ignorance I tried to rename the plone object using the Zope administrative interface and after a minute or so I cancelled the page loading that was running on my browser, thinking that I had cancelled the rename operation.

To make a long story short I'll tell you that the operation was still running and after several hours the folder was renamed (in fact I noticed when the good solution broke, as I had already solved the problem using the next method), but something went wrong and part of the site functionality was broken... the final solution to the debacle has been to recover a backup of the Zope instance older than the rename operation and continue from that copy.

The Right Solution (TM)

It seems that Zope has a couple of systems to do Virtual Hosting and the best option is the use of the product called Virtual Host Monster, a weird and confusing system (IMHO, of course), that does the job once the right configuration settings are in place.

The best solution to our problem was to modify the requests done by the reverse proxy without touching anything on the Plone site (the original one already had a Virtual Host Monster object installed and that was the only thing that we needed to add).

The nginx configuration for the new /web path is the following:

  location /web/ {
    proxy_pass http://plone:9673/plone/VirtualHostRoot/_vh_web/;
    include    /etc/nginx/proxy.conf;
  }

With this change, when the user asks for anything under the /web/ path the Zope server gets the contents traversing the /plone object and adding to it the elements that appear after the VirtualHostRoot component, ignoring components that start with the _vh_ prefix (the protocol and host name of the requests are not modified, as we did not touched that).

Once the object is found, the server rewrites the URLs included on the HTML files using the path components that appear after the VirtualHostRoot one, including the suffix of the components that start with the prefix _vh_.

For example, when the Zope server receives a request for an URL like:

  http://plone:9673/plone/VirtualHostRoot/_vh_web/home

it publishes the content found on:

  http://plone:9673/plone/home

but the HTML files returned assume that their base URL is:

  http://plone:9673/web/home