Не так давно, в результате массивных атак, произошедших в интернете, в частности, из-за DDoS-атак WordPress-хостов, я был вынужден переместить некоторые мои сайты на виртуальный сервер с небольшим объемом памяти и одноядерным процессором.

Это потребовало переосмысления всей стратегии их размещения: вместо безграничных ресурсов огромного сервера с практически неограниченным объемом памяти, дисковым пространством и многоядерными процессорами я должен был каким-то образом выжать аналогичную производительность из крошечного виртуального сервера. Как?

После целой недели изучения по большей части устаревших руководств и оценки разнообразных подходов и стратегий стало ясно, что моя любимая среда разработки LAMP, используемая многими разработчиками и компаниями для запуска WordPress, могла оказаться подходящим выбором. Однако от Apache пришлось отказаться, поскольку он не вписывался в такие жесткие ограничения.

Неплохой альтернативой выглядел Nginx, с которым, правда, у меня не было никакого опыта работы, потому я не ждал чудес – к тому же я знал, что WordPress был специально разработан так, чтобы использовать различные преимущества Apache, такие как mod_rewrite для получения красивых URL, настройки дискового кэширования и т.д.

Однако к моему удивлению, Nginx не только прекрасно справился с запуском WordPress, но и помог добиться высочайшей производительности – я даже не думал, что такое возможно! Небольшой, но ультрабыстрый сервер! Ниже мы покажем, как его настроить.

sun-reflected-on-water

Требования

Для данного руководства нам понадобятся три следующих вещи:

1. Виртуальная машина (или VPS), либо созданная на вашем компьютере (с помощью VMWare или аналогичных программ), либо, что более вероятно, арендованная у частного провайдера. Вы можете сравнить возможности и цену разных VPS на сайте CompareVPS. Я использую VPS с 512 Мб памяти, 40 Гб дискового пространства и 500 Гб месячного трафика примерно за $10/месяц.

2. Установленная Ubuntu. Для данного руководства мы будем использовать Ubuntu 12.04. Есть и более свежие версии; многие команды и настройки будут также работать и в Debian Linux . Частные провайдеры обычно предлагают уже установленную операционную систему после вашей регистрации.

3. Некоторое знание консольных команд Unix. По крайней мере, вы не должны бояться экспериментировать с ними!

Быстрый обзор

Что мы собираемся сделать. Для начала мы установим и настроим MySQL, чтобы подогнать его под среду с ограниченной памятью. Затем мы установим Nginx с базовой конфигурацией. Nginx требует внешнего способа взаимодействия с PHP, поэтому нам понадобится установить PHP-FPM – один из вариантов управления PHP FastCGI процессами, показывающий наилучшую производительность в тестах (именно его использует WordPress.com для подъема собственной производительности). После установки тщательно настроим все это.

Мы будем использовать PHP вместе с кэшированием Alternative PHP Cache (APC), позволяющим ускорить обработку PHP и совместимым с плагином W3 Total Cache (который, в свою очередь, полностью совместим с Nginx).

Наконец, мы объясним, как разместить многочисленные сайты с полностью различными доменными именами, используя одиночную мультисайтовую сборку WordPress.

Предостережения

Перед тем как двигаться по руководству, вы должны учесть несколько вещей. Выбор «наилучшей» сборки для WordPress – дело тонкое, поскольку, с одной стороны, этот выбор зависит от того, что вы подразумеваете под словом «наилучший»; с другой стороны, выбор зависит от вашей сборки WordPress (и аппаратных средств, используемых для ее запуска), типа данных (изображения, мультимедиа-файлы), которые вы хотите размещать, и, что более важно, от ваших посетителей и их действий.

В сети есть много сравнений, которые «доказывают», что одно решение «лучше», чем другое. Я сделал то же самое для своей собственной сборки. Ниже вы сможете ознакомиться с результатами моих тестов. Однако вы можете иметь ту же самую среду, но при этом ваши результаты не будут дотягивать до моих.

К примеру, некоторые люди отмечают, что Nginx + PHP-FPM в действительности работает несколько медленнее, чем Apache + mod_php, если у вас нет больших объемов статичного контента (поскольку Nginx обрабатывает его напрямую, не обращаясь к бэкэнду PHP-FPM). Если у вас есть достаточный запас памяти, вы можете воспользоваться решением Varnish + Apache + mod_php, которое способно превзойти даже тонко настроенную среду Nginx + PHP-FPM. Не стоит пользоваться Nginx + PHP-FPM только потому, что эта связка прекрасно работает на сайте WordPress.com  — в вашем случае она может оказаться не самой лучшей.

Однако если вы имеете ограниченную среду с малыми ресурсами – или, вместо того чтобы приобретать мощный сервер с большим объемом памяти и многоядерными CPU, вы предпочитаете распределять нагрузки по нескольким небольшим облачным экземплярам – то наше руководство может помочь вам выжать максимальную производительность из вашего небольшого виртуального сервера.

Установка MySQL

Итак, ваш провайдер виртуального сервера только что отправил вам пароль для доступа к собственному виртуальному пространству! Самое время войти на сервер через SSH и запустить установку интересных вещей. Мы начнем с MySQL.

Некоторые предустановленные версии Ubuntu могут уже включать в себя MySQL 5.5 как часть пакета. В противном случае вам понадобится запустить MySQL:

01sudo apt-get install mysql-server

Теперь пришло время настроить MySQL для работы с минимальным объемом памяти, сохраняя высокую производительность. Первый шаг – выбор между двумя популярными системами хранения данных, MyISAM и InnoDB. MyISAM – одна из наиболее старых систем; InnoDB поставляется по умолчанию вместе с MySQL 5.5.

Опять же, в интернете активно ведутся обсуждения, какое из решений лучше для WordPress, и, как и в прошлом случае, все зависит от личных предпочтений и определенной среды. В данном контексте важно, что мы должны воспользоваться каким-либо одним решением. Нет никакого смысла запускать сразу оба решения для MySQL; к тому же, это позволит сохранить немного памяти.

После некоторого обдумывания, в особенности после чтения статьи Mark Maunder (который тестировал MySQL, используя оба подхода), я пришел к выводу, что MyISAM может оказаться предпочтительным выбором для сред с одним CPU. А поскольку в данном руководстве мы будем использовать небольшой виртуальный сервер, имеющий одно ядро CPU, то есть смысл остановиться на MyISAM.

Открываем /etc/mysql/my.cnf (вам понадобится текстовый редактор; nano – наиболее популярный из них, установленный на большинстве систем; если он отсутствует, выполните команду «sudo apt-get install nano») и добавляем/меняем следующее:

01#
02# * MySQL configuration for tiny memory footprint
03#
04[client]
05port = 3306
06socket = /var/run/mysqld/mysqld.sock
07
08[mysqld_safe]
09socket = /var/run/mysqld/mysqld.sock
10nice = 0
11
12[mysqld]
13#
14# * Basic Settings
15#
16user = mysql
17pid-file = /var/run/mysqld/mysqld.pid
18socket = /var/run/mysqld/mysqld.sock
19port = 3306
20basedir = /usr
21datadir = /var/lib/mysql
22tmpdir = /tmp
23lc-messages-dir = /usr/share/mysql
24skip-external-locking
25skip-networking
26key_buffer = 24M
27sort_buffer_size = 4M
28read_buffer_size = 4M
29#binlog_cache_size = 2M
30max_allowed_packet = 12M
31thread_stack = 128K
32thread_cache_size = 8
33
34# This replaces the startup script and checks MyISAM tables if needed
35# the first time they are touched
36myisam-recover = BACKUP
37
38#max_connections = 200
39#table_cache = 64
40table_cache = 128
41thread_cache = 256
42#thread_concurrency = 10
43thread_concurrency = 4
44myisam_sort_buffer_size = 1M
45tmp_table_size = 12M
46max_heap_table_size = 12M
47wait_timeout = 200
48interactive_timeout = 300
49max_connect_errors = 10000
50
51#
52# * Query Cache Configuration
53#
54query_cache_type = 1
55query_cache_limit = 1M
56query_cache_size = 16M
57
58#
59# * InnoDB
60#
61# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
62# Read the manual for more InnoDB related options. There are many!
63
64skip-innodb
65default-storage-engine = myisam
66skip-external-locking
67skip-slave-start
68skip-name-resolve
69
70[mysqldump]
71quick
72quote-names
73max_allowed_packet = 16M
74
75[mysql]
76#no-auto-rehash # faster start of mysql but no tab completition
77
78[isamchk]
79key_buffer = 16M
80#
81# * IMPORTANT: Additional settings that can override those from this file!
82# The files must end with '.cnf', otherwise they'll be ignored.
83#
84!includedir /etc/mysql/conf.d/

Небольшое разъяснение по данной конфигурации: возможно, вы уже видели руководства по улучшению производительности MySQL (некоторые были даже от Мулленвега), и параметры в них были несколько выше. Здесь мы пойдем на компромисс: нам не нужна плохая производительность MySQL, однако и потребление слишком больших объемов памяти нас не устроит.

Другим более интересным аспектом может выступать отсутствие сетевого соединения (обход расширения имен и т.д.) – в таком случае мы можем обойтись без InnoDB. Так мы сможем сохранить некоторые сетевые буфера, однако, естественно, это означает, что WordPress должен быть связан с MySQL на сокете Unix и должен быть установлен на ту же самую машину; чуть позже мы посмотрим, как это работает.

Если вы предпочитаете запускать два сервера, связанные друг с другом, на одном из которых находится MySQL, а на другом — Nginx/WordPress, то тогда, естественно, вам понадобится включить сетевое соединение. Это может оказаться более подходящей средой для облачных сетей – некоторые провайдеры позволяют вам распределять определенные ресурсы CPU, памяти и дискового пространства, однако вы можете запускать столько экземпляров, сколько вам потребуется.

Обычно только некоторые из них доступны для внешнего мира. Все остальные ресурсы находятся в «частной» сети, которая закрыта от посторонних. Облачные провайдеры обычно не взимают платы за трафик между вашими виртуальными экземплярами – вы платите только за трафик, который пересекает границу с «реальным миром».

Даже если у вас есть открытые сетевые соединения, в данном случае они будут полностью закрыты от внешнего мира и надежно защищены. Естественно, впоследствии вы можете дублировать экземпляры MySQL (или экземпляры фронтэнда) в случае необходимости.

В данном руководстве мы сохраним вещи простыми: все будет храниться на одном виртуальном сервере, потому сетевое соединение нам не понадобится – вместо этого мы организуем взаимодействие через сокеты Unix.

Запускаем MySQL:

01service mysql start

Мы должны установить root-пароль (аккаунт администратора) для MySQL, поскольку по умолчанию он пуст. Есть много способов сделать это, однако в Ubuntu 12.04 для MySQL 5.5 есть специальная команда:

01sudo dpkg-reconfigure mysql-server-5.5

При работе с другими версиями или системами вам понадобится использовать следующие команды:

01sudo mysqladmin -u root -h localhost password 'mypassword'
02sudo mysqladmin -u root -h myhostname password 'mypassword'

Не забудьте задать сложный пароль, по возможности сгенерированный случайным образом.

Установка Nginx

Следующий шаг – установка Nginx, программного приложения, которое находится в постоянном развитии с целью улучшении безопасности. К сожалению, разработчики Ubuntu не всегда учитывают последние обновления Nginx, потому рекомендованный выбор, как указывает Nginx Wiki, заключается в загрузке приложения из стороннего хранилища (изPersonal Package Archive, PPA), которое составляется и поддерживается обычными людьми, и которое не связано с nginx.org. Такое приложение будет иметь в себе некоторые дополнительные откомпилированные модули, которые, возможно, подойдут для вашей среды.

01sudo -s
02nginx=stable # use nginx=development for latest development version
03add-apt-repository ppa:nginx/$nginx
04apt-get update
05apt-get install nginx

Если вы получили ошибку «add-apt-repository  не существует», то тогда вам понадобится установить python-software-properties:

01sudo apt-get install python-software-properties

После чего запустить приведенные выше команды снова.

Обзор конфигурации Nginx

Вы можете запускать Nginx и Apache совместно на одном и том же сервере (к примеру, Nginx работает со статичным контентом, а Apache – с PHP), однако в данном руководстве мы предположим, что запущен только Nginx, и будем использовать ту же самую структуру директорий (для хранения актуальных файлов веб-сайтов), которая используется в Apache.

Зачем? Все просто — вы легко сможете перейти на Apache, если вам чем-то не понравится Nginx; или, если вы будете следовать за некоторыми руководствами в сети, которые предполагают, что вы имеете «стандартную» структуру директорий для дистрибутива Linux с Apache, то тогда вам не придется долго размышлять над тем, в верный ли каталог вы скопировали файлы.

Это означает то, что все данные будут помещены в /var/www директорию. Nginx всегда поддерживает конфигурационный стиль, аналогичный приложениям под Debian/Ubuntu. Основная конфигурационная директория — /etc/nginx. Основной конфигурационный файл — /etc/nginx/nginx.conf. Дополнительные конфигурационные файлы (мы будем использовать их, чтобы добавить конфигурации, относящиеся к WordPress) — /etc/nginx/conf.d; они будут автоматически загружаться при рестарте/перезагрузке Nginx.

Наконец, все относящиеся к веб-сайтам конфигурации (для каждого виртуального хоста) будут храниться в /etc/nginx/sites-available. Каждый раз, когда вы создаете новый виртуальный хост, его конфигурационный файл будет символически связан с /etc/nginx/sites-enabled.

Некоторые конфигурации Nginx, которые вы найдете в этой папке, будут просто состоять из одного файла, используемого для всех возможностей (Nginx обычно не имеет длинных конфигурационных файлов). Однако здесь мы внесем некоторые корректировки – мы разделим все настройки по сложившейся традиции Debian/Ubuntu. Идея ее заключается в том, что каждый виртуальный хост будет иметь как можно меньше различной информации, и всегда будет обращаться к общим правилам.

Установка PHP5, расширений PHP5 и PHP-FPM

Nginx, как вы помните, обрабатывает только статичные файлы – все остальное нужно передавать внешним сервисам. В нашем случае мы будем использовать PHP-FPM для обработки PHP5. PHP-FPM – это мини-сервер, обладающий своими собственными настройками, единственной задачей которого является обработка PHP. Мы вернемся к нему позже.

Определить, какие из расширений PHP5  вам действительно нужны, не так уж просто. Для данного руководства нам понадобится PHP5 с минимальным числом расширений (чтобы не расходовать лишнюю память!), необходимых для WordPress (и некоторых плагинов).

Таким образом, я буду следовать за рекомендациями Rahul Bansal. На первом шаге мы убедимся в том, что действительно получили PHP 5.4 (вместо стандартного PHP 5.3, который поставляется с Ubuntu 12.04 LTS). Новый версии Ubuntu могут уже содержать PHP 5.4 по умолчанию.

01sudo add-apt-repository ppa:ondrej/php5
02sudo apt-get update

Теперь вы должны установить PHP5 и все необходимые модули:

01sudo apt-get install php5-common php5-mysql php5-xmlrpc php5-cgi php5-curl php5-gd php5-cli php5-fpm php-apc php5-dev php5-mcrypt

Для некоторых WordPress-плагинов вам, возможно, понадобится добавить php5-pear к данному списку команд (а также некоторые другие команды, как, к примеру, php5-imap, если вам требуются почтовые рассылки). Пользователям из разных стран, возможно, пригодится команда php5-intl. Я обычно добавляю php5-tidy для W3 Total Cache, но это не всегда требуется.

Настройка Nginx

Перед тем как показать вам, что делает представленная ниже конфигурация Nginx, важно остановиться на некоторых правилах его настройки: поскольку он получает URL, Nginx должен знать, что с ним делать – взять из определенной директории статичный файл (изображения, CSS и т.д.), передать PHP-скрипт в PHP-FPM или блокировать доступ (из соображений безопасности).

Безусловно, Nginx может делать и более углубленную обработку, добавлять no-expiry-заголовки, удалять cookie-запросы для статичных файлов (для наилучшего кэширования), проводить gzip-архивацию всех файлов (для сохранения пропускной способности).

Ниже представлен файл /etc/nginx/nginx.conf, который обрабатывает большую часть общих возможностей:

01user www-data;
02worker_processes 1;
03pid /var/run/nginx.pid;
04events {
05 worker_connections 256;
06 # multi_accept on;
07}
08http {
09 ##
10 # Basic Settings
11 ##
12 sendfile on;
13 tcp_nopush on;
14 tcp_nodelay on;
15 keepalive_timeout 65;
16 types_hash_max_size 2048;
17 server_tokens off;
18 client_max_body_size 8m;
19 reset_timedout_connection on;
20 # server_names_hash_bucket_size 64;
21 # server_name_in_redirect off;
22 index index.php index.html index.htm;
23 include /etc/nginx/mime.types;
24 default_type application/octet-stream;
25 ##
26 # Logging Settings
27 ##
28 access_log /var/log/nginx/access.log;
29 error_log /var/log/nginx/error.log;
30 ##
31 # Gzip Settings
32 ##
33 gzip on;
34 gzip_disable "msie6";
35upstream php5-fpm {
36 keepalive 8;
37 server unix:/var/run/php5-fpm.sock;
38 }
39include /etc/nginx/conf.d/*.conf;
40 include /etc/nginx/sites-enabled/*;
41}

Отметьте для себя несколько важных моментов. Первое: worker_processes должен быть установлен в 1 для одного CPU (в моем VPS я имею только один CPU). client_max_body_size  — это размер загружаемых файлов через POST; я предпочитаю оставлять его по умолчанию — 1m (один мегабайт), однако 8 – стандартное значение, используемое PHP для загрузок файлов, таким образом, я предпочитаю менять его на 8m, чтобы избежать разногласий.

Команда upstream необходима для объединения с PHP-FPM: точно так же, как и в случае с MySQL, мы будем использовать сокеты Unix для связи с PHP-FPM. Если бы у вас была сборка с Nginx на одном VPS и PHP-FPM на другом (используя Nginx, скажем, в качестве фронтэнд прокси/кэширующего сервера), то в таком случае вам нужно было бы использовать команду server my.ip.address:portnumber.

В данном руководстве мы покажем вам, как задать конфигурацию как для отдельного сайта, так и для мультисайтов в WordPress. Конфигурационные файлы для этих двух вариантов будут храниться в папке /etc/nginx/conf.d/, поэтому мы сможем активировать их в случае необходимости. По этой причине строка закомментирована – нам не требуется загружать сразу обе конфигурации, ибо в режиме мультисайтов WordPress функционирует совершенно иначе, чем в своем обычном режиме.

Конфигурация для одиночной сборки WP (сохраните в /etc/nginx/conf.d/wordpress.conf) основана на соответствующей статье в Nginx Wiki, которая предостерегает от популярных ошибок и описывает подходящий вариант настройки:

01# WordPress single blog rules.
02# Designed to be included in any server {} block.
03# This order might seem weird - this is attempted to match last if rules below fail.
04# http://wiki.nginx.org/HttpCoreModule
05location / {
06 try_files $uri $uri/ /index.php?$args;
07}
08# Add trailing slash to */wp-admin requests.
09rewrite /wp-admin$ $scheme://$host$uri/ permanent;
10# Directives to send expires headers and turn off 404 error logging.
11location ~* ^.+.(xml|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
12 access_log off; log_not_found off; expires max;
13}
14# Uncomment one of the lines below for the appropriate caching plugin (ifused).
15#include global/wordpress-wp-super-cache.conf;
16#include global/wordpress-w3-total-cache.conf;
17# Pass all .php files onto a php-fpm/php-fcgi server.
18location ~ .php$ {
19 # Zero-day exploit defense.
20 # http://forum.nginx.org/read.php?2,88845,page=3
21 # Won't work properly (404 error) if the file is not stored on this server, which is
22 #  entirely possible with php-fpm/php-fcgi.
23 # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  #  And then cross your fingers that you won't get hacked.
24 try_files $uri =404;
25 #fastcgi_split_path_info ^(.+.php)(/.+)$;
26 #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
27 include fastcgi_params;
28 fastcgi_index index.php;
29# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
30# fastcgi_intercept_errors on;
31 fastcgi_keep_conn on;
32 fastcgi_pass php5-fpm;
33}

А теперь правила для WordPress в режиме мультисайтов (сохраните в /etc/nginx/conf.d/wordpress-mu.conf):

01# WordPress multisite subdirectory rules.
02# Designed to be included in any server {} block.
03index index.php;
04# This order might seem weird - this is attempted to match last if rules below fail.
05# http://wiki.nginx.org/HttpCoreModule
06location / {
07 try_files $uri $uri/ /index.php?$args;
08}
09# Add trailing slash to */wp-admin requests.
10rewrite /wp-admin$ $scheme://$host$uri/ permanent;
11# Pass all .php files onto a php-fpm/php-fcgi server.
12location ~ .php$ {
13 # Zero-day exploit defense.
14 # http://forum.nginx.org/read.php?2,88845,page=3
15 # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
16 # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
17 try_files $uri =404;
18# fastcgi_split_path_info ^(.+.php)(/.+)$;
19 #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
20include fastcgi_params;
21 fastcgi_index index.php;
22# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
23# fastcgi_intercept_errors on;
24 fastcgi_pass php5-fpm;
25}
26location ~ ^/files/(.*)$ {
27 try_files /wp-content/blogs.dir/$blogid/$uri /wp-includes/ms-files.php?file=$1;
28 # access_log on; log_not_found on; expires max;
29}
30#avoid php readfile()
31location ^~ /blogs.dir {
32 internal;
33 alias /var/www/wordpress/wp-content/blogs.dir ;
34 access_log off; log_not_found off; expires max;
35}
36# Directives to send expires headers and turn off 404 error logging.
37location ~* ^.+.(xml|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
38 access_log off; log_not_found off; expires max;
39}

Различие по большей части касается загрузок файлов – мультисайтовая сборка WordPress имеет одну «общую» область, однако отдельные области под загрузки. Мы увидим позже, как это работает (подсказка: нам понадобится провести domain mapping для корректных значений $blogid).

На данный момент эта конфигурация не является идеальной: я должен был явно добавить alias /var/www/wordpress/wp-content/blogs.dir; в идеале это должно быть задано в конфигурации каждого виртуального сервера, иначе это будет работать для всей сборки мультисайтов.

Также мы добавим общий набор ограничений, чтобы сделать Nginx более безопасным. Поместим их в файл /etc/nginx/conf.d/restrictions.conf:

01# Global restrictions configuration file.
02# Designed to be included in any server {} block.</p>
03location = /favicon.ico {
04 log_not_found off;
05 access_log off;
06}
07location = /robots.txt {
08 allow all;
09 log_not_found off;
10 access_log off;
11}
12# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
13# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
14location ~ /. {
15 deny all;
16}
17# Deny access to any files with a .php extension in the uploads directory
18# Works in sub-directory installs and also in multisite network
19# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
20location ~* /(?:uploads|files)/.*.php$ {
21 deny all;
22}

Все, что осталось нам сделать – это задать конфигурационные файлы для отдельных веб-сайтов. Однако сначала мы должны настроить PHP-FPM; затем, после установки WordPress, мы сможем увидеть, как все это работает вместе: на данном этапе мы можем увидеть только ошибки конфигурации:

01sudo service nginx configtest

Если ошибок нет, вы увидите:

01Testing nginx configuration: nginx.

Настройка PHP-FPM

Сам PHP5 настраивается в /etc/php5. В Debian/Ubuntu каждый способ запуска PHP5 будет иметь свою собственную конфигурацию – к примеру, apache2 для Apache-конфигурации, cli для command-line-версии PHP5, и, естественно, fpm для PHP-FPM. Все они настраиваются независимо друг от друга, что может показаться слишком запутанным, поскольку вы можете запускать различные модули и иметь разные параметры для каждой конфигурации.

Мы начнем с /etc/php5/fpm/php.ini, поскольку этот файл не требует масштабных изменений. Убедимся в том, что memory_limit = 128M (вы можете задать меньший объем памяти, однако учтите, что W3 Total Cache потребляет много памяти – в обмен на сверхбыструю производительность). Возможно, вы заметили из конфигурации Nginx, что мы должны использовать cgi.fix_pathinfo=0. Также не забудьте установить date.timezone для вашего собственного часового пояса (это обязательно для PHP 5.4). Все остальное можно оставить стандартным.

Проверьте в /etc/php5/fpm/conf.d, какие модули PHP5 будет загружать. В моем случае мне понадобилось удалить 20-snmp.ini, который мне не требовался. Каждый из этих файлов вызывает соответствующее расширение и позволяет вам задавать дополнительные параметры. У вас должно быть что-то похожее на следующий список:

0110-pdo.ini
0220-apc.ini
0320-curl.ini
0420-gd.ini
0520-mcrypt.ini
0620-mysql.ini
0720-mysqli.ini
0820-pdo_mysql.ini
0920-xmlrpc.ini

Теперь нужно настроить сервисы, которые обеспечивают PHP для Nginx. PHP-FPM имеет для этого дополнительный конфигурационный файл, хранящийся в /etc/php5/fpm/php-fpm.conf. Нам не нужно изменять этот файл; это глобальная конфигурация для PHP-FPM. Затем запускаются несколько пулов.

PHP-FPM работает как веб-сервер с виртуальными хостами: php-fpm.conf содержит полную конфигурацию; также у нас есть отдельные конфигурации для пулов в каталоге /etc/php5/fpm/pool.d/. По умолчанию имеется только один пул, www.conf, и нам нужно его отредактировать. Это длинный файл – я просто покажу, какие изменения нужно сделать:

01listen = /var/run/php5-fpm.sock
02pm = dynamic
03pm.max_children = 20
04pm.start_servers = 3
05pm.min_spare_servers = 1
06pm.max_spare_servers = 5
07pm.max_requests = 500

Где-то это мы уже видели, верно? Для начала нам нужно убедиться в том, что PHP-FPM использует тот же сокет Unix, что и Nginx. Затем мы используем динамическое распределение пулов – в данном случае, мы инициируем запуск PHP-FPM с трех серверов (т.е. три процесса, готовые получать PHP-запросы от Nginx), ограничив максимальное количество серверов до 20, не нужно держать слишком много запасных серверов. Всякий раз, когда дочерний процесс будет обслуживать 500 запросов, он будет убит.

Естественно, это относится к моей собственной сборке – 512 Мб памяти, часть которой требуется MySQL и Nginx (правда, Nginx ест не так много памяти). После тщательной настройки параметров моя среда позволяет обслуживать 10 параллельных запросов и хранить все процессы в памяти – без свопинга!

Естественно, это зависит от того, как много расширений вы загружаете в PHP5, какое число параллельных запросов вам нужно (10 одновременных соединений – это не так много), как быстро загружаются ваши страницы (что, в свою очередь, зависит от плагинов, виджетов, внешних вызовов и т.д.).

Вам понадобится долго играться с этими числами, пока вы не получите приемлемую производительность, избегая свопинга и длительного ожидания загрузки страниц.

Если вы хотите иметь отдельные логи, в которых будут отмечаться разные события, такие как слишком ранняя смерть процесса из-за нехватки ресурсов, проблемы соединения с Nginx и аналогичные ошибки, добавьте следующий код в файл конфигурации пула www.conf:

01php_admin_value[error_log] = /var/log/fpm-php.www.log

В противном случае PHP-FPM будет просто пересылать большую часть ошибок через Nginx (но не все), и они будут отражены в логе веб-сервера.

Запустите PHP-FPM:

01sudo service php5-fpm start

Убедитесь в том, что в Ubuntu запущены MySQL, Nginx и PHP-FPM; в противном случае используйте update-rc.d для их проверки.

Установка WordPress

Большая часть пользователей устанавливает WordPress напрямую из источника, хорошее руководство для этого находится на сайте Ubuntu Server Guide. Мне лично не нравится тот способ, как Ubuntu обрабатывает WordPress в виде приложения. Было бы лучше объединить все в одну цельную систему, и вы получали бы только необходимые обновления от команды разработчиков Ubuntu. Последнее обновление происходило достаточно давно. В случае с WordPress, самая последняя (и самая лучшая) версия является одновременно и самой защищенной, потому я рекомендую устанавливать систему вручную.

Несмотря на то что Nginx способен считывать любую информацию практически из любого места структуры директорий, я остаюсь верным способу организации вещей «Apache/Ubuntu», потому храню все в /var/www – включая и виртуальный хост, который будет содержать нашу сборку WordPress.

01sudo -i
02cd /var/www
03wget -O wordpress.tar.gz http://wordpress.org/latest.tar.gz
04tar -zxvf wordpress.tar.gz
05chown -R www-data:www-data /var/www/wordpress
06rm wordpress.tar.gz

Теперь мы должны обработать нашу базу данных. WordPress требует «чистую» базу данных (недавно созданную). В данном примере мы также добавим пользователя только для этой базы данных.

Все изменения в базу данных мы будем вносить через командную строку. Заходим на mysql сервер под root-пользователем:

01mysql -u root -p

Создаем базу данных wordpress:

01CREATE DATABASE wordpress;

Создаем пользователя, который получит доступ только к этой базе данных; пусть его имя также будет wordpress:

01CREATE USER wordpress;

Задаем пароль для пользователя wordpress – «VeryHardToFigureOut2013!» (можете использовать любой другой):

01SET PASSWORD FOR wordpress = PASSWORD("VeryHardToFigureOut2013!");

Предоставляем пользователю wordpress все полномочия по работе с базой данных wordpress:

01GRANT ALL PRIVILEGES ON wordpress.* TO wordpress@localhost IDENTIFIED BY'VeryHardToFigureOut2013!';
02FLUSH PRIVILEGES;

Теперь мы можем закончить сессию работы:

01exit

Обычно я пытаюсь потом сразу же войти под новым пользователем, чтобы проверить, что имя и пароль заданы верно.

Теперь настало время конфигурации. WordPress сделает большую часть работы самостоятельно, однако сначала нам надо, чтобы Nginx опознал наш новый сайт.

Откроем /etc/nginx/sites-available/mydomain.conf и введем следующее:

01map $http_host $blogid {
02 default 0;
03 mydomain.com 1;
04}
05server {
06 server_name mydomain.com;
07 root /var/www/wordpress;
08 access_log /var/log/nginx/mydomain.com-access.log;
09 error_log /var/log/nginx/mydomain.com-error.log;
10 include conf.d/restrictions.conf;
11 include /var/www/wordpress/nginx.conf;
12 include conf.d/wordpress-mu.conf;
13}

Мы вернемся к этому позже.

01cd /etc/nginx/sites-enabled
02ln -s /etc/nginx/sites-available/mydomain.conf
03touch /var/www/wordpress/nginx.conf

Отметьте для себя, что последняя команда является требованием W3 Total Cache (этот файл должен существовать и должен быть открыт для чтения пользователю веб-сервера).

Наконец, чтобы убедиться в том, что сервер может прочитать все это, выполним следующую команду:

01chown -R www-data:www-data /var/www/wordpress

Запуск установщика WordPress

create-configuration-file

Переходим дальше и позволяем WordPress создать конфигурационный файл.

lets-go

Щелкаем Let’s Go

database-connection-details

Заметьте, что хост базы данных: localhost:/var/run/mysqld/mysqld.sock. WordPress сможет обращаться к базе данных через сокет Unix, который настраивается для MySQL по умолчанию, и, как было сказано, полностью обходит любые сетевые TCP-соединения.

Если все идет по плану, вы можете сделать следующие знакомые вам шаги:

install-wordpress

Если что-то пошло не так, вы, возможно, столкнетесь с двумя ошибками. Первая из них состоит в том, что наша «необычная» MySQL-установка неверно сконфигурирована. Вторая – либо пароль, либо параметр был задан неверно; вернитесь обратно и исправьте это. Помните, что лучше не использовать в качестве имени суперадминистратора admin; недавняя ботнет-атака на WP-сайты относилась именно к «admin» и перебору паролей для него.

После этого вы должны легко входить в консоль; WordPress запущен в обычном режиме («один сайт»). Теперь переходим к следующему шагу!

Определяем мультисайты

Чтобы перевести WP в мультисайтовый режим, нам понадобится открыть /var/www/wordpress/wp-config.php в текстовом редакторе. Если вы делали это ранее, то проблем не возникнет. Над строкой:

01/* That's all, stop editing! Happy blogging. */

Добавим следующее:

01/* Multisite */
02define('WP_ALLOW_MULTISITE', true);

Обновляем страницу в браузере, после чего появляется новая опция Tools & Network Setup:

01/* Multisite */
02define('WP_ALLOW_MULTISITE', true);

Для данного руководства я настрою отдельные поддомены. На то есть своя причина – это заметно упростит использование Nginx. Если вы нажмете сейчас Install, WP выполнит некоторую проверку и, скорее всего, возвратит ошибку об отсутствующих «wildcard-доменах». Не беспокойтесь. Нам просто нужно внести в wp-config.php дополнительные изменения. Как вы могли видеть, WP «предполагает», что вы работает под Apache, таким образом, мы по большей части будем игнорировать второй шаг, и просто добавим командные строчки с шага 1 в wp-config.php:

01define('MULTISITE', true);
02define('SUBDOMAIN_INSTALL', true);
03define('DOMAIN_CURRENT_SITE''mydomain.com');
04define('PATH_CURRENT_SITE''/');
05define('SITE_ID_CURRENT_SITE', 1);
06define('BLOG_ID_CURRENT_SITE', 1);

Помните, что все это должно стоять ниже определения define(‘WP_ALLOW_MULTISITE’, true); , однако перед строкой:

01/* That's all, stop editing! Happy blogging. */

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

Добавление плагинов

Нам понадобится по меньше мере плагин W3 Total Cache. Я предположу, что вы знакомы с процедурой установки плагинов, поэтому не стану в нее углубляться. Переходим к My Sites > Network Admin > Dashboard и выбираем Plugins > Add New, далее ищем W3 Total Cache, устанавливаем его, и выставляем для него Network Activate. Одна из примечательных особенностей W3TC состоит в том, что вы можете конфигурировать его сразу для всех сайтов в мультисайтовой среде, и это именно то, что мы хотим сделать.

На данном этапе вы, вероятно, добавите все свои любимые плагины. Я лично являюсь фанатом Jetpack, поскольку он включает в себя много полезных вещей – анти-спам, статистика, Photon для кэширования изображений в облаке WP.com (что может показаться очень удобным для экономии трафика), а также хорошая система для управления интеграцией с социальными сетями. Из-за разных инцидентов с безопасностью WP я также устанавливаю Limit Login Attempts.

Также мне импонирует пара плагинов от Human Made Limited: WP Remote иBackUpWordPress. Первый из них позволяет управлять всеми блогами WP (даже если они расположены на разных серверах!), причем плагин является бесплатным  — с его помощью вы можете проверять актуальность плагинов, тем, системы, не забывая обновляться. BackUpWordPress – возможно, один из самых простых бесплатных плагинов для бэкапа, позволяющий создавать резервные копии и базы данных, и контента; как показал мой опыт, этот плагин является одним из самых простых решений для выполнения переезда с одного сервера на другой.

Когда оба плагина установлены, вы можете легко взять свои бэкапы из специального хранилища WP Remote для любого вашего сайта. Таким образом, если вы управляете большим количеством WP-блогов на разных серверах, оба плагина необходимы. Поскольку они являются бесплатными, просты в использовании и справляются с поставленными задачами, нет никаких причин для того, чтобы обходить их, даже учитывая тот факт, что существуют лучшие (платные) альтернативы. Естественно, выбирать вам!

Обязательно нужно будет установить плагин WordPress MU Domain Mapping. Есть несколько глубоко академических дискуссий о том, почему этот плагин не является частью ядра WP. Вообще, у вас есть два варианта создания сети сайтов: либо они все будут находиться под одним доменом, но в разных директориях (к примеру, mydomain.com/site1, mydomain.com/site2), либо под разными поддоменами (site1.mydomain.com, site2.mydomain.com). В большинстве реальных ситуаций мы имеем полностью различающиеся домены для каждого сайта, потому нам потребуется способ управления ими всеми сразу.

Тут в игру вступает WordPress MU Domain Mapping: вы можете указывать ему, что определенный домен – к примеру myotherdomain.com или anotherdomain.com – относится к определенным сайтам в вашей сборке. Очевидно, вам понадобится некоторая помощь Nginx. Целью следующих шагов будет добавление этих двух сайтов, проверка, что они указывают на нужное место, а также тестирование корректной передачи запросов от Nginx к сайтам. И все это при работающем W3 Total Cache!

Для начала давайте проверим, что W3 Total Cache работает при заданной конфигурации. В панели Network Administration переходим по ссылке Performance > Dashboard и щелкаем Check Configuration. Если все хорошо, вы получите что-то, напоминающее следующее:

w3tc-compatibility-test

Важно, чтобы Nginx был обнаружен. Также вы можете видеть, что у нас есть PHP со включенным модулем Alternative PHP Cache (APC).

Теперь идем в Performance > General Settings и включаем кэширование Page Cache, Minify, Database Cache, Object Cache (и Browser Cache, включенный по умолчанию). В качестве метода используем Opcache: Alternative PHP Cache (APC). Сохраняем конфигурацию — Save All Settings. W3TC должен вам сообщить, что нужно Empty the Page Cache (Почистить кэш страниц), потому выполняем и это.

Если все было сделано правильно, W3TC выполнит некоторые «магические пассы» для вас. Если вы теперь откроете файл /var/www/wordpress/nginx.conf, вы увидите небольшой сюрприз: W3TC уже заполнит его за вас! (если файл пуст или вы получили ошибку, это означает, что вы либо забыли выполнить touch для этого файла ранее, либо у вас нет корректных прав доступа; проверьте, что файл установлен в www-data:www-data и является перезаписываемым).

Тщательная настройка W3TC – это очень тонкое искусство, хотя с новыми версиями делать это стало проще. Page Cache прекрасно работает с настройками по умолчанию. Minify зависит от многих вещей и, возможно, является самым интересным моментом. Если вы пользуетесь CloudFlare и так же ленивы, как и я, просто позвольте CloudFlare выполнить минимизацию за вас. Если вы добавите свой логин от CloudFlare в W3TC, то последние версии плагина смогут связаться с вашим аккаунтом, пройти корректную идентификацию и настроить автоматическую минимизацию всех вещей, отключив родные настройки W3TC.

Лучше всего всегда проводить минимизацию через CloudFlare, вместо того чтобы тратить собственные драгоценные ресурсы на это. Однако я сталкивался с ситуацией, когда минимизация CloudFlare работала не слишком хорошо, а вот W3TC отлично справлялся с этой задачей. Все во многом зависит от тем и плагинов, которые вы используете, и приятно осознавать, что у вас всегда есть выбор.

Если вы не используете CloudFlare попробуйте автоматические настройки, и в Performance > Minify включите, как минимум, HTML & XML (с Inline CSS-минимизацией и Inline JS-минимизацией), JS и CSS. Это должно автоматически объединить все JS и CSS, что отразится на Google PageRank.

Обычно я не играюсь с Database Cache и Object Cache, однако всегда обращаюсь к Browser Cache и включаю все, кроме Prevent caching of objects after settings и Do not process 404 errors for static objects with WordPress (поскольку мне нравятся мои собственные страницы ошибок!)

Отметьте, что W3TC является плагином с очень активным циклом разработки. Это говорит о том, что многие настройки в нем постоянно добавляются и/или удаляются, особенно если они не так понятны и прозрачны. Если вы читаете это руководство по прошествии долгого времени с того момента, как оно было написано, то я советую вам проверить следующий W3TC-туториал, чтобы понять, какие опции были изменены и как они теперь работают.

Давайте теперь установим плагин WordPress MU Domain Mapping. Помните, что плагину требуется активированная сеть для работы. После установки переходим в раздел Domains > Domain Mapping и ставим чекбоксы в разделе Domain Options:

domain-options

Добавляем два новых сайта

На момент завершения руководства у вас должна быть сеть, состоящая из трех сайтов: mydomain.com, myotherdomain.com и anotherdomain.com. Мы сделаем следующий mapping:

  • mydomain.com будет указывать на общую сборку, сайт по умолчанию, т.е. mydomain.com.
  • myotherdomain.com будет указывать на site1.mydomain.com
  • anotherdomain.com будет указывать на site2.mydomain.com

Во-первых, вы должны перейти к поставщику DNS и добавить записи для всех этих сайтов. Мы уже видели, как был сконфигурирован mydomain.com с указанием на ваш IP-адрес. Теперь вам понадобится связать site1.mydomain.com, site2.mydomain.com, myotherdomain.com и anotherdomain.com с тем же самым IP-адресом (Nginx обработает все остальное).

Как только DNS будет обновлен (убедитесь в том, что все домены обладают корректным IP-адресом – одинаковым для всех!), мы можем начать добавление наших двух сайтов. Сделать это можно в разделе Network Admin > Sites > Add Site. В Site Address поместим site1; в Site Title – myotherdomain; в качестве электронной почты администратора укажем ту же, что и для основного сайта (myname@mydomain.com в данном руководстве). Точно так же для site2, используем anotherdomain в заголовке, и указываем тот же самый email.

Теперь давайте все это отобразим должным образом. Переходим в Settings > Domains. Вы увидите следующее сообщение:

01Please copy sunrise.php to /var/www/wordpress/wp-content/sunrise.php and ensure the SUNRISE definition is in /var/www/wordpress/wp-config.php

Во-первых, давайте скопируем этот файл (он будет являться обработчиком для domain mapping):

01cp /var/www/wordpress/wp-content/plugins/wordpress-mu-domain-mapping/sunrise.php /var/www/wordpress/wp-content/

Теперь открываем /var/www/wordpress/wp-config.php и добавляем в него:

01define( 'SUNRISE''on' );

над строкой:

01/* That's all, stop editing! Happy blogging. */

Переходим в Settings > Domains снова, теперь мы должны видеть следующее:

domains-settings

Мы готовы добавить наши mapping’s. К сожалению, панели для WordPress MU Domain Mapping не слишком удобные – мы должны сами найти ID сайтов.

К счастью, это не так трудно, поскольку все они перечислены в панели Sites > All Sites:

sites1111

Теперь, если вы наведете мышь на доменное имя, то получите ID; URL будет иметь следующий вид:

01http://mydomain.com/wp-admin/network/site-info.php?id=1

Заметьте, что появилась дополнительная колонка Mapping, которая была добавлена плагином WordPress MU Domain Mapping. Поначалу она пустая. Если вы выполняли шаги руководства, не добавляли и не удаляли какие-либо домены, то тогда логика будет простой: первый сайт будет иметь ID=1, второй ID=2, и так далее (но как только вы добавите и удалите домены, порядок может измениться).

Таким образом, мы должны сделать следующие привязки:

  • mydomain.com будет использовать ID 1 (по умолчанию, ничего добавлять не нужно)
  • myotherdomain.com будет использовать ID 2
  • anotherdomain.com будет использовать ID 3

Если настройки заданы корректно, то вы должны получить следующее:

domain-mapping-after-config

В разделе Sites > All Sites вы должны иметь:

sites-after-config

WordPress теперь настроен так, чтобы обрабатывать domain mapping, однако мы должны сказать об этом Nginx!

Поэтому давайте вернемся назад к открытому /etc/nginx/sites-available/mydomain.conf. Вы можете увидеть директиву map в самом верху файла. Мы должны повторить здесь то, что было настроено в WordPress:

01map $http_host $blogid {
02 default 0;
03 mydomain.com 1;
04 myotherdomain.com 2;
05 anotherdomain.com 3;
06}
07server {
08 server_name mydomain.com myotherdomain.com anotherdomain.com;
09 root /var/www/wordpress;
10access_log /var/log/nginx/mydomain.com-access.log;
11 error_log /var/log/nginx/mydomain.com-error.log;
12include conf.d/restrictions.conf;
13 include /var/www/wordpress/nginx.conf;
14 include conf.d/wordpress-mu.conf;
15}

Делаем рестарт nginx:

01sudo service nginx reload

Теперь пришло время тестирования! Если все сделано правильно, мы должны быть в состоянии просматривать http://myotherdomain.com/ и http://anotherdomain.com/ в браузере и они должны быть должным образом переадресованы.

Тестирование перед окончательным запуском

Руководство, представленное выше, требует наличия как минимум трех доменных имен, которые вы не используете для каких-либо своих целей, и, естественно, адаптации каждой строки кода под ваши реальные домены. Однако, возможно, вы захотели бы провести небольшое тестирование еще до старта процесса разработки, чтобы убедиться в том, что все было сконфигурировано верно.

Вот небольшой трюк, который вы можете использовать: с помощью HOSTS-файла можно создать «фэйковые» домены. Большинство компьютеров сконфигурировано на начальное чтение привязки статичных IP-адресов из HOSTS-файла, и только потом уже на получение DNS. Все, что вам нужно – это IP-адрес вашего сервера.

Вы должны выполнить это для двух мест: для сервера, на котором запущена ваша сборка WordPress и на вашем настольном компьютере. В Linux/Mac OS X файл находится в /etc/hosts, поэтому команда sudo nano /etc/hosts должна помочь вам отредактировать этот файл и добавить в самый низ его следующую строку:

01192.168.0.1 mydomain.com site1.mydomain.com site2.mydomain.com myotherdomain.com anotherdomain.com

Здесь вы должны заменить 192.168.0.1 на реальный IP-адрес вашего сервера. В Windows это зависит от версии, которую вы используете; обычно файл hosts хранится по адресу C:WINDOWSsystem32driversetchosts. Редактировать его лучше в Блокноте или в каком-нибудь специализированном текстовом редакторе, как Notepad++ (Word не подойдет, поскольку он добавляет ненужное форматирование, способное вообще все сломать к чертям).

После внесения всех изменений вам понадобится, скорее всего, закрыть браузер и запустить его снова (поскольку многие браузеры кэшируют DNS).

Тут есть несколько предостережений: поскольку вы не используете «реальные» DNS, в вашей сборке WordPress могут не работать плагины, которые требуют вызова XML-RPC. Яркий пример – Jetpack, который требует «реальные» адреса, поскольку он связывается напрямую с сервером.

Однако стоит отметить, что практически все остальные плагины – даже базовая возможность автообновления, которой необходимо связываться с «внешним» миром – не имеют таких ограничений. CloudFlare также может иметь некоторые проблемы: вы должны запретить CloudFlare чистить кэш, в противном случае он будет кэшировать неверный сайт! Лучше просто отключить его в своей среде разработки и активировать CloudFlare уже при переходе к среде производства.

Источник: wpmu.org & http://oddstyle.ru/wordpress-2/stati-wordpress/nastrojka-i-zapusk-multisajtov-v-wordpress-na-nginx.html