migrating Topincs to nginx

Francis Daly francis at daoine.org
Wed Jul 10 22:50:39 UTC 2013

On Fri, Jul 05, 2013 at 03:13:51PM +0200, Piotr Kopszak wrote:

Hi there,

I have not tested any of this, so take it as "may be interesting to
consider" rather than "this is the recipe to use".

> "My main objective in the Apache and Topincs integration was that it
> is possible to occupy any URL space below a domain without the need
> for a general 'root', e.g. everything under /topincs. Plus it should
> be possible to run different stores under different Topincs versions,
> just in case.

I confess I don't know what those words mean, in terms of anything that
nginx should do.

I *think* it says "there can be no configured prefix"; but it might mean
"the prefix can be set by the administrator to whatever they want".

nginx works in terms of locations, which are "parts of the url
hierarchy". It is generally good if these are segregated by url prefix.

> So Apache does two things for Topincs:
> 1. The rewrite rules basically cut off the store path prefix (e.g.
> /trial/movies) and pass the result on to
> TOPINCS_HOME/docroot/.topincs.
> 2. Based on the path prefix it maps the URL to a store (database).
> This is done by setting an Apache environment variable in the
> configuration. This variable is read in .topincs only.
> So once you manage to provide .topincs with the above, you are set." (

I suspect that these words make perfect sense to someone who has studied
the topincs jargon. That's not me. But I guess that if "an Apache
environment variable" means specifically that, then it may not work
outside of apache, without some code changes.

For nginx the questions are, approximately, "what url are you requesting",
and "what do you want nginx to do with that request".

If you can answer those questions, you'll probably have a better chance
of getting a working configuration.

> /etc/apache2/sites-enabled/000-default contains:

apache is very different from nginx. It allows configuration based on the
url (location) and also the filesystem (directory, file). It combines
configuration from different blocks to determine what happens with one
request. It handles php internally.

nginx allows configuration based on the url (location). One request is
handled in one location. Unless the config you want is active in that
one location, is does not apply. php is entirely external, typically
done by talking to a fastcgi server.


> <VirtualHost *:80>


This is all fairly general, and pretty much doesn't apply for nginx
(unless the defaults are insufficient).

> <Directory "/home/apollo/topincs/docroot">

If you can find the matching url, you can put this in a location{}.

>     DirectoryIndex index.php
>     AddType 'text/html; charset=UTF-8' .html
>     DefaultType application/x-httpd-php

Does that mean "urls ending in .html are served from the filesystem;
everything else is handled by php"? Or is it "urls ending in a specific
list of things are served from the filesystem; everything else is handled
by php"? Or something else?

That might make a difference for the nginx config.

>     php_value include_path
> "/home/apollo/topincs/php:/home/apollo/topincs/vendor/php"
>     php_value default_charset "UTF-8"

Those all look like php configuration settings. Put them in your php
config file, not your nginx one.

> <Directory ~ "/home/apollo/topincs/docroot/[0-9]\.[0-9]+\.[0-9](beta\([0-9]+\))?">

This looks like another location.

You might want to nest this inside the previous one; or you might want
to repeat what is in the previous one, here.

What configuration does topincs expect will apply for matching urls?

> <LocationMatch ^/mercury/.*>
>     SetEnv TOPINCS_STORE mercury

What uses that SetEnv result? If it is the php application, maybe it
should be a fastcgi_param. If it is something else, then the details
might matter.

> RewriteRule ^/mercury/([3-9]\.[0-9]\.[0-9].*/(.core-topics|css|images|js|vendor|fonts).*)$
> /mercury/$1 [PT,E=TOPINCS_STORE:mercury]
> RewriteRule ^/mercury((\.|/).*)$ /mercury/.topincs?request=$1
> Alias /mercury "/home/apollo/topincs/docroot"

And what do those lines do?

"/mercury" is your prefix. The second one seems to say that
/mercury.anything and /mercury/anything are handled by the php script
at /home/apollo/topincs/docroot/.topincs with a query string of
request=.anything or request=/anything. (Or maybe it also appends the
original query string.)

I'm not sure about the first one. /mercury/version-number/some-prefixes
are... served from the file system? Or sent through to the second one
where they match /mercury/anything?

I'm mostly guessing here, because I don't speak (much) apache.

> ---------------------------------------------------------------------
> user www-data;
> worker_processes 4;
> pid /var/run/nginx.pid;
> events {
>         worker_connections 768;
> }
> http {

For initial testing, keep it simple. Only add directives where you know
why they are there. And run in debug mode.

>         include /etc/nginx/mime.types;

That line is useful, if you are serving something from the filesystem.

>         error_log /var/log/nginx/error.log debug;

And that one, because of the debug mode.

>         include /etc/nginx/conf.d/*.conf;
>         include /etc/nginx/sites-enabled/*;

I suggest you include just the one named file that you are testing with,
to avoid any confusion. Your test system is only intended to run a single
service, so keep it that way.

>         include fastcgi_params;

That might be useful; but it is probably more useful within the server{}
or location{} that you care about.

> }

> server {
>         listen   80;
>         root /home/apollo/topincs/docroot;
>         index index.php;

Here it starts getting messy.

Rather than you trying to translate from apache to nginx, could you try
to translate from apache to a word-description of how some specific urls
should be handled? After that, it may be obvious what the nginx config
should be.

So, when you browse your apache-based topincs server, choose a few
urls that you access. You'll see them in your browser location bar,
or in your server access log file.

When you "curl -i" those urls, what do you see? An indication that it
was served from the filesystem, or from php, or something else?

When you know that, you'll be able to define the location{} blocks that
you will need in nginx.

And after *that*, you'll have a better chance of putting in the rest of
the configuration.

Good luck with it,

Francis Daly        francis at daoine.org

More information about the nginx mailing list