Host multiple VHosts with different users in Nginx

The most normal thing in the world when you have a server is to think about security and more security, you can never be paranoid enough 😉

A somewhat common practice and NOTHING recommended, is to use the same user for all databases, worse if root is used, which as incredible as it may seem, there are those who (due to vagrancy or ignorance) do this, I already talked about why you should NOT act like this in another postNow it's time to explain how and why it is better to separate the web server processing in different users, this time it will be using Nginx.


What is that of users and web server?

To explain it in a brief and simple way, the web server (apache, nginx, whatever) needs to open processes in the system, processes that will be the ones who take the files from the HDD (images, etc.) and make them available to the client's browser . The web server cannot simply take the files and manipulate them while being nobody, that is, it needs a user who will be the one who will do all this in the end, and that user is the one I am talking about, is that understood?

What is that of separating in several users?

Suppose that on our server we have 2 websites, ours which is a personal project, and another one (let's imagine it's our girlfriend or brother's). Even when we use separate databases and different users to access them, in the end the files of both websites are manipulated by the same user, the PHP processing is managed by the same user for all sites (it is usually www-data). This is a non-recommended practice, it is better to have everything well separated, as an old saying goes, it is better to be safe than sorry.

Ok I understand how I do it with Nginx


The first thing to note is that Nginx does not have its own module that handles PHP processing as Apache does, for Nginx we need to use PHP-CGI or PHP-FPM, which works just as well (or better) than Apache. So in order to separate PHP processing across different users, we will need to change lines in PHP configuration files (CGI or FPM), not Nginx itself.

Suppose you use PHP-FPM, we will create a configuration file of pool for a specific site, that is, a pool is the way to separate PHP processing from PHP-FPM, but we go in parts.

1. First we must know which user of the system we will use, I will assume that we still do not have any created and well, let's create it:

All the following commands MUST be executed with administrative privileges, either with direct root or using sudo

adduser blog

We will start the normal process of creating a user, enter the password, etc.

I blog the user just to follow the example, that the first site that we will host will be a blog, well that ... to know each user with which site is related

1. First let's go to /etc/php5/fpm/pool.d/:

cd /etc/php5/fpm/pool.d/

2. Now, we will create a file called blog.conf:

touch blog.conf

3. Now we will put the configuration of the pool that we will use for the VHost blog:

Edit the blog.conf file with nano ... for example: sudo nanoblog.conf
[blog] user = blog
group = blog
listen = / var / run / php5-fpm-blog.sock listen.owner = blog = blog
pm = ondemand pm.max_children = 96 chdir = /

Note: What I mark them in red is what they must modify depending on the user they previously created. For example, if they create another VHost with another user (forum for example) then instead of blog simply put forum in each of the lines, is it understood?

4. Once the configuration of the new pool (the blog.conf file that we just created and edited), it is the turn to tell the Nginx VHost to use a different sock for that VHost, for this site. The sock that will be used will be the one we previously declared (/var/run/php5-fpm-blog.sock). Let's edit the Nginx VHost and in the PHP processing part, we indicate to use that socks. For example:

location ~ \ .php $ {if (! -f $ request_filename) {return 404; }
fastcgi_pass unix: / var / run / php5-fpm-blog.sock;
include fastcgi_params; fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; fastcgi_read_timeout 300; }

As you can see, I indicate that the PHP processing of that VHost (those lines are for example inside / etc / nginx / sites-enabled / vhost-blog) do it with the socks found in /var/run/php5-fpm-blog.sock ... which is the one we previously created when editing /etc/php5/fpm/pool.d/blog.conf ... is it not understood ?

5. Once this is done, we restart both services (php5-fpm and nginx) and voila, we will see that the processing of that site (vhost) is NOT done by www-data or root or anyone similar, but by the user that we previously defined .

Here I show you the output of a ps aux | grep fpm on one of my node's servers:

ps aux | grep fpm ebook 586 0.0 0.0 349360 1204? S Mar30 0:00 php-fpm: pool ebook ebook 589 0.0 0.0 349360 1204? S Mar30 0:00 php-fpm: pool ebook www 608 0.0 0.2 350084 5008? S Mar30 0:00 php-fpm: pool www www 609 0.0 0.2 350600 5048 30? S Mar0 00:3 php-fpm: pool www tv611 0.0 0.0 349360 1204 30? S Mar0 00:3 php-fpm: pool tv3 tv615 0.0 0.0 349360 1204 30? S Mar0 00:3 php-fpm: pool tv1818 magazine 1.7 1.7 437576 36396 09? S 55:0 46:2264 php-fpm: pool magazine magazine 1.9 1.7 437332 35884 10? S 15:0 26:2338 php-fpm: pool magazine pupil 4.3 1.0 428992 22196 10? S 18:0 53:2413 php-fpm: pool pupil magazine 1.8 1.7 437764 36152 10? S 22:0 18:2754 php-fpm: pool gutl magazine 3.5 1.3 356724 27164 10? S 38:0 00:5624 php-fpm: pool gutl cgr 0.0 1.0 365168 22696 28? S Apr0 16:7900 php-fpm: pool cgr pupil 0.3 2.5 457052 52444 25? S Apr20 23:11021 php-fpm: pool pupil pupil 0.4 2.5 458316 52864 28? S Apr5 57:11254 php-fpm: pool pupil cgr 0.0 1.0 363152 21708 28? S Apr0 12:13184 php-fpm: pool cgr cgr 0.0 1.0 362872 21360 28? S Apr0 08:XNUMX php-fpm: pool cgr

As you can see ... separating the PHP processing by users using Nginx + PHP-FPM is really easy, there you see that there are several pools, as there are several users.


When it comes to servers, you are never paranoid enough ... security is not something to play with, the more we always try to improve the security of our servers and their services, the less likely we will be scared by a (successful) hack attempt or anything similar 😉

The content of the article adheres to our principles of editorial ethics. To report an error click here!.

9 comments, leave yours

Leave a Comment

Your email address will not be published.



  1. Responsible for the data: Miguel Ángel Gatón
  2. Purpose of the data: Control SPAM, comment management.
  3. Legitimation: Your consent
  4. Communication of the data: The data will not be communicated to third parties except by legal obligation.
  5. Data storage: Database hosted by Occentus Networks (EU)
  6. Rights: At any time you can limit, recover and delete your information.

  1.   dhunter said

    Gaara, in current times these things should be automated as much as possible, I recommend you try Ansible. Without agent, you only need python on the remote host, very simple to configure, yaml files, Jinja templates.

    1.    KZKG ^ Gaara said

      Let's see, that's not always only for WordPress sites, and ... haha ​​maybe Ansible clicks volao, but I prefer to know exactly how everything works on the server, even if I have to spend 1 minute creating a new socks and a new VHost 😀

      1.    dhunter said

        With Ansible you automate everything, you do practically whatever you want, the advantage of this method is that you encapsulate the practice and then execute at will, imagine that you have a heavily loaded site and you want to do load balancing between application servers, these have to be configured exactly the same you can't skip a step or do anything different in one of them, can you imagine doing the procedure step by step 4 times? With Ansible it's as simple as adding the hostname to the inventory file and Voilá !!

      2.    dhunter said

        Sorry about the Ansible cult, but it is one of these technologies that you discover and you want everyone to use it now because it is so cool and practical, it's like when you discover NGINX and you want all your friends to leave Apache immediately.

  2.   rots87 said

    I am (or study to be) a developer and with NGIX I had a lot of problems when configuring nginx + php-fpm. I know that the archlinux distro is not the best to make it a server, but every time I updated a version of ngix or php it always crashed everything so I abandoned the attempt lol ... For today I stayed with the classic Apache + PHP but I'll see if I go around NGIX again ... maybe in a virtual machine

    1.    dhunter said

      The mentality changes a bit, nginx serves the static content and serves as a reverse proxy for the php-fpm that is who runs the real PHP, you have to start in parts and achieve the deploy step by step, look for a guide to deploy the framework with which you work, each one has its detail by the names of the public, static, resources, etc ...

  3.   Anonymous said

    Do the community the great favor of abandoning the word "hostear", which does not exist. By God, is it so difficult to say "host"?

  4.   Wil said

    Greetings, following your example I would like to know if a pool could be made only for the wordpress backen, that is, for the wp-admin making a new socket for incoming connections to the backend

    location / wp-admin {
    root /var/www/;
    index index.php index.html index.htm;
    location ~ ^ / wp-admin /(.+. php) $ {
    try_files $ uri = 404;
    root /var/www/;
    include / etc / nginx / fastcgi_params;

    fastcgi_pass server unix:/run/php5-fpm2.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 256 4k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_read_timeout 1240;
    location ~* ^/wp-admin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
    root /var/www/;