Переезд XenForo форума на современную платформу

  • Tutorial


Зачем это было нужно


Площадка для сообщества нашего продукта давно работает на базе форумного движка XenForo. До недавнего времени, форум работал VPS на базе CentOS 6.8 с вендорским Apache 2.2.15, MySQL 5.1 и PHP 5.6.

В связи с приближающимся релизом XenForo 2.0, у которого повышенные требования к компонентам, и общим желанием ускорить работу форума на современной компонентной базе, было принято решение о переезде на VPS с nginx, последней версией PHP и базой данных, работающей на Percona Server 5.7.

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

Подготовка VPS


В качестве операционной системы была выбрана CentOS 7.3 просто потому, что администратору rpm-based OSes ближе, чем deb-based :)

VPS располагает 25Gb дискового пространства, 4Gb RAM, а команда:

# cat /proc/cpuinfo | grep processor | wc -l

показывает число 8.

Сначала удаляем все ненужные пакеты, такие как Samba, httpd, и все, что посчитаете ненужным. Затем устанавливаем все доступные апдейты из официального репозитория с помощью:

# yum update

Далее нужно подключить все необходимые third-party репозитории и установить нужные нам компоненты. Первым устанавливаем сервер баз данных Percona. Подключаем репозиторий и устанавливаем необходимые пакеты:

# yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
# yum install Percona-Server-server-57

Здесь тонкость в том, что во время установки генерируется временный админский пароль, который нужно найти с помощью команды:

# grep 'temporary password' /var/log/mysqld.log

Он нам потребуется для дальнейшей security настройки Percona Server командой:

# /usr/bin/mysql_secure_installation

После этого вы получите постоянный пароль для вашего сервера баз данных.

Далее устанавливаем репозиторий nginx и сам пакет nginx:

# yum install epel-release
# yum install nginx

После этого устанавливаем свежайшую версию PHP со всеми необходимыми компонентами:

# cd /tmp
# curl 'https://setup.ius.io/' -o setup-ius.sh
# bash setup-ius.sh
# yum install php71u-fpm-nginx php71u-cli php71u-mysqlnd php71u-pecl-memcached php71u-opcache php71u-gd memcached

Включаем все нужные сервисы с помощью

# systemctl enable nginx
# systemctl enable memcached
# systemctl enable mysql
# systemctl enable php-fpm

чтобы после перезагрузки сервера, все они запускались автоматически. На этом подготовку заканчиваем и приступаем к самому сложному — настройке всего этого хозяйства для оптимальной работы нашего XenForo форума.

Настройка сервисов


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

Итак, для начала в файле /etc/php.ini установим значение параметра cgi.fix_pathinfo=0. Затем идем в файл /etc/php-fpm.d/www.conf, комментируем строчку listen = 127.0.0.1:9000 и раскомментируем listen = /run/php-fpm/www.sock. Дополнительно включаем listen.acl_users = nginx. Должно быть что-то вроде:

;listen = 127.0.0.1:9000
listen = /run/php-fpm/www.sock
listen.acl_users = nginx

В файле /etc/nginx/conf.d/php-fpm.conf тоже включаем работу через сокет:

#server 127.0.0.1:9000;
server unix:/run/php-fpm/www.sock;

Перезапускаем php-fpm:

# systemctl restart php-fpm

Сервис memcached по соображениям безопасности привязываем только к адресу 127.0.0.1:

# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="2048"
CACHESIZE="1024"
OPTIONS="-l 127.0.0.1"

Запускаем его с помощью:

# systemctl start memcached

убеждаемся, что порт 11211 открылся для соединений и настраиваем в конфиге XenForo его использование для кэширования backend-а в соответствии с официальной документацией XenForo. Но тут есть тонкость, вместо строчки:

$config['cache']['backend'] = 'Memcached';

у меня заработала строчка:

$config['cache']['backend']='Libmemcached';

Percona Server можно попробовать оптимизировать с помощью их визарда, либо известным скриптом mysqltuner.pl Все на ваше усмотрение и в соответствии с ресурсами вашего железа.

Имейте только в виду, что конфигурационный файл находится в /etc/percona-server.conf.d/mysqld.cnf

Самая сложная часть в этой истории — конфигурация nginx. В основных настройках ничего особенного. Только правильно выставите значения worker_processes (количество процессоров определяется командой cat /proc/cpuinfo | grep processor | wc -l) и worker_connections (worker_processes * 1024):

user nginx;
worker_processes 8;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 8192;
    use epoll;
    multi_accept on;
}

Дальше идет блок httpd. Тут тоже особенных тонкостей нет, за исключением одной, весьма важной. Дело в том, что у нас используется кэширование FastCGI, и для этого потребуются дополнительные настройки. Это кэширование требует включения двух блоков конфигурации в разных блоках nginx.conf. Для начала, как все выглядит в блоке httpd:

http {

    access_log  off;
    server_tokens off;
    charset utf-8;
    reset_timedout_connection on;
    send_timeout 15;
    client_max_body_size 5m;
    client_header_buffer_size    1k;
    client_header_timeout 15;
    client_body_timeout 30;
    large_client_header_buffers  2 1k;
    open_file_cache max=2000 inactive=20s;
    open_file_cache_min_uses 5;
    open_file_cache_valid 30s;
    open_file_cache_errors off;
    output_buffers      1 32k;
    postpone_output     1460;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    keepalive_requests  100000;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    ### FastCGI Cache ################
    map $http_cookie $nocachecookie {
     default                   0;
    ~xf_fbUid                  1;
    ~xf_user                   1;
    ~xf_logged_in              1;
}

    map $request_uri $nocacheuri {
       default              0;
    ~^/register             1;
    ~^/login                1;
    ~^/validate-field       1;
    ~^/captcha              1;
    ~^/lost-password        1;
    ~^/two-step             1;
}

fastcgi_cache_path              /tmp/nginx_fastcgi_cache levels=1:2 keys_zone=fastcgicache:200m inactive=30m;
fastcgi_cache_key               $scheme$request_method$host$request_uri;
fastcgi_cache_lock              on;
fastcgi_cache_use_stale         error timeout invalid_header updating http_500;
fastcgi_ignore_headers          Cache-Control Expires Set-Cookie;
### FastCGI Cache ################

Дальше мы еще вернемся к особенностям включения FastCGI кэширования в другом блоке, а пока посмотрим на следующий блок, server:

server {
    listen  80 reuseport;
    server_name  domain.com;
    return 301 https://domain.com$request_uri;
}
server {
    listen 443 ssl reuseport http2;
    server_name  domain.com;
    root  /var/www/html;
    ssl_certificate "/etc/nginx/ssls/ssl-bundle.crt";
    ssl_certificate_key "/etc/nginx/ssls/domain_com.key";
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers "EECDH:+AES256:-3DES:RSA+AES:RSA+3DES:!NULL:!RC4";
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 77.88.8.8 valid=300s;
    resolver_timeout 5s;
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header Strict-Transport-Security max-age=31536000;


Здесь важно конфигурирование SSL сертификата. В нашем случае используется сертификат от Comodo. Инструкцию по его подключению можно найти на их сайте, а для генерации /etc/ssl/certs/dhparam.pem используем команду:

# openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Последующую проверку правильности настройки SSL сертификата можно сделать тут.

И, наконец, последние важные блоки конфига nginx:

location / {
  index  index.php index.html;
  try_files $uri /index.php?$uri&$args;
  }

location ~ /(internal_data|library) {
         internal;
    }

location ~ /wp-content/ { return 444; }
location ~ /wp-includes/ { return 444; }

# define error page
error_page 404 = @notfound;

# error page location redirect 301
location @notfound {
    return 301 /;
}

error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

location ~ \.php$ {
    fastcgi_max_temp_file_size 1M;
    fastcgi_cache_use_stale updating;
    fastcgi_pass_header Set-Cookie;
    fastcgi_pass_header Cookie;
    fastcgi_pass  unix:/run/php-fpm/www.sock;
    fastcgi_index index.php;
    fastcgi_intercept_errors on;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 256 16k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
    proxy_buffer_size 8k;
    include fastcgi_params;

    ### fastcgi_cache ###
    fastcgi_cache           fastcgicache;
    fastcgi_cache_bypass    $nocachecookie $nocacheuri;
    fastcgi_no_cache        $nocachecookie $nocacheuri;
    fastcgi_cache_valid     200 202 302 404 403 5m;
    fastcgi_cache_valid     301 1h;
    fastcgi_cache_valid     any 1m;
    add_header X-Cache      $upstream_cache_status;
    ### fastcgi_cache end ###

        }

    gzip                   on;
    gzip_http_version      1.1;
    gzip_vary              on;
    gzip_min_length        1100;
    gzip_buffers           64 8k;
    gzip_comp_level        6;
    gzip_proxied           any;
    gzip_types             image/png image/gif image/svg+xml image/jpeg image/jpg text/xml text/javascript text/plain text/css application/json application/javascript application/x-javascript application/vnd.ms-fontobject
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";


location ~* \.(ico|css|js|gif|jpeg|jpg|png|woff|ttf|svg)$ {
    add_header "Access-Control-Allow-Origin" "*";
    root /var/www/html;
    expires 30d;
    add_header Pragma public;
    add_header Cache-Control "public";
}

}

}

Здесь очень важны параметры location для корректной работы ссылок ЧПУ, скриптов PHP и закрытия доступа к важным внутренним директориям internal_data и library. Кроме того, здесь включается gzip компрессия и кэширование статический медиа файлов. Ну и вторая часть настройки FastCGI кэширования.

Собственно сам переезд контента форума состоял в переносе дампа базы данных и tar.gz архива содержимого форумного root directory и разворачивании их на новом сервере.

Дополнительная информация о кэшировании в nginx


В начале, я попытался использовать nginx microcaching. Для начала создал директорию для хранения кэша:

# mkdir /var/cache/nginx2

Создал файл /etc/nginx/conf.d/microcache.conf с содержимым:

fastcgi_cache_path /var/cache/nginx2 levels=1:2 keys_zone=microcache:5m max_size=1000m;
map $http_cookie $cache_uid {
  default nil; # hommage to Lisp 
  ~SESS[[:alnum:]]+=(?<session_id>[[:alnum:]]+) $session_id;
}
map $request_method $no_cache {
  default 1;
  HEAD 0;
  GET 0;
}

и в конфиге nginx для php location сделал так:

location ~ \.php$ {
  fastcgi_cache microcache;
  fastcgi_cache_key $server_name|$request_uri;
  fastcgi_cache_valid 404 30m;
  fastcgi_cache_valid 200 10s;

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

Оказалось, что проблема лежит в глубинах движка XenForo и решается установкой плагина Logged In Cookie и правкой темплейтов XenForo helper_login_form и login_bar_form заменой строки:

<label class="rememberPassword"><input type="checkbox" name="remember" value="1" id="ctrl_pageLogin_remember" tabindex="3" /> {xen:phrase stay_logged_in}</label>

на строку:

<input type="hidden" name="remember" checked="checked" value="1" />

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

Вывод


После тестирования форума на Google Pagespeed и соответствующей дополнительной оптимизации, существенное ускорение работы форума было нельзя не заметить. Сейчас форум набирает 86 баллов из 100. Раньше, на Apache было 78 баллов. Есть еще над чем работать в плане оптимизации кода, в особенности для мобильной версии.

Кроме того, провел сравнение старого форума на Apache и нового на nginx нагрузочным тестированием на php скрипт общим количеством запросов 1000 и с числом одновременных соединений 300. Результаты налицо, как говорится:

Apache:


# ab -n 1000 -c 300 talk6.plesk.com/admin.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, www.zeustech.net
Licensed to The Apache Software Foundation, www.apache.org

Benchmarking talk6.plesk.com (be patient)
Completed 100 requests
SSL handshake failed (5).
SSL handshake failed (5).
Completed 200 requests
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
SSL handshake failed (5).
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software: Apache/2.2.15
Server Hostname: talk6.plesk.com
Server Port: 443
SSL/TLS Protocol: TLSv1/SSLv3,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path: /admin.php
Document Length: 3438 bytes

Concurrency Level: 300
Time taken for tests: 9.056 seconds
Complete requests: 1000
Failed requests: 44
(Connect: 0, Receive: 0, Length: 44, Exceptions: 0)

Write errors: 0
Total transferred: 3734136 bytes
HTML transferred: 3286728 bytes
Requests per second: 110.43 [#/sec] (mean)
Time per request: 2716.714 [ms] (mean)
Time per request: 9.056 [ms] (mean, across all concurrent requests)
Transfer rate: 402.69 [Kbytes/sec] received

Connection Times (ms)
min mean[±sd] median max
Connect: 0 1987 1940.1 1223 8748
Processing: 59 257 800.3 76 4254
Waiting: 0 79 31.4 72 211
Total: 234 2244 1926.3 1472 8811

Percentage of the requests served within a certain time (ms)
50% 1472
66% 2019
75% 2683
80% 3068
90% 4278
95% 8313
98% 8625
99% 8787
100% 8811 (longest request)

nginx:


# ab -n 1000 -c 300 talk.plesk.com/admin.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, www.zeustech.net
Licensed to The Apache Software Foundation, www.apache.org

Benchmarking talk.plesk.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software: nginx
Server Hostname: talk.plesk.com
Server Port: 443
SSL/TLS Protocol: TLSv1/SSLv3,ECDHE-RSA-AES128-GCM-SHA256,2048,128

Document Path: /admin.php
Document Length: 3437 bytes

Concurrency Level: 300
Time taken for tests: 5.585 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 3932790 bytes
HTML transferred: 3474807 bytes
Requests per second: 179.05 [#/sec] (mean)
Time per request: 1675.541 [ms] (mean)
Time per request: 5.585 [ms] (mean, across all concurrent requests)
Transfer rate: 687.65 [Kbytes/sec] received

Connection Times (ms)
min mean[±sd] median max
Connect: 182 1089 298.9 1185 1450
Processing: 55 261 279.5 159 1092
Waiting: 55 243 267.6 139 943
Total: 253 1350 81.5 1323 1510

Percentage of the requests served within a certain time (ms)
50% 1323
66% 1347
75% 1422
80% 1451
90% 1467
95% 1477
98% 1486
99% 1498
100% 1510 (longest request)

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

P.S. Был бы очень признателен знатокам и экспертам nginx в указании на ошибки и советах по дополнительной оптимизации конфигурации.
Plesk
Plesk – панель управления хостингом

Комментарии 6

    0
    Как-то странно, когда такая заметка от аккаунта компании разрабатывающей панель управления хостингом.
    Форум в /var/www/html, а php-fpm sock называется www.sock
      0
      Что странного? При развертывании проекта изначально не было привязки к Plesk, и задачи я себе такой не ставил.
        +1
        С одной стороны, этот комментарий напрашивается — ну как не подколоть вендора-то?..

        С другой стороны, если на VPSке только этот форум и крутится, то панель управления хостингом там очевидно излишня — разве что в Plesk сделают XenForo Toolkit сопоставимый с имеющимся WordPress Toolkit. (На что вряд ли хватит популярности XenForo.)
          0
          Это да. Если, например, на VPS запустить еще Elasticsearch для форума на XenForo, то для любой панели уже совсем ресурсов не останется :)
            0
            По сравнению с активным форумом панель ничего не потребляет. Просто по принципу KISS её не следует туда ставить.
              0
              С упоминанием принципа KISS ты заходишь на опасную территорию :)

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

      Самое читаемое