# Migrating Topincs to nginx

**URL:** <https://www.ruby-forum.com/t/migrating-topincs-to-nginx/245705>\
**Category:** NGINX\
**Created:** [July 5, 2013, 3:14pm UTC](https://www.ruby-forum.com/t/migrating-topincs-to-nginx/245705 "2013-07-05T15:14:33Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rafa\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/958977/32.png) [@Rafa\_F](https://www.ruby-forum.com/u/Rafa_F)\
**Post date:** [July 5, 2013, 3:14pm UTC](https://www.ruby-forum.com/t/migrating-topincs-to-nginx/245705/1 "2013-07-05T15:14:33Z")

</div>

Dear list,

This is going to be a long post, but I hope you will bear with me. I  
am trying to find a way to run Topincs, an agile web application  
framework based on Topic Maps paradigm, on nginx. Topincs is a  
typical LAMP app, so I hoped I would be able to figure it out on my  
own, but unfortunately not. Even if you find this post too long and  
boring to read, I would be grateful for pointing me to resources  
concerning migration from apache2 to nginx and descriptions of  
successful cases.

First a description of the situation by Topincs’ author:

"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.

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." (  
[http://tech.groups.yahoo.com/group/topincs/message/673](http://tech.groups.yahoo.com/group/topincs/message/673) )

So let’s start with a working Apache configuration. I’m running Debian  
Wheezy, uname -a gives:

Linux box 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86\_64 GNU/Linux

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

* * *

## \<VirtualHost \*:80\> ServerAdmin webmaster@localhost DocumentRoot /var/www/ Options FollowSymLinks AllowOverride None \<Directory /var/www/ \> Options Indexes FollowSymLinks MultiViews AllowOverride all Order allow,deny allow from all ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ \<Directory “/usr/lib/cgi-bin”\> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all ErrorLog ${APACHE\_LOG\_DIR}/error.log CustomLog ${APACHE\_LOG\_DIR}/access.log combined Include “/home/apollo/topincs/conf/httpd.conf”

/home/apollo/topincs/conf/httpd.conf :

* * *

## RewriteEngine on \<Directory “/home/apollo/topincs/docroot”\> Order allow,deny Allow from all DirectoryIndex index.php AddType ‘text/html; charset=UTF-8’ .html DefaultType application/x-httpd-php php\_value include\_path “/home/apollo/topincs/php:/home/apollo/topincs/vendor/php” php\_value default\_charset “UTF-8” php\_value magic\_quotes\_gpc “0” php\_value max\_execution\_time “7200” php\_value memory\_limit “500M” php\_value short\_open\_tag “0” \<Directory ~ “/home/apollo/topincs/docroot/[0-9].[0-9]+.0-9?”\> FileETag none Header set Expires “Fri, 31 Dec 2020 23:59:59 GMT” Header set Cache-control “public” Include “/home/apollo/topincs/conf/\*.httpd.conf”

/home/apollo/topincs/conf/ contains mercury.httpd.conf:

* * *

## \<LocationMatch ^/mercury/._\> SetEnv TOPINCS\_STORE mercury_ _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 [PT,L,QSA,E=TOPINCS\_STORE:mercury] Alias /mercury “/home/apollo/topincs/docroot”

The (useless) nginx setup I came up with so far is following:

/etc/nginx/nginx.conf

* * *

## user www-data; worker\_processes 4; pid /var/run/nginx.pid; events { worker\_connections 768; } http { sendfile on; tcp\_nopush on; tcp\_nodelay on; keepalive\_timeout 65; types\_hash\_max\_size 2048; include /etc/nginx/mime.types; default\_type application/octet-stream; access\_log /var/log/nginx/access.log; error\_log /var/log/nginx/error.log debug; gzip on; gzip\_disable “msie6”; include /etc/nginx/conf.d/_.conf; include /etc/nginx/sites-enabled/_; include fastcgi\_params; }

/etc/nginx/sites-enabled/topincs :

* * *

server {  
listen 80;  
root /home/apollo/topincs/docroot;  
index index.php;  
location / {  
fastcgi\_pass localhost:9000;  
fastcgi\_index “/index.php”;  
allow all;  
try\_files $uri $uri/ /index.php;  
}  
location ~ .php$ {  
include fastcgi\_params;  
if (-f $request\_filename) {  
fastcgi\_pass 127.0.0.1:9000;  
}  
}  
location ~ mercury {  
fastcgi\_param TOPINCS\_STORE mercury;  
}  
location ~ /.[0-9].[0-9]+.0-9? {

```
            add_header Expires "Fri, 31 Dec 2020 23:59:59 GMT";
            add_header Cache-Control "public";
            }
    location /mercury {
             rewrite

```

## ^/mercury/([3-9].[0-9].[0-9]._/(.core-topics|css|images|js|vendor|fonts)._)$ /mercury/$1; rewrite ^/mercury((.|/).\*)$ /mercury/.topincs?request=$1; } }

/etc/php5/fpm/php.ini

* * *

[PHP]  
short\_open\_tag = Off  
asp\_tags = Off  
precision = 14  
output\_buffering = 4096  
zlib.output\_compression = Off  
implicit\_flush = Off  
unserialize\_callback\_func =  
serialize\_precision = 17  
disable\_functions =  
pcntl\_alarm,pcntl\_fork,pcntl\_waitpid,pcntl\_wait,pcntl\_wifexited,pcntl\_wifstopped,pcntl\_wifsignaled,pcntl\_wexitstatus,pcntl\_wtermsig,pcntl\_wstopsig,pcntl\_signal,pcntl\_signal\_dispatch,pcntl\_get\_last\_error,pcntl\_strerror,pcntl\_sigprocmask,pcntl\_sigwaitinfo,pcntl\_sigtimedwait,pcntl\_exec,pcntl\_getpriority,pcntl\_setpriority,  
disable\_classes =  
zend.enable\_gc = On  
expose\_php = On  
max\_execution\_time = 30  
max\_input\_time = 60  
memory\_limit = 128M  
error\_reporting = E\_ALL & ~E\_DEPRECATED & ~E\_STRICT  
display\_errors = Off  
display\_startup\_errors = Off  
log\_errors = On  
log\_errors\_max\_len = 1024  
ignore\_repeated\_errors = Off  
ignore\_repeated\_source = Off  
report\_memleaks = On  
track\_errors = Off  
html\_errors = On  
error\_log = /var/log/php\_errors.log  
variables\_order = “GPCS”  
request\_order = “GP”  
register\_argc\_argv = Off  
auto\_globals\_jit = On  
post\_max\_size = 8M  
auto\_prepend\_file =  
auto\_append\_file =  
default\_mimetype = “text/html”  
doc\_root =  
user\_dir =  
enable\_dl = Off  
cgi.fix\_pathinfo=0  
file\_uploads = On  
upload\_max\_filesize = 2M  
max\_file\_uploads = 20  
allow\_url\_fopen = On  
allow\_url\_include = Off  
default\_socket\_timeout = 60  
request\_terminate\_timeout = 30s  
[CLI Server]  
cli\_server.color = On

[Pdo\_mysql]  
pdo\_mysql.cache\_size = 2000  
pdo\_mysql.default\_socket=

[mail function]  
SMTP = localhost  
smtp\_port = 25  
mail.add\_x\_header = On  
[SQL]  
sql.safe\_mode = Off  
[ODBC]  
odbc.allow\_persistent = On  
odbc.check\_persistent = On  
odbc.max\_persistent = -1  
odbc.max\_links = -1  
odbc.defaultlrl = 4096  
odbc.defaultbinmode = 1  
[Interbase]  
ibase.allow\_persistent = 1  
ibase.max\_persistent = -1  
ibase.max\_links = -1  
ibase.timestampformat = “%Y-%m-%d %H:%M:%S”  
ibase.dateformat = “%Y-%m-%d”  
ibase.timeformat = “%H:%M:%S”  
[MySQL]  
mysql.allow\_local\_infile = On  
mysql.allow\_persistent = On  
mysql.cache\_size = 2000  
mysql.max\_persistent = -1  
mysql.max\_links = -1  
mysql.default\_port =  
mysql.default\_socket =  
mysql.default\_host =  
mysql.default\_user =  
mysql.default\_password =  
mysql.connect\_timeout = 60  
mysql.trace\_mode = Off  
[MySQLi]  
mysqli.max\_persistent = -1  
mysqli.allow\_persistent = On  
mysqli.max\_links = -1  
mysqli.cache\_size = 2000  
mysqli.default\_port = 3306  
mysqli.default\_socket =  
mysqli.default\_host =  
mysqli.default\_user =  
mysqli.default\_pw =  
mysqli.reconnect = Off  
[mysqlnd]  
mysqlnd.collect\_statistics = On  
mysqlnd.collect\_memory\_statistics = Off  
[bcmath]  
bcmath.scale = 0  
[Session]  
session.save\_handler = files  
session.use\_cookies = 1  
session.use\_only\_cookies = 1  
session.name = PHPSESSID  
session.auto\_start = 0  
session.cookie\_lifetime = 0  
session.cookie\_path = /  
session.cookie\_domain =  
session.cookie\_httponly =  
session.serialize\_handler = php  
session.gc\_probability = 0  
session.gc\_divisor = 1000  
session.gc\_maxlifetime = 1440  
session.bug\_compat\_42 = Off  
session.bug\_compat\_warn = Off  
session.referer\_check =  
session.cache\_limiter = nocache  
session.cache\_expire = 180  
session.use\_trans\_sid = 0  
session.hash\_function = 0  
session.hash\_bits\_per\_character = 5  
url\_rewriter.tags =  
“a=href,area=href,frame=src,input=src,form=fakeentry”  
[MSSQL]  
mssql.allow\_persistent = On  
mssql.max\_persistent = -1  
mssql.max\_links = -1  
mssql.min\_error\_severity = 10  
mssql.min\_message\_severity = 10  
mssql.compatability\_mode = Off  
mssql.secure\_connection = Off  
[Tidy]  
tidy.clean\_output = Off  
[soap]  
soap.wsdl\_cache\_enabled=1  
soap.wsdl\_cache\_dir=“/tmp”  
soap.wsdl\_cache\_ttl=86400  
soap.wsdl\_cache\_limit = 5  
[ldap]  
ldap.max\_links = -1  
[dba]  
cgi.fix\_pathinfo = 0;

* * *

/etc/php5/fpm/pool.d/www.conf

* * *

[www]  
user = www-data  
group = www-data  
listen = 127.0.0.1:9000  
pm = dynamic  
pm.max\_children = 5  
pm.start\_servers = 2  
pm.min\_spare\_servers = 1  
pm.max\_spare\_servers = 3

## slowlog = /var/log/php5-fpm.slow.log request\_terminate\_timeout = 30s chdir = / php\_value[include\_path] = “/home/apollo/topincs/php:/home/apollo/topincs/vendor/php” php\_value[default\_charset] = “UTF-8” php\_value[magic\_quotes\_gpc] = “0” php\_value[php\_value max\_execution\_time] = “7200” php\_value[php\_value memory\_limit] = “500M” php\_value[php\_value short\_open\_tag] = “0” env[TOPINCS\_STORE] = “mercury”;

That’s all I can think of. If you have any ideas how to make this work  
it would be GREATLY appreciated, not only by my but also by other  
Topincs users, who will enjoy using nginx instead of apache.

Many thanks in advance

Piotr

P.S.

Topincs installation instructions are here:

[http://www.cerny-online.com/topincs/manual/installing](http://www.cerny-online.com/topincs/manual/installing)

–  
[http://okle.pl](http://okle.pl)

---

<div class="post-metadata">

**Author:** ![Piotr\_Kopszak](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/91b2a8/32.png) [@Piotr\_Kopszak](https://www.ruby-forum.com/u/Piotr_Kopszak)\
**Post date:** [July 11, 2013, 12:51am UTC](https://www.ruby-forum.com/t/migrating-topincs-to-nginx/245705/2 "2013-07-11T00:51:31Z")

</div>

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.

So…

> \<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?”\>

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  
> [PT,L,QSA,E=TOPINCS\_STORE:mercury]  
> 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,

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
