Изоляция виртуальных хостов с использованием nginx/apache + fastcgi + пулы php-fpm

:

При размещении большого числа проектов на одном сервере появляется угроза, что при взломе одного из хостов нехороший человек получит доступ и к соседним проектам. Или же, если вы хостите чужие проекты и предоставляете кому-то другому доступ к серверу, очень хорошо бы было исключить возможность доступа к другим хостам. Дальше предлагается однин из многих вариантов решения этой проблемы.

Установка php-fpm.
Php-fpm официально включен в php начиная с версии 5.3.3, в первую очередь скорее всего вам нужно обновить php.
Debian Squeeze:
в /etc/apt/sources.list добавте

deb http://packages.dotdeb.org squeeze all

Дальше нужно поставить ключ:

wget http://www.dotdeb.org/dotdeb.gpg
cat dotdeb.gpg | apt-key add -

Теперь ставим пакеты:

aptitude update
aptitude install php5 php5-cli php5-mysql php5-fpm

Ubuntu 10.04:
PHP 5.3.5 можно взять с ppa https://launchpad.net/~nginx/+archive/php5
в /etc/apt/sources.list добавте

deb http://ppa.launchpad.net/nginx/php5/ubuntu lucid main
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
sudo aptitude update
sudo aptitude install php5 php5-cli php5-mysql php5-fpm

Пулы php-fpm
Пулы позволяют задать разные настройки для отдельных хостов. Разные php.ini, количество дочерних процессов fpm’a, пользователя/группу запускаемых процессов etc.
Идем в /etc/php5/fpm/, открываем main.conf и добавляем туда:

include=/etc/php5/fpm/pool.d/*.conf

Теперь перейдем в директорию /etc/php5/fpm/pool.d/ и создадим конфиги для виртуальных хостов.
Для хостов, которые будут работать через апач сокет должен находиться в /var/lib/apache2/fastcgi/

# vi one-example-com.conf
[one-example-com]
listen = /var/run/one-example-com-php5-fpm.sock
user = one-example-com
group = one-example-com
pm = dynamic
pm.max_children = 80
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 15
pm.max_requests = 200

listen.owner = root
listen.group = www-data
listen.mode = 0660

и второй:

# vi two-example-com.conf
[two-example-com]
listen = /var/run/two-example-com-php5-fpm.sock
user = two-example-com
group = two-example-com
pm = dynamic
pm.max_children = 80
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 15
pm.max_requests = 200

listen.owner = root
listen.group = www-data
listen.mode = 0660

Добавим юзеров в систему:

useradd one-example-com
useradd two-example-com

Теперь, что б apache/nginx смог отдавать статику юзера www-data нужно добавить в группы созданных пользователей.

#vi /etc/group
...
one-example-com:x:1028:www-data
two-example-com:x:1029:www-data

Все, перезапускаем php-fpm

/etc/init.d/php5-fpm restart

Apache
Apache умеет работать с fastcgi через сторонний модуль mod-fastcgi, поставим его.

aptitude install libapache2-mod-fastcgi
cd /etc/apache2/mods-available/
a2enmod fastcgi
# vi /etc/apache2/mods-enabled/fastcgi.conf
<IfModule mod_fastcgi.c>
  AddHandler fastcgi-script .fcgi
  #FastCgiWrapper /usr/lib/apache2/suexec
  FastCgiIpcDir /var/lib/apache2/fastcgi
  AddHandler php-fcgi .php .php5
    <FilesMatch \.php$>
        SetHandler php5-fcgi
  </FilesMatch>
  <Location "/fastcgiphp">
        Order Deny,Allow
        Deny from All
        # Prevent accessing this path directly
        Allow from env=REDIRECT_STATUS
  </Location>
Action php5-fcgi /fastcgiphp
Action php5-fastcgi /fastcgiphp
</IfModule>

Теперь идем в /etc/apache2/sites-available/ и создадим конфиги для наших хостов:

# vi one.example.com

<VirtualHost *:80>

        ServerName one.example.com
        ServerAlias www.one.example.com
        ServerAdmin admin@example.com
        DocumentRoot /var/www/one.example.com/public
        Options -Indexes

        
        <Directory /var/www/one.example.com/public>
                Order Allow,Deny
                Allow from all
        </Directory>

<IfModule mod_fastcgi.c>
        FastCgiExternalServer /usr/local/bin/one-example-com-fpm -socket one-example-com-php5-fpm.sock

        Alias /fastcgiphp /usr/local/bin/one-example-com-fpm
</IfModule>


CustomLog /var/log/apache2/one.example.com/access.log combined
ErrorLog /var/log/apache2/one.example.com/error.log

</VirtualHost>
# vi two.example.com

<VirtualHost *:80>

        ServerName two.example.com
        ServerAlias www.two.example.com
        ServerAdmin admin@example.com
        DocumentRoot /var/www/two.example.com/public
        Options -Indexes

        
        <Directory /var/www/two.example.com/public>
                Order Allow,Deny
                Allow from all
        </Directory>

<IfModule mod_fastcgi.c>
        FastCgiExternalServer /usr/local/bin/two-example-com-fpm -socket two-example-com-php5-fpm.sock

        Alias /fastcgiphp /usr/local/bin/two-example-com-fpm
</IfModule>

CustomLog /var/log/apache2/two.example.com/access.log combined
ErrorLog /var/log/apache2/two.example.com/error.log

</VirtualHost>

Файлы /usr/local/bin/*-fpm не должны существовать в реальности на файловой системе и должны быть уникальны для каждого виртуального хоста, указанные в конфиге сокеты должны находиться в /var/lib/apache2/fastcgi/

a2ensite one.example.com
a2ensite two.example.com

Создадим нужные директории/файлы, настроим права:

mkdir -p /var/www/one.example.com/public/
mkdir -p /var/www/two.example.com/public/
echo '<?php echo "one.example.com"; ?>' > /var/www/one.example.com/public/index.php
echo '<?php echo "two.example.com"; ?>' > /var/www/two.example.com/public/index.php
chown -R one-example-com /var/www/one.example.com/public/
chown -R two-example-com /var/www/two.example.com/public/
chmod 750 /var/www/*

И перезапустим apache:

/etc/init.d/apache2 restart

Все, теперь можете проверить работоспособность хостов. Еще рекомендую залить веб-шелл и проверить правильно ли все настроено. Т.е. с веб шелла войти в директорию другого хоста будет нельзя. Скачать веб шелл можно тут

Nginx
С nginx’ом все в разы проще, начнем. Переходим в /etc/nginx/ и открываем конфиг nginx.conf

# vi nginx.conf
...
http {
...
include /etc/nginx/vhost/*;
...

Создаем директорию vhost и конфиги для хостов:

# mkdir vhost
# vi vhost/one.example.com
server {
        listen ип_сервера:80;
        server_name one.example.com;
        client_max_body_size 5M;
        root /var/www/one.example.com/www/public;
        access_log     /var/log/nginx/one.example.com/access.log;
        error_log       /var/log/nginx/one.example.com/error.log;

        location / {
                index index.php index.html;
        }

        location ~ \.php$ {
                fastcgi_pass    unix:/var/run/one-example-com-php5-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www/one.example.com/www/public$fastcgi_script_name;
                fastcgi_intercept_errors on;
                fastcgi_param  QUERY_STRING     $uri;
                include        fastcgi_params;
        }
}
# vi vhost/two.example.com
server {
        listen ип_сервера:80;
        server_name two.example.com;
        client_max_body_size 5M;
        root /var/www/two.example.com/www/public;
        access_log     /var/log/nginx/two.example.com/access.log;
        error_log       /var/log/nginx/two.example.com/error.log;

        location / {
                index index.php index.html;
        }

        location ~ \.php$ {
                fastcgi_pass    unix:/var/run/two-example-com-php5-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www/two.example.com/www/public$fastcgi_script_name;
                fastcgi_intercept_errors on;
                fastcgi_param  QUERY_STRING     $uri;
                include        fastcgi_params;
        }
}
/etc/init.d/nginx restart

Все, теперь создаем нужные директории, правим права. Все так же, как описано в части про apache. После проверяем тем же веб шеллом.