Руководство по настройке Linux Web сервера
|
|
Предисловие[править]
Итак, я решил обобщить свой опыт по развёртыванию веб-сервера на основе Linux, который мог бы работать в сети I2P. В принципе ничего необыкновенного или сверхъестественного, но задокументировать смысл имеет. В принципе данный набор позволяет серверу выносить весьма серьёзные нагрузки. Ресурсоёмкость описанной системы - 200-220 Mb в оперативной памяти, без использования swap. На планке оперативки в 512 Мб (которая стоит в сервере сейчас) остаётся ещё очень неплохой запас по ресурсам (в отличие от Windows 2003, которая кушала файл подкачки неимоверно, и неимоверно же тормозила).
Часть руководства почерпнута отсюда, часть является специфичной для I2P.
Подготовка[править]
Описываемый сервер развёрнут на следующей платформе:
- ОС: Linux, Debian 6 (однако часть примеров команд в консоли приведена для старой платформы - CentOS с менеджером пакетов Yum. Не было времени поправить)
- Веб-сервер: nginx
1.0.01.0.5 - MySQL: 5+,
- PHP в режиме FastCGI. Посредников и иных backend'ов типа Apache - нет. Дополнительно установлен XCache с кэшированием и оптимизацией в память.
- I2P Router 0.9.3
- Аппаратная часть всё та же: 512 ОЗУ, 2,4 ГГц проц Pentium, HDD 160 Gb.
Для начала, собственно, требуется установить CentOS (подойдет любой дистрибутив, на самом деле). На чисто серверной машине графический интерфейс не нужен, потому по умолчанию пакеты типа KDE || Gnome не ставим. Плюс вообще можно систему облегчить, пробежавшись по списку пакетов при установке. Очень рекомендую создать дополнительную файловую систему и монтировать её как /www - в ней мы будем хранить все ресурсы веб.
Настройка сервера[править]
Установка и настройка Nginx[править]
Есть куча любителей поставить софт на сервер/рабочую машинку из исходников. Хозяин барин, конечно, но я этого делать не рекомендую. Во-первых, усложняется обновление софта. Каждый раз придётся ручками пересобирать всё. В случае с установкой из репозитория - всё проще: yum update. Но с другой стороны, если вам нужны какие-то специфические модули nginx, или иные особенности конфигурирования, то всё равно придётся собирать.
Для того, чтобы установить nginx так, надо добавить репозиторий CentALT. Сделать это можно выполнив команду с правами root:
Для 32-разрядных систем: Шаблон:LinuxConsole
Для 64-разрядных систем:
Если команда yum search nginx после этого ничего не нашла, то надо проверить файл в директории /etc/yum.repos.d/ с именем centalt.repo:
Если его там нет - надо создать: Шаблон:LinuxConsole
И добавить туда строки:
[CentALT] name=CentALT Packages for Enterprise Linux 5 - $basearch baseurl=http://centos.alt.ru/repository/centos/5/$basearch/ enabled=1 gpgcheck=0
(кто не знает как работать в vim, сначала надо нажать клавишу i, чтобы войти в режим редактирования. Когда вы внесли изменения - Esc, а затем последовательно наберите :w! Enter, :q! Enter) Но первый способ весьма предпочитительнее - если он не сработал, значит что-то не так.
Всё. устанавливайте nginx:
Настроим автозапуск:
Управление Nginx производится путём подачи сигналов типа:
Конфигурирование виртуальных хостов и реврайтов[править]
Конфиг внизу - устарел. Новая версия вики с ним уже не работает, так как там появился злобный ResourceLoader. Речь идёт только о движке MediaWiki - в общем случае данный конфиг работает.
Чтобы долго не описывать сам процесс, приведу пример конфига этой вики. Как правило конфиг виртуальных хостов лежит в /etc/nginx/conf.d/virtual.conf Кстати, почитать по поводу конфига nginx можно, например, тут.
По образу и подобию можно создавать произвольное количество виртуальных хостов для ваших проектов. Кстати - {PATH_TO_YOU_WWW_DIR} - надо заменить на реальный путь к директории, где находится корневой каталог вашего приложения.
################################################################################################ ## Тащемта, Rus.I2P сайт. ################################################################################################ server { listen 80; #listen rus.i2p:80; server_name rus.i2p alias www.rus.i2p; charset utf-8; # Сжимать передаваемые данные gzip on; # Задайте уровень сжатия от 1 до 9 # Т.к. посетителей очень ма-а-а-ало, # а сеть очень ме-е-е-едленная, лучше 9 gzip_comp_level 9; location / { root {PATH_TO_YOU_WWW_DIR}/rusi2p/htdocs; index index.html index.php; rewrite ^/wiki/([^?]*)(?:\?(.*))? /wiki/index.php?title=$1&$2; allow 127.0.0.1; # Разрешаем коннект только с локалхоста. deny all; } location /skins { root {PATH_TO_YOU_WWW_DIR}/rusi2p/htdocs; } location /images { root {PATH_TO_YOU_WWW_DIR}/rusi2p/htdocs; } error_page 404 /404.html; location = /404.html { root {PATH_TO_YOU_WWW_DIR}/rusi2p/htdocs; } # Настройки для связки с PHP-FastCGI location ~ \.php$ { root {PATH_TO_YOU_WWW_DIR}/rusi2p/htdocs; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME {PATH_TO_YOU_WWW_DIR}/rusi2p/htdocs/index.php$fastcgi_script_name; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one location ~ /\.ht { deny all; } } ##============================================================================================== ## / END OF Rus.I2P ##==============================================================================================
В целом, если вам не хочется отказываться от любимого Apache, можно настраивать и на основе него, никаких проблем (если только не дорожите каждым мегабайтом оперативки, но то уже случай тяжёлый и требующий индивидуального подхода) - разницы во "фронте" никакой не будет. Вряд ли на вашем сервере будет такая нагрузка, что Apache с ней не справится (скорее загнётся i2p роутер, что, впрочем, тоже вряд ли). Тем более, что конфигурирование Apache + PHP Module - ощутимо более просто и распространённо.
Установка и настройка MySQL[править]
Собственно, нет ничего проще:
Единственное, потом надо задать рутовый пароль, естественно, и создать требуемые базы. Кроме того, никто не мешает вам выбрать другую БД, например PostgreSQL или Oracle - при этом не надо ложного снобизма. PostgreSQL|Oracle имеет смысл использовать тогда, когда вы планируете задействовать его мощнейший встроенный язык хранимых процедур - PL/SQL. Если нет, и вы просто планируете хранить там данные - да используйте MySQL - он обеспечивает с лихвой все обычные потребности среднего веб-проекта.
Установка и настройка PHP - FastCGI + XCache[править]
Для начала требуется поставить сам PHP с модулями. В список модулей добавляем всё то, что вам нужно. Данный пример невозбранно содран из интернетов (с http://www.itpad.ru/?p=1960). По нему и rus.i2p настраивался. Какие именно модули там ставились точно я не помню, да это и не важно.
В него добавим следующее:
#!/bin/sh . /etc/rc.d/init.d/functions . /etc/sysconfig/network [ "$NETWORKING" = "no" ] && exit 0 spawnfcgi="/usr/bin/spawn-fcgi" php_cgi="/usr/bin/php-cgi" prog=$(basename $php_cgi) server_ip=127.0.0.1 server_port=9000 server_user=nginx server_group=nginx server_childs=5 pidfile="/var/run/php_cgi.pid" [ -f /etc/sysconfig/phpfastcgi ] && . /etc/sysconfig/phpfastcgi start() { [ -x $php_cgi ] || exit 1 [ -x $spawnfcgi ] || exit 2 echo -n $"Starting $prog: " daemon $spawnfcgi -a ${server_ip} -p ${server_port} -u ${server_user} -g ${server_group} -P ${pidfile} -C ${server_childs} -f ${php_cgi} retval=$? echo return $retval } stop() { echo -n $"Stopping $prog: " killproc -p ${pidfile} $prog -QUIT retval=$? echo [ -f ${pidfile} ] && /bin/rm -f ${pidfile} return $retval } restart(){ stop sleep 2 start } rh_status(){ status -p ${pidfile} $prog } case "$1" in start) start;; stop) stop;; restart) restart;; status) rh_status;; *) echo $"Usage: $0 {start|stop|restart|status}" exit 3 esac
Затем, добавляем скрипту право на запуск и добавляем в автозагрузку
Собственно, если вы внимательно посмотрите выше на конфиг nginx-а, то увидите, где в настройке сервера указывается, что работать надо с php-FastCGI.
XCache[править]
Тащемта, просто неиллюзорно:
И устанавливаем следующие настройки (или отредактируйте по желанию, с условием понимания, что вы делаете):
[xcache-common] zend_extension = /usr/lib/php/modules/xcache.so [xcache.admin] xcache.admin.auth = On xcache.admin.user = "admin" ; xcache.admin.pass should be md5($your_password), or empty to disable administration. xcache.admin.pass = "<md5_password_hash>" xcache.test = Off ;xcache.coredump_directory = "" [xcache] xcache.cacher = On xcache.size = 100M xcache.count = 1 xcache.slots = 8K xcache.ttl = 3600 xcache.gc_interval = 300 ; Same as aboves but for variable cache ; If you don't know for sure that you need this, you probably don't xcache.var_size = 4M xcache.var_count = 1 xcache.var_slots = 8K xcache.var_ttl = 3600 xcache.var_maxttl = 3600 xcache.var_gc_interval = 300 ; N/A for /dev/zero xcache.readonly_protection = Off ; Use something like "/tmp/xcache" if you want to turn on ReadonlyProtection ; 2 group of php won't share the same /tmp/xcache xcache.mmap_path = "/dev/zero" xcache.optimizer = On xcache.coverager = Off ;xcache.coveragedump_directory = "/tmp/pcov"
После чего перезапускаем php (не nginx!):)
Вообще, имеет смысл сделать какой-нить файл типа phpinfo.php и в нём смотреть - подцепились ли дополнения, или не подцепились.
Установка и настройка I2P роутера[править]
Для начала надо установить java. В принципе у меня работает и на openjdk 1.6.0_20. Но если у вас не так - поставьте Java от Sun. Чтобы не трахаться с поиском, установкой и настройкой - проверьте сначала, может у вас оно есть? Выполните в консоли следующую команду. Если у вас отобразится то же самое, что у меня или близкое к тому - забиваем большой и толстый и идём ставить I2P.
Ставится это тоже просто, например около так (выберите пакет, например -devel пакет не обязателен, можно простой установить):
А потом выкачиваем и ставим, тащемта, I2P роутер, например:
Далее следуйте инструкциям ФСБ инсталлятора.
Как правило I2P ставится в директорию /usr/local/i2p - насколько я помню, её можно указать при установке. В принципе не так важно куда ставить, она сможет работать нормально и если вы её установите в домашнюю папку пользователя i2p: /home/i2p, суть не в этом, а в том, что в этой директории лежит скрипт i2prouter - им производится управление службой i2p. Работает примерно так: /usr/local/i2p/i2prouter start|stop|restart - обычный shell-файл. Его можно добавить в автозагрузку. Самый простой (но и самый неправильный) способ - это добавить команду в конец файла /etc/rc.local
# I2P Service start sleep 20 /usr/local/i2p/i2prouter start
В этом случае роутер будет загружаться от root с запаздыванием на 20 секунд после остальных служб. Это было необходимо в моём случае, так как иначе сервис запускался с ошибками, или не запускался вовсе. Но как утверждают анонимусы - это плохая практика, кошернее запускать от специально созданного пользователя I2P. Если у вас есть оттестированный и рабочий пример того, как надо - пожалуйста, добавьте ниже.
В принципе должен работать вариант такой команды:
Но я лично не проверял. Если работает - гут.
Удалённый доступ к I2P консоли через SSH[править]
Собственно, зависит от того, какая у вас машина. На Linux работает команда
Где, соответственно, <USER_NAME> - учётка на том сервере куда стучитесь, а <HOST_IP> - айпишник/DNS имя сервера. В результате на локальной машине вы сможете просто подключиться в браузере к http://localhost:7657 и получить там удалённую консоль, как будто она у вас на локальной машине.
В Windows, как обычно, сложнее. Для начала, надо скачать программку plink.exe и куда-нибудь её поместить, после чего в командной строке набрать:
результат получится аналогичным. Кстати подобные тоннели - весьма полезная вещь, например в качестве прокси на работе, где злые админы заблокировали всякие кошерные сайты. Правда они могли заблокировать и 22-й порт, но то уже другая песня...
Портирование / создание тоннелей[править]
Тащемта, есть две разницы, если у вас уже был какой-то сайт/домен в I2P (и, соответственно, приватные ключи к нему) или не было. Если не было - то имеет смысл посмотреть эту статью. Там создание тоннелей с нуля даже в картинках.
В принципе - портирование тоннелей из старого сервера / окружения на новый - очень похоже. Для начала надо скопировать приватные ключи - те, которые сопоставлены вашим доменам. А дальше шаги примерно аналогичны, просто в качестве приватного ключа указываете имя файла, содержащего приватный ключ от домена, например i2ptunnel6-privKeys.dat - сразу же, при создании тоннеля. Тогда он автоматически подцепит ключ, и будет перенаправлять тоннель на ваш виртуальный хост.
Настройка резервного копирования[править]
В принципе, если есть время, знания и желание, а главное, насущная необходимость - лучше использовать нечто специализированное, наподобие Bacula. Но для небольшого проекта - до 10 сайтов и базы размером до 1 Гб, вполне пойдёт автоматизация путём какого-либо скрипта. Что он должен делать?
- Копировать во временную папку необходимые файлы.
- Создавать в той же временной папке дамп mysql
- Сжимать всё это в архив, и помещать его в хранилище (на другом физическом диске - предпочтительнее)
- Удалять временные файлы
- Осуществлять сборку мусора (устаревших копий)
Естественно, это всё будет запускаться по cron.
Для начала, нам потребуется архиватор, скачиваем, ставим:
А затем делаем где-нибудь, скажем в /usr/scripts (создайте) файлик следующего содержимого (часть его пока корявая, потом поправлю, как допишу и испытаю - а именно в области удаления устаревших копий):
<?php /** * Тащемта, файл обеспечивает автоматизированное резервное копирование данных хостов, * базы данных, конфиги, и так далее. * * Суть работы - упаковка всего и вся, по путям прописанным в настройках, в единый архив, и помещение его * в резервное хранилище на другом физическом разделе. При этом производится нумерация файлов по * датам, и удаление файлов, устаревших на N дней. * * @data 25.07.2011 * @author Alex * * */ /** * Папки, которые необходимо зарезервировать * @var array */ $reservPaths = array( '/root/.i2p', '/www', '/usr/local/i2p', '/etc/nginx', '/etc/php.d', '/etc/php.ini', //'', ); /** * Где будем хранить бэкапы * @var integer */ $backupPath = '/backups/web'; /** * Указываем время хранения бэкапа * @var integer */ $backupTTL = 7; /** * Путь к логам * @var string */ $logPath = '/var/log/web_backup.log'; $log = null; if (!file_exists($logPath)) { $log = fopen($logPath, 'w'); } else { $log = fopen($logPath, 'a+'); } fwrite($log, "--- START ".date('d.m.Y H:i:s')." ---\n\n"); // Делаем временные папки $tmp = '/tmp/' . strtoupper( substr( md5( mt_rand() ), 0, 6 ) ); mkdir($tmp, 0777); mkdir($tmp . '/DB', 0777); foreach ($reservPaths as $v) { $fix_name = str_replace(array('/', '\\'), '_', $v); if (!is_file($v) && is_dir($v)) { mkdir($tmp.'/'.$fix_name, 0777); system("cp {$v}/* {$tmp}/{$fix_name}/ -R -f"); } else { system("cp {$v} {$tmp}/{$fix_name} -f"); } } // Сохраняем БД system("mysqldump --all-databases --user 'root' --password='YOU_MYSQL_PASSWORD' --hex-blob > {$tmp}/DB/sqldump"); // Упаковываем, должен стоять пакет p7zip (yum search!) $date = date('dmY_His'); system("7za a -t7z -m0=lzma '{$backupPath}/{$date}_dump.7z' {$tmp}/* "); if (file_exists($backupPath.'/'.$date.'_dump.7z')) { system("rm -rf {$tmp}"); } fwrite($log, date('d.m.Y H:i:s')." > Резервирование окончено, резервная копия в {$backupPath}/{$date}_dump.7z\n"); // Garbage Collector. $dir = scandir($backupPath); if (0 < count($dir)) { $time = time(); $interval = strtotime( "-{$backupTTL} days" ); foreach ($dir as $v) { if (('.' != $v) && ('..' != $v)) { $cDate = lstat($backupPath.'/'.$v); // Если не работает, то ctime меняем на числовой индекс 10 // Это потребуется если PHP ниже версии 4.0.6 if ($interval > $cDate['ctime']) { unlink($backupPath.'/'.$v); fwrite($log, date('d.m.Y H:i:s')." > Файл {$backupPath}'/'{$v} устарел и удалён. \n"); } } } } fwrite($log, "--- END ".date('d.m.Y H:i:s')." ---"); fclose($log);
Итак, предположим, что у вас скрипт лежит по пути /var/scripts/backup.php - естественно пользователь, от которого вы будете запускать его на выполнение, должен иметь права соответствующие на файл. Для пробы можете запустить его прямо из командной строки, чтобы проверить - корректно ли он работает.
Если он ругается на права - необходимо разрешить проблему до того, как вы поместите его в crontab на выполнение. В случае удачного исполнения, в папке с вашими бэкапами создастся файл архива (типа backups/10122011_010300_back.7z).
Теперь следующее. В /etc/ есть директории cron.daily, cron.weekly и т. д.Права на запись в них имеет пользователь root, если у вас есть эти права, то всё ок (а я исхожу из того, что на сервере у вас есть root права). Сделаем:
В открывшемся редакторе введём:
#!/bin/sh /usr/bin/php /usr/scripts/backup.php
Ну и собственно всё. Теперь ваш скрипт будет запускаться по cron раз в сутки, и сваливать результаты своей деятельности в директорию бэкапов. Устаревшие бэкапы будут удаляться (срок хранения задаётся в скрипте). Автор, собственно, очень удивился тому, что скрипт вышел довольно переносимым. Т.е. имея окружение, описанное в требованиях, вы можете перезаписать некоторые параметры и он будет работать. Выяснилось это при переносе rus.i2p на новое железо в начале 2012-го. Ожидались проблемы, однако таковых не последовало - скрипт исправно отрабатывает свою функцию.