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

в 10:54, , рубрики: mysql, nginx, php-fpm, ubuntu server, Серверное администрирование

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

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

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

Первые шаги

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

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

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

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

nginx

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

# иногда происходит неведомая фигня с добавлением ключей непосредственно из 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-сервера можно здесь. Статья отлично написана, поэтому не вижу смысла дублировать сюда информацию.

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

В качестве протокола передачи файлов я предлагаю использовать 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, то описанную ниже процедуру придется повторить несколько раз. В этом случае имеет смысл попытаться автоматизировать процесс заведения нового хоста. Советую для этих целей обратить внимание на небольшой набор скриптов, описанных в этой статье, и «допилить» их под себя.

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

По соображениям безопасности все файлы, связанные с нашим сайтом будут принадлежать специально заведенному в системе пользователю. Подключение по 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. Перед тем, как отдавать на обработку скрипт нашему бэкэнду, проверяем его существование. Это позволить избежать проблемы, описанной здесь. Для того, чтобы снизить нагрузку на сайт от незарегистрированных пользователей, будем использовать кеширование на стороне 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. На хабре есть отличная статья про него, поэтому подробно останавливаться на нём не будем.

Для осуществления ротации логов нам нужно всего лишь создать правильный конфиг для утилиты 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
}

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

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

Автор: vinogradov_m

Источник

Поделиться

* - обязательные к заполнению поля