Nginx + php + fpm plug'n'play configuration

Hi guys, im new to Nginx.

Im running on a ubuntu 10.04 server machine, and im trying to understand
how
to configure nginx in order to run a website with many subdomains, where
every of them must run php with a different user, without restarting
nginx
or php5-fpm.

Basically, when i need to a subdomain, i have a script that create the
server user, then his folder owned by him; for example, for the
foo.example.com subdomain i will have a foo user and a
/var/www/vhosts/subdomains/foo/htdocs folder.

So, for every requests to *.example.com, i need to:

  1. check if user and folder exists
  2. invoke fpm with the matching user/group (maybe the group will be the
    same
    for every subdomain)

Any suggestion about?

On Fri, Apr 01, 2011 at 04:14:40PM +0200, Daniele Pignedoli wrote:

Hi there,

Hi guys, im new to Nginx.

Welcome. You’ll probably want to refer to the manuals for more
information
on everything you read here; but for testing purposes, hopefully the
following will help.

Im running on a ubuntu 10.04 server machine, and im trying to understand how
to configure nginx in order to run a website with many subdomains, where
every of them must run php with a different user, without restarting nginx
or php5-fpm.

The short answer is “it’s not a problem; nginx doesn’t know or care
about php”. But that’s not what you want to hear, so…

Basically, when i need to a subdomain, i have a script that create the
server user, then his folder owned by him; for example, for the
foo.example.com subdomain i will have a foo user and a
/var/www/vhosts/subdomains/foo/htdocs folder.

On the nginx side, there are two main ways to approach this.

Run one nginx instance which can read files of all users; or run one
nginx
instance as each user which only has access to that user’s files, plus
one “main” nginx which will proxy_pass to the correct per-user instance.

The first case is probably easier. An nginx.conf with something like

===
http {
server {
root /tmp/$host/html;
}
}

will probably do most of what you want. “$host” is “whatever the client
sent in the Host: header” (approximately), so you’ll want to make sure
that nothing nasty happens in edge cases, such as “no Host: header
at all” or “Host: …” or “Host: *” and the like.

So, for every requests to *.example.com, i need to:

  1. check if user and folder exists

“error_page 404” may help here. But it may cause confusion if there are
“genuine” 404s generated.

  1. invoke fpm with the matching user/group (maybe the group will be the same
    for every subdomain)

nginx doesn’t do php. But it does “fastcgi_pass” to a fastcgi server,
which is what fpm is.

So run one fastcgi server per user, accessible at a derivable
location. And add something like

===
location ^~ /php/ {
fastcgi_pass unix:/tmp/$host/fcgi.sock;
include fastcgi.conf;
}

inside the server{} block, and all requests for /php/something will be
sent to the appropriate fastcgi server (failing if it is not there).

Any suggestion about?

In this example I use $host as the on-filesystem key. You can set that
to something else, if you prefer.

Also, if you want to run one nginx per user, then you would listen
on a unix socket, and proxy_pass to that socket in the “main” server,
similar to fastcgi_pass above. And it would probably be “error_page 502”
if the per-user server isn’t responding.

And, I have no idea if FPM has a better way of splitting things per-user
without restarting when users are changed.

And, of course, none of this is tested by me :wink:

But if I wanted to do this, I’d probably adjust my “enable user” script
to run a dedicated php fastcgi server as this user, and possibly also
a dedicated nginx server. And then turn them off in my “disable user”
script. The main nginx would run always.

Good luck with it,

f

Francis D. [email protected]

Hi francis, many thanks for your suggestion, with that i’ve been able to
setup a ‘almost-work’ enrivonment!

I have a file i my /etc/nginx/sites-available/ (softlinket do
sites-enabled)
that looks as follow:

server{

    fastcgi_pass    unix:/var/run/php5-fpm-test_$domain.sock;
    fastcgi_param    SCRIPT_FILENAME

$document_root$fastcgi_script_name;
include fastcgi_params;
}
}

All my subdomains are hosted in /var/www/test_[subdomain_name], for
example
foo.test.local => /var/www/test_foo/{htdocs,conf,private}

Then, in my /etc/php5/fpm/fpm.d/ i just create a new file for each
subdomain, for example:

[test_foo]

listen = /var/run/php5-fpm-test_foo.sock

user = test_foo
group = test_foo
pm = static
pm.max_children = 10

…obviously this after i created the unix user useradd test_foo.

This isnt the “plug’n’play” behavior i was looking for, becose in order
to
activate new domains i have to run /etc/init.d/php-fpm reload; but i
thought a solution: when i add a new domain, i first create a simple
“temp”
php-cgi process in order to have the subdomain active instantly

php5-cgi -b /var/run/php5-fpm-test_bar.sock

Then, running a cron task that every night kill all the php5-cgi
instances
and then reload the fpm configuration.

Do you think this could be a solution?

2011/4/1 Francis D. [email protected]

On Tue, Apr 05, 2011 at 11:59:43AM +0200, Daniele Pignedoli wrote:

Hi there,

Hi francis, many thanks for your suggestion, with that i’ve been able to
setup a ‘almost-work’ enrivonment!

Good stuff.

I have a file i my /etc/nginx/sites-available/ (softlinket do sites-enabled)
that looks as follow:

OK, so you’ve gone for “one nginx which can read all files”.

Your config looks to me like it should work ok.

Then, in my /etc/php5/fpm/fpm.d/ i just create a new file for each
subdomain, for example:

And this is “one fpm that runs many instances as different users”,
which,
as you have spotted, needs a restart for a changed user.

This isnt the “plug’n’play” behavior i was looking for, becose in order to
activate new domains i have to run /etc/init.d/php-fpm reload;

I think I had suggested just running one fcgi server per user, which
would
avoid the “restart” thing. That would probably be the equivalent to your

php5-cgi -b /var/run/php5-fpm-test_bar.sock

Of course, that’s all php or fpm stuff, rather than nginx stuff. So:

Then, running a cron task that every night kill all the php5-cgi instances
and then reload the fpm configuration.

…while I think that will probably work ok, you may find better
confirmation elsewhere.

Note that on the nginx side, you haven’t got anything specific relating
to

So, for every requests to *.example.com, i need to:

  1. check if user and folder exists

that. But your testing will show what response you get, and you can
decide whether that is adequate for you.

Good luck with it,

f

Francis D. [email protected]

OK, so you’ve gone for “one nginx which can read all files”.

Your config looks to me like it should work ok.

Yes, my first try is to have just 1 nginx instance, i think is easy to
mantain and manage… and im not comfortable with ports, for what i’ve
understood every nginx instance must have its own port to listen to…

I think I had suggested just running one fcgi server per user, which
would

avoid the “restart” thing. That would probably be the equivalent to your

php5-cgi -b /var/run/php5-fpm-test_bar.sock

Yep, running 1 cgi instance per user is more flexible, but will require
more
effords in maintenance… easily to fall in a headcache to administer so
mny
instances (please note that im not a sysadmin and i dont have much
experience with server administration, that’s why im using a KIS
approach)

Of course i know the cron task can not be the solution in production
mode,
but from my tests seem that fpm could reload the configuration without
restart: I haven to try this under a storm of requests, but looks pretty
nice.

Well, thanks again for your time and suggestion, i’ll play around with
the
configurations hoping to find the ‘best’ solution.

Bye!