- PVSM.RU - https://www.pvsm.ru -

Настройка выделенного сервера для работы сайта под управлением HostCMS

В «жизни» практически любого веб-проекта – будь то небольшой интернет-магазин или сайт набирающего популярность бара – рано или поздно случается момент, когда не хватает ни возможностей и ресурсов shared-хостинга, ни средств для тотальной реорганизации архитектуры приложения. Несколько лет назад, когда я ещё работал в небольшой веб-студии, мне частенько приходилось наблюдать такую картину. Практически во всех подобных случаях принималось одно и то же решение – аренда выделенного сервера и перенос на него проекта в том виде, в котором он есть. В то время в сети было доступно немало статей по настройке серверов с Linux на борту. Причём практически все они были не самого лучшего качества и зачастую содержали настолько вредные советы [1], что господин Остер мог бы стоя аплодировать авторам тех материалов.

«Всё это дела давно минувших дней» – так я думал ещё совсем недавно, пока ко мне не обратился мой давний приятель за помощью в решении аналогичной проблемы. Как оказалось, ситуация с тех пор сильно не изменилась: нужный раздел документации [2] практически не обновился, сами разработчики в основном советуют воспользоваться shared-хостингом от своих партнёров, а толкового материала, учитывающего нюансы миграции на выделенный сервер [3] проекта на HostCMS, так и не нашлось. Мне нравится сама CMS, поэтому я решил исправить это упущение. Если интересно – добро пожаловать под кат.

Прежде всего оговорюсь. В этой статье я не буду рассматривать вопросы выбора хостинг-провайдера [3] – с этим, я думаю, вы справитесь сами. В качестве серверной ОС выбрана Ubuntu Server 14.04 как одна из наиболее дружелюбных к пользователю. Я предполагаю, что вы обладаете минимальным набором знаний для работы в Linux. К сожалению, здесь вы не найдете тонкой настройки PAM модуля для установки пользовательских лимитов на обращение к файлам и т.п. – если вы ищите такой материал, то скорее всего эта статья будет для вас скучна.

Первые шаги

Итак, у нас есть выделенный сервер [3] и данные для доступа к нему по ssh. Правило первое, оно же главное, старайтесь избегать постоянной работы от имени привилегированного пользователя. Во время первого же сеанса создайте собственную учетную запись и установите для нее пароль. Например, так:

useradd user_name -s /bin/bash -U -m -G sudo
passwd user_name 

Дальнейшую работу будем проводить уже от имени только что созданного пользователя.

Установка необходимого ПО

nginx

В качестве HTTP-сервера будет использоваться nginx. Думаю, что в представлении он не нуждается. Устанавливать его будем из репозитория [4], любезно развёрнутого командой разработчиков. Для этого необходимо получить ключ, которым подписаны установочные пакеты:

# иногда происходит неведомая фигня с добавлением ключей непосредственно из STDOUT
# поэтому сначала ключ сохраняем в файл и только потом добавляем
wget http://nginx.org/keys/nginx_signing.key 
sudo apt-key add nginx_signing.key
rm nginx_signing.key

И обновить список источников пакетов, добавив в файл /etc/apt/sources.list строки:

# 12.04 = precise
# 14.04 = trusty
deb http://nginx.org/packages/ubuntu/ trusty nginx
deb-src http://nginx.org/packages/ubuntu/ trusty nginx

После этого обновляемся и устанавливаем nginx:

sudo aptitude update && sudo aptitude upgrade -y
sudo aptitude install nginx

Чтобы задать лимиты на количество открываемых пользователем http-сервера файлов, нужно добавить в /etc/security/limits.conf строки:

nginx        hard    nofile  32768
nginx        soft    nofile  32768

Точные цифры следует подбирать, исходя из конфигурации вашего сервера. Активируется модуль лимитов добавлением следующей строки в /etc/pam.d/common-session:

session required     pam_limits.so

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

sudo su nginx --shell /bin/bash --command "ulimit -a"

PHP

HostCMS требует, чтобы были включены следующие модули php: curl, gd, xslt и, естественно, mysql. Кроме того, обратите внимание, что теперь пакет php5-json не является виртуальным и его нужно устанавливать отдельно. Помимо прочего подключим модуль кеширования опкода xcache. В качестве SAPI (режим запуска интерпретатора) будем использовать PHP-FPM, однако, чтобы иметь возможность выполлять некоторые скрипты по расписанию будет установлен еще и PHP-CLI.

sudo aptitude install php5-common php5-fpm php5-cli php5-curl php5-gd php5-mysql php5-xsl php5-json php5-xcache

MySQL

Установка MySQL довольная проста. Несколько раз установщик запросит у вас пароль для root'а сервера баз данных, можете смело оставлять его пустым — мы сменим его позже, с помощью утилиты mysql_secure_installation. При ее запуске ответьте, что хотите сменить пароль root'a, удалить тестовую БД и тестовых пользователей и обновить права на таблицы службной БД.

sudo aptitude install mysql-server
sudo mysql_secure_installation

Подробно почитать о настройке mysql-сервера можно здесь [5]. Статья отлично написана, поэтому не вижу смысла дублировать сюда информацию.

Настройка загрузки файлов

В качестве протокола передачи файлов я предлагаю использовать SSH FTP (SFTP). Во-первых, он безопаснее обычного ftp, так как данные будут передаваться в зашифрованном виде. Во-вторых, не придется устанавливать дополнительное ПО: все что нужно — ssh-сервер — у нас уже есть. А минусов практически никаких — все современные IDE и клиенты загрузки данных умеют работать с этим протоколом.
Чтобы определить, кому можно подключаться по sftp, создадим дополнительную группу пользователей, например, sftp:

sudo groupadd sftp

И активируем передачу данных, добавив в конец файла /etc/ssh/sshd_config строки:

Match Group sftp
	ChrootDirectory    %h
	ForceCommand       internal-sftp
	AllowTcpForwarding no

Подготовка файловой системы

Традиционно, файлы, относящиеся к веб-сайтам, размещаются в каталоге /var/www/. И мы не будем отступать от этого негласного правила. Создадим папку для виртуальных хостов и будущую точку монтирования быстрого кэша:

sudo mkdir -p -m 755 /var/www/data
sudo mkdir -m 777 /var/www/tmp

Затем укажем, что при следующей загрузке, в эту папку будет смонтирована tmpfs. Добавим в /etc/fstab:

tmpfs	/var/www/tmp/	tmpfs	defaults,noatime,nosuid,nodev,noexec,mode=1777,size=128M	0	0

Стоит заметить, что некоторые редакции HostCMS имеют встроенный алгоритм кеширования ответов в файлы. Если вы используете одну из таких редакций имеет смысл примонтировать tmpfs к директории кеша самой CMS.

Настройка виртуальных хостов

Если вы планируете развернуть на своем сервере несколько сайтов под управлением HostCMS, то описанную ниже процедуру придется повторить несколько раз. В этом случае имеет смысл попытаться автоматизировать процесс заведения нового хоста. Советую для этих целей обратить внимание на небольшой набор скриптов, описанных в этой статье [6], и «допилить» их под себя.

Заведение пользователя хоста

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

sudo useradd -b /var/www/data -s /usr/lib/sftp-server -m -U -G sftp example.com
sudo passwd example.com
sudo su example.com --shell /bin/bash --command "mkdir -m 0755 ~/data ~/log && mkdir -m 0777 ~/tmp"

Для корректной работы chroot'а нужно сделать root'a владельцем домашнего каталога этого пользователя:

cd /var/www/data
sudo chown root:root example.com

Заведение пула PHP-FPM

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

Пример конфига пула

[example.com]
user = example.com
group = example.com

listen = /var/run/php5_example.com.sock
listen.backlog = 4096
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

process.priority = 0
chdir = /

pm = dynamic
pm.max_children = 64
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 16
pm.process_idle_timeout = 60s;
pm.max_requests = 256

access.log = /var/www/data/example.com/log/php.access.log
access.format = "%R # %{HTTP_HOST}e # %{HTTP_USER_AGENT}e # %t # %m # %r # %Q%q # %s # %f # %{mili}d # %{kilo}M # %{user}C+%{system}C"

slowlog = /var/www/data/example.com/log/php.slow.log
request_slowlog_timeout = 2s
request_terminate_timeout = 300s

php_admin_flag[display_errors]     = off
php_admin_flag[log_errors]         = on
php_admin_value[error_log]         = /var/www/data/example.com/log/php.error.log
php_admin_value[memory_limit]      = 32M
php_admin_value[open_basedir]      = /var/www/data/example.com/:.
php_admin_value[upload_tmp_dir]    = /var/www/data/example.com/tmp
php_admin_value[session.save_path] = /var/www/data/example.com/tmp

Создание конфига виртуального хоста

В файле настройки хоста nginx вам нужно будет указать доменное имя сайта, путь для записи логов доступа и адрес юникс-сокета, который слушает php-fpm. Для обработки запросов к несуществующим файлам будем использовать именованный location — таким образом мы будем эмулировать работу mod_rewrite для Apache2. Перед тем, как отдавать на обработку скрипт нашему бэкэнду, проверяем его существование. Это позволить избежать проблемы, описанной здесь [7]. Для того, чтобы снизить нагрузку на сайт от незарегистрированных пользователей, будем использовать кеширование на стороне nginx. Для этого создадим конфигурационный файл /etc/nginx/conf.d/cache со следующим содержимым:

    fastcgi_cache_path  /var/www/tmp/cache levels=1:2 keys_zone=cache:32m max_size=128m;
    fastcgi_temp_path   /var/www/tmp/proxy 1 2;

    fastcgi_ignore_headers  Expires Cache-Control;

    fastcgi_cache_lock          on;
    fastcgi_cache_lock_timeout  60s;
    fastcgi_cache_use_stale     error timeout updating invalid_header;

    fastcgi_cache_bypass  $cookie_PHPSESSID;
    fastcgi_no_cache      $cookie_PHPSESSID;

    fastcgi_cache_key  $scheme$host$request_uri;

А затем подключим его в конфиге виртуального хоста.

Пример конфига хоста nginx

server {
    listen       80;
    server_name  example.com www.example.com;

    access_log   /var/www/data/example.com/log/nginx.access.log  main;
    error_log    /var/www/data/example.com/log/nginx.error.log;

    root         /var/www/data/example.com/data;

    error_page  404  /404/;

    location / {
        index  index.html index.php;
        try_files $uri $uri/ @hostcms;
    }

    # php скрипты отдаем в php-fpm, предварительно проверяя их существование
    location ~ .php$ {
        try_files $uri =404;

        fastcgi_pass   unix:/var/run/php5_example.com.sock;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
        include        /etc/nginx/conf.d/cache;
    }

    # все запросы, для которых не нашлось файлов, переадресуются на index.php
    location @hostcms {
        fastcgi_pass   unix:/var/run/php5_example.com.sock;
        fastcgi_param  SCRIPT_FILENAME  $document_root/index.php;
        include        fastcgi_params;
        include        /etc/nginx/conf.d/cache;
    }

Создание базы данных сайта

Сейчас почти всё готово, осталось только развернуть базу данных и создать пользователя, от имени которого будет осуществляться к ней подключение. Для этого нужно в консоли mysql выполнить несколько простых команд:

CREATE USER 'example_com'@'localhost' IDENTIFIED BY 'ВашСуперСтойкийПароль';
GRANT USAGE ON * . * TO 'example_com'@'localhost' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
CREATE DATABASE IF NOT EXISTS example_com_db DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
GRANT ALL PRIVILEGES ON example_com_db . * TO 'example_com'@'%';

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

use example_com_db;
source ПутьДоДампаБазыДанных;

Настройка резервного копирования и ротации логов

Если вы всё сделали правильно, то у вас уже должно быть полностью настроенное окружение для запуска вашего проекта. Остаются два последних по списку, но не по значимости, шага — настройка резервного копирования и ротации логов. В качестве инструмента для создания бэкапов я рекомендую использовать backup-manager. На хабре есть отличная статья [8] про него, поэтому подробно останавливаться на нём не будем.

Для осуществления ротации логов нам нужно всего лишь создать правильный конфиг для утилиты logrotate.

Например, такой

/var/www/data/example.com/log/nginx*.log {
    weekly
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 root root
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

/var/www/data/example.com/log/php*.log {
    weekly
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 root root
    postrotate
        invoke-rc.d php5-fpm reopen-logs > /dev/null
    endscript
}

Вместо заключения

Пожалуй, это всё, что я хотел сказать.
Возможно, кто-то сочтёт статью не слишком актуальной ввиду засилия панелей управления хостингом [3]. Хотя, на мой взгляд, они хороши для массового предоставления услуг и совершенно не годятся, когда речь заходит о затачивании настроек сервера под конкретный проект.
Другие посчитают её немного сумбурной. Не исключено, что это и так: в статье я только попытался отразить свой путанный опыт в области серверного администрирования.
В любом случае, буду рад, если этот материал поможет кому-то. Замечания и дополнения приветствуются.

Автор: vinogradov_m

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/mysql/71979

Ссылки в тексте:

[1] вредные советы: http://www.hostcms.ru/forums/17/5174/

[2] раздел документации: http://www.hostcms.ru/documentation/server/nginx/

[3] выделенный сервер: https://www.reg.ru/?rlink=reflink-717

[4] репозитория: http://nginx.org/ru/linux_packages.html#stable

[5] здесь: https://habrahabr.ru/post/108418/

[6] этой статье: https://habrahabr.ru/post/202348/

[7] здесь: https://habrahabr.ru/post/100961/

[8] отличная статья: https://habrahabr.ru/post/87435/

[9] Источник: http://habrahabr.ru/post/240725/