August 9, 2011

Есть ли жизнь без ISPmanager?

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

Недавно заметил что Apache стал потреблять до безобразия много виртуальной памяти: из 512 мегабайт RAM на VPS с установленным Debian 6 в режиме ожидания (т.е. простоя) Apache жрал 300 с чем-то. Согласитесь, это слишком. ISPmanager, конечно, меня более чем устраивала, но для её работы требуется тот самый Apache и я решил попробовать не сколько найти ей замену, а просто обойтись без панели управления. Потому как лучшая альтернатива ISPmanager, да и любой другой панели управления сервером — это никакой панели управления сервером, уж простите за каламбур.

Чтобы для создания/удаления сайтов (т.е. Virtualhost'ов в Nginx, баз данных MySQL, папок и т.д.) не приходилось лазить по серверу и править конфиги руками, написал небольшой скрипт добавления хостов, бд, об этом ниже. Но сначала установим связку Nginx + PHP-CGI.

Забегая наперед отмечу что установка с нуля Nginx, PHP-FastCGI, MySQL и phpMyAdmin по предложенной в этой статье схеме методом копировать-вставить заняла у меня не более семи минут. Безусловно, я слепо и не проверяя копировал в консоль команды из этой статьи т.к. сам же их писал и смыла самого себя опасаться нет. Но читателю я рекомендую изучать предлагаемые команды прежде чем использовать их.

И да, кстати. Вы, может, и знаете, но лишний раз отмечу: все команды ниже совсем необязательно вводить в консоль вручную, их можно копировать-вставлять. Их здесь много, а время надо экономить. Для того чтобы вставить текст в консоль (я использую клиент Putty) нужно просто нажать правой кнопкой мыши. Если в скопированном тексте захвачен символ переноса строки, то команда автоматически "вобьется", иначе нужно будет нажать клавишу Enter.

Часть 0. Приготовление

  1. Обновляем список пакетов:
    apt-get update
  2. Если при выполнении apt-get update вылетает GPG error — загружаем GPG ключи:
    apt-get install debian-archive-keyring
  3. Можем поубирать все необязательные/ненужные пакеты, в т.ч. Апач (см. следующую часть этой статьи).
  4. Пробуем обновиться:
    apt-get update && apt-get upgrade

Часть 1. Web-сервер

Берем чистую систему.
Открываем список всех установленных в системе пакетов:
dpkg --get-selections
Смотрим есть ли конфликтующие. Например, тот же Apache2:
dpkg --get-selections | grep apache
Автоматически сносим всё что похоже на пакет с заданным названием, в моем примере — "apache":
apt-get purge -y `dpkg --get-selections | grep apache | awk '{print $1}'`
Узнаем версию nginx:
apt-cache policy nginx
Переходим к установке:
  • В Debian 6 при помощи apt-get устанавливается nginx версии 0.7 (при том, что на момент написания статьи текущая версия nginx — 1.1.0). Если устраивает — приступаем, если же нет — смотрим следующий пункт. UPD: можно, конечно, включить testing-репозиторий где таки лежит новая версия, но это не всегда хорошее решение.
    apt-get update && apt-get install -y nginx php5-cgi
  • В Debian 5 лежит только 0.6. И если версия 0.7, которая в Debian 6, ещё терпима, то здесь придётся устанавливать из исходников. Зато в результате получим версию на 5 порядков выше!

    Но сначала — требуемые пакеты: libpcre3-dev для PRCE и zlib1g-dev для zlib[7] (а zlib, в свою очередь, нужна для работы gzip), иначе будут вываливаться ошибки:
    ./configure: error: the HTTP rewrite module requires the PCRE library
    ./configure: error: the HTTP gzip module requires the zlib library
    apt-get update && apt-get install -y gcc libpcre3-dev zlib1g-dev
    Теперь сам Engine X, он же nginx. Внимание! Если модуль gzip не нужен — используйте параметр --without-http_gzip_module.
    UPDATE Изменил версию на 1.0.8 — самая последния stable-версия на момент редактирования. Можно также поставить свежайшую development-версию (т.е. 1.1.5) — для этого просто замените номер в команде ниже.
    mkdir /root/nginx && cd /root/nginx && wget http://nginx.org/download/nginx-1.0.8.tar.gz && tar zxf nginx-1.0.8.tar.gz && cd nginx-1.0.8 && ./configure --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --pid-path=/var/log/nginx/nginx.pid --user=www-data --group=www-data && make && make install && rm -rf /root/nginx && cd ~
    Конфиг nginx, как правило, расположен в файле /etc/nginx/nginx.conf. Проверьте наличие в нём строчки
    include /etc/nginx/sites-enabled/*;
    Если её нет — добавьте. Она должна располагаться в конце директивы http {}. В итоге мой конфиг /etc/nginx/nginx.conf, например, выглядел так:
    worker_processes  1;
    pid /var/run/nginx.pid;
    events {
        worker_connections  1024;
    }
    http {
        include mime.types;
        default_type application/octet-stream;
        charset utf-8;
        sendfile on;
        keepalive_timeout 65;
        server {
            listen 80;
            server_name localhost;
            location / {
                root /var/www;
                index index.html index.htm;
            }
        }
        include /etc/nginx/sites-enabled/*;
    }
    Чтобы сохранить предложенный мной конфиг нужно сначала очистить существующий:
    cat /dev/null > /etc/nginx/nginx.conf
    Затем открыть его в редакторе и вставить предложенный вариант конфигурации:
    vi /etc/nginx/nginx.conf
    Когда файл откроется скопируйте конфиг из блока с кодом выше в буффер обмена, перейдите в режим INSERT (нажав соответствующую клавишу) и вставьте текст в консоль (нажав правой кнопкой), затем сохраните. Для сохранения файла в vi нужно нажать клавишу Escape (чтобы выйти из режима редактирования) и ввести :wq, где двоеточие — начало команд, w — write (записать), а q — quit (покинуть редактор) соответственно.

    В моём конфиге используется виректива charset со значением utf-8 — это добавляет charset=utf-8 к отправляемому nginx'ом заголовку Content-Type, в результате чего он принимает вид:
    Content-Type: text/html; charset=utf-8


    Старт-скрипт /etc/init.d/nginx можно взять отсюда: http://wiki.nginx.org/Nginx-init-ubuntu. Я же скопировал из ранее установленного nginx 0.6.
    Открываем файл в редакторе:
    vi /etc/init.d/nginx
    Прежде чем вставлять текст нажмите клавишу Insert.
    #! /bin/sh
    
    ### BEGIN INIT INFO
    # Provides:          nginx
    # Required-Start:    $all
    # Required-Stop:     $all
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: starts the nginx web server
    # Description:       starts nginx using start-stop-daemon
    ### END INIT INFO
    
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    DAEMON=/usr/local/nginx/sbin/nginx
    NAME=nginx
    DESC=nginx
    
    test -x $DAEMON || exit 0
    
    # Include nginx defaults if available
    if [ -f /etc/default/nginx ] ; then
        . /etc/default/nginx
    fi
    
    set -e
    
    case "$1" in
        start)
            echo -n "Starting $DESC: "
            start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
            --exec $DAEMON -- $DAEMON_OPTS || true
            echo "$NAME."
            ;;
        stop)
            echo -n "Stopping $DESC: "
            start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \
            --exec $DAEMON || true
            echo "$NAME."
            ;;
        restart|force-reload)
            echo -n "Restarting $DESC: "
            start-stop-daemon --stop --quiet --pidfile \
            /var/run/$NAME.pid --exec $DAEMON || true
            sleep 1
            start-stop-daemon --start --quiet --pidfile \
            /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true
            echo "$NAME."
            ;;
        reload)
            echo -n "Reloading $DESC configuration: "
            start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/$NAME.pid \
            --exec $DAEMON || true
            echo "$NAME."
            ;;
        *)
            N=/etc/init.d/$NAME
            echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
            exit 1
            ;;
    esac
    
    exit 0
    Внимание! В скрипте выше выделен путь к nginx. Узнать где он расположен у вас в системе можно следующим образом:
    whereis nginx
    Делаем его исполняемым и добавляем в автозапуск:
    chmod +x /etc/init.d/nginx && update-rc.d nginx defaults
Теперь fastcgi:
apt-get install -y php5-cgi
Nginx и PHP как FastCGI установлен. Никакого дополнительного ПО типа Lighttpd, вопреки рекомендациям многочисленных статей в "блогах сисадминов", я не ставил, заработало и без этого.
Создаем /etc/init.d/php-fastcgi. Откройте редактор vi:
vi /etc/init.d/php-fastcgi
И скопируйте следующий текст:
#!/bin/bash
BIND=127.0.0.1:9000
USER=www-data
PHP_FCGI_CHILDREN=4
PHP_FCGI_MAX_REQUESTS=4096

PHP_CGI=/usr/bin/php-cgi
PHP_CGI_NAME=`basename $PHP_CGI`
PHP_CGI_ARGS="- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND"
RETVAL=0

start() {
    echo -n "Starting PHP FastCGI: "
    start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS
    RETVAL=$?
    echo "$PHP_CGI_NAME."
}
stop() {
    echo -n "Stopping PHP FastCGI: "
    pkill $PHP_CGI_NAME
    RETVAL=$?
    echo "$PHP_CGI_NAME."
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo "Usage: php-fastcgi {start|stop|restart}"
        exit 1
        ;;
esac
exit $RETVAL
Делаем файл исполняемым и добавляем его в автозапуск:
chmod +x /etc/init.d/php-fastcgi && update-rc.d php-fastcgi defaults
Отключаем Magic Quotes (выставляем директиву magic_quotes_gpc в положение Off):
sed -i 's/magic_quotes_gpc = On/magic_quotes_gpc = Off/g' /etc/php5/cgi/php.ini
Теперь можем запустить PHP:
/etc/init.d/php-fastcgi start

Часть 2. База данных MySQL

Устанавливаем MySQL и соответствующий модуль для PHP.
Внимание! Если устанавливать MySQL через менеджер пакетов apt-get то будут также установлены зависимости, среди которых exim. Зачем базам данных нужен почтовый сервер — для меня загадка. Поэтому я ставлю через aptitude, позволяющий указать флаг --without-recommends [8]. Вариант с установкой через apt-get всё же приведу для справки.
  • Установка MySQL при помощи aptitude и без зависимостей:
    aptitude --without-recommends install -y mysql-server mysql-client php5-mysql
  • Установка MySQL при помощи apt-get и с зависимостями:
    apt-get install -y --force-yes mysql-server mysql-client php5-mysql
Приготовьтесь неоднократно нажимать Enter для принятия пустого пароля MySQL, или же введите его сразу.
Смотрим нагрузку и расход ресурсов процессора, RAM и т.д.:
top -d 1
Всё бы ничего, но mysqld стал жрать много памяти. Если вы не будете использовать таблицы отличные от MyISAM, отключите лишнее. Для этого надо раскомментировать строчку skip-innodb:
sed -i 's/#skip-innodb/skip-innodb/g' /etc/mysql/my.cnf && /etc/init.d/mysql restart
Эта строчка сбросила потребление MySQL'ом виртуальной памяти со ~150-ти до ~50-ти МБ т.е. в почти 3 раза!
P.S. интересная статья по оптимизации MySQL: http://www.databasejournal.com/features/mysql/article.php/3367871/Optimizing-the-mysqld-variables.htm. Датируется 2004-м годом. Трогательно читать как человек пишет, мол, "предыдущую статью по оптимизации MySQL я написал в 2001-м году, а это было три года назад...", а их-то, лет прошло, уже десять [5].

Создаем пароль для MySQL-root'а (если не сделали это на этапе регистрации — как раз самое время). Вместо 'hackme' введите свой пароль.
mysqladmin -u root password hackme

Часть 3. phpMyadmin

Нужна библиотека mcrypt:
apt-get install -y libmcrypt-dev php5-mcrypt
Установим phpMyadmin:
mkdir /root/pma && cd /root/pma && wget http://sourceforge.net/projects/phpmyadmin/files/phpMyAdmin/3.4.5/phpMyAdmin-3.4.5-all-languages.tar.gz && tar xzvf phpMyAdmin-3.4.5-all-languages.tar.gz && mkdir /usr/share/phpmyadmin && mv /root/pma/phpMyAdmin-3.4.5-all-languages/* /usr/share/phpmyadmin && cd ~ && rm -rf /root/pma
Настроим nginx для работы с phpMyadmin. Сделать это на IP-адресе у меня не полчилось, поэтому придётся задействовать домен. Создадим файл /etc/nginx/sites-enabled/phpmyadmin:
mkdir /etc/nginx/sites-enabled && vi /etc/nginx/sites-enabled/phpmyadmin
Скопируйте в него:
server {
    server_name phpmyadmin.example.com;
    access_log /var/log/nginx/phpmyadmin.example.com.access.log;
    error_log /var/log/nginx/phpmyadmin.example.com.error.log;
    root /usr/share/phpmyadmin;
    include /etc/nginx/common_params;
}
Не забывайте перед вставкой текста переводить редактор vi в режим Insert! иначе часть текста будет потеряна.
Файл common_params будет создан автоматически позже.
Отключим AJAX-окна в phpMyAdmin. Для этого добавьте параметр $cfg['AjaxEnable'] = false; в конфигурационный файл config.inc.php:
echo "<?php \$cfg['AjaxEnable'] = false; ?>">/usr/share/phpmyadmin/config.inc.php
Обратите внимание что обратный слеш в команде выше нужен для ее корректной обработки консолью Linux.

Часть 4. Добавление сайтов, баз данных

Создайте файл /root/random_string.sh: для этого откройте редактор vi...
vi /root/random_string.sh
... и скопируйте в него следующий текст:
#!/bin/bash
if [ $1=="-l" ]
    then
        length=$2
    else
        length="8"
    fi
echo `cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w $length | head -1`
Сохраните файл (клавиша Escape -> :wq ).
Этот скрипт понадобится для генерации случайных паролей в shell.
Делаем его исполняемым:
chmod +x /root/random_string.sh

Автоматизируем создание виртуалхостов (т.е. сайтов) в nginx'е, баз данных и директорий для каждого сайта. Пароли и пользователи генерируются случайные, и записываются в файл config.php, расположенный в корне свежесозданного домена. Скрипт спрашивает добавлять ли псевдонимы (алиасы) домена, как назвать папку, в которой будет лежать добавляемый сайт, где разместить эту папку, как назвать базу данных MySQL для сайта, и как назвать добавляемого к ней пользователя. В квадратных скобках пишутся значения, которые будут использованы если вы ничего не введете а просто нажмете Enter.
Создаем файл /root/add_host.sh. Скачать его можно отсюда: add_host.sh. Файл сравнительно большой, поэтому забирать будем wget'ом:
wget -N http://dl.dropbox.com/u/45515900/Shell_Scripts/add_host.sh
Делаем add_host.sh исполняемым:
chmod +x /root/add_host.sh

Добавляем постоянный (permanent) alias (т.е. чтобы можно было запускать одной командой):
echo 'alias addhost="sh /root/add_host.sh"'>>~/.bashrc


Всё, теперь создайте хотя бы один хост чтобы скрипт создал файл /etc/nginx/common_params и nginx запустился.

Использование скрипта:
  • добавление сайта:
    addhost example.com
  • удаление сайта:
    addhost -r example.com

Перезапустим PHP чтобы задействовались новые модули:
/etc/init.d/php-fastcgi restart

Все проверено на Debian 5 Lenny. Вот как выглядит работающий под nginx'ом phpmyadmin:


Если для работы свежесозданного сайта нужно импортировать дамп таблиц из SQL-файла в базу MySQL, то воспользуйтесь phpMyAdmin (см. статью «Загрузить большой дамп БД MySQL в PhpMyAdmin») или зайдите в консоль mysql:
mysql -u root -phackme

Пробел между параметром -p и самим паролем не ставится.
Выберите базу данных в которую нужно загрузить файл .sql:
use %database_name%;

(где %database_name% — название БД в которую производится загрузка файла).
И осуществите импорт:
source /path/to/dump.sql

(где /path/to/dump.sql — путь к .sql-файлу).

Вы также можете создать отдельного пользователя для работы с сайтами по SFTP:
useradd -d /var/www -p `openssl passwd -crypt passsword` -U admin

(где passsword — пароль для создаваемого пользователя, а admin — его имя/логин; параметр -d задает его домашнюю директорию, -p шифрует заданный пароль с помощью openssl, а -U автоматически создает для пользователя одноименную группу, куда сразу же его добавляет).

Безусловно, на полноценную замену ISPmanager, да и любой другой панели управления сервером это не тянет. Нужно доработать бэкапы, FTP-пользователей и т.д. Но для начала предложенного скрипта может вполне хватить.

Источники:
  1. http://tomasz.sterna.tv/2009/04/php-fastcgi-with-nginx-on-ubuntu/
  2. https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/
  3. http://www.chaugule.in/linux/shell-script-adding-virtual-hosts-ubuntu-apache/
  4. http://habrahabr.ru/blogs/sysadm/113101/
  5. http://www.databasejournal.com/features/mysql/article.php/3367871/Optimizing-the-mysqld-variables.htm
  6. http://bash.cyberciti.biz/backup/backup-mysql-database-server-2/
  7. http://www.linuxquestions.org/questions/debian-26/compile-php-with-zlib-on-debian-lenny-debian-5-0-a-828200/#post4076297
  8. http://citkit.ru/articles/838/

P.S. я не профессионал в написании shell-скриптов, более того — это моя первая "серьезная" проба. Поэтому если у вас есть пожелания/советы по отптимизации предложенного кода, пишите в комментарии. Спасибо.

2 comments:

Anonymous said...

Панель SimpleHM- vds64.com/simplehm почти не жрет ресурсы и нормально все работает даже на 256 озу.
Сам раньше с шызменеджером мучался, щас перешел на симпл вообще нет никаких проблем.

altaynews said...

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

А за статью спасибо автору! Как раз потребовалось развернуть сервер без ИСПманаджер.