Руководство по настройке Linux Web сервера
Итак, я решил обобщить свой опыт по развёртыванию веб-сервера на основе Linux, который мог бы работать в сети I2P. В принципе ничего необыкновенного или сверхъестественного, но задокументировать смысл имеет. В принципе данный набор позволяет серверу выносить весьма серьёзные нагрузки. Ресурсоёмкость описанной системы — 200—220 Mb в оперативной памяти, без использования swap. На планке оперативки в 512 Мб (которая стоит в сервере сейчас) остаётся ещё очень неплохой запас по ресурсам (в отличие от Windows 2003, которая кушала файл подкачки неимоверно, и неимоверно же тормозила).
Часть руководства почерпнута отсюда, часть является специфичной для I2P.
Содержание |
[править] Подготовка
Описываемый сервер развёрнут на следующей платформе:
- ОС: Linux, CentOS 5.6
- Веб-сервер: nginx
1.0.01.0.5 - MySQL: 5+,
- PHP в режиме FastCGI. Посредников и иных backend’ов типа Apache — нет. Дополнительно установлен XCache с кэшированием и оптимизацией в память.
- I2P Router 0.8.5
- Аппаратная часть всё та же: 512 ОЗУ, 2,4 ГГц проц Pentium, HDD 160 Gb.
Для начала, собственно, требуется установить CentOS. На чисто серверной машине графический интерфейс не нужен, потому по умолчанию пакеты типа KDE || Gnome не ставим. Плюс вообще можно систему облегчить, пробежавшись по списку пакетов при установке. Очень рекомендую создать дополнительную файловую систему и монтировать её как /www — в ней мы будем хранить все ресурсы веб.
[править] Настройка сервера
[править] Установка и настройка Nginx
Есть куча любителей поставить софт на сервер/рабочую машинку из исходников. Хозяин барин, конечно, но я этого делать не рекомендую. Во-первых, усложняется обновление софта. Каждый раз придётся ручками пересобирать всё. В случае с установкой из репозитория — всё проще: yum update.
Для того, чтобы установить nginx так, надо добавить репозиторий CentALT. Сделать это можно выполнив команду с правами root:
Для 32-разрядных систем:
rpm -ihv http://centos.alt.ru/repository/centos/5/i386/centalt-release-5-6.noarch.rpm
Для 64-разрядных систем:
rpm -ihv http://centos.alt.ru/repository/centos/5/x86_64/centalt-release-5-6.noarch.rpm
Если команда yum search nginx после этого ничего не нашла, то надо проверить файл в директории /etc/yum.repos.d/ с именем centalt.repo:
[root@host]# ls -la /etc/yum.repos.d
Если его там нет — надо создать:
[root@host]# vim /etc/yum.repos.d/centalt.repo
И добавить туда строки:
[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:
[root@host]# yum install nginx
Настроим автозапуск:
chkconfig –level 35 nginx on
Управление Nginx производится путём подачи сигналов типа:
[root@host]# service nginx start // Старт сервера [root@host]# service nginx stop // Стоп [root@host]# service nginx restart // перезапуск
[править] Конфигурирование виртуальных хостов и реврайтов
Конфиг внизу — устарел. Новая версия вики с ним уже не работает, так как там появился злобный 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; 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
Собственно, нет ничего проще:
[root@host]# yum install mysql mysql-server mysql-devel [root@host]# chkconfig –level 35 mysqld on
Единственное, потом надо задать рутовый пароль, естественно, и создать требуемые базы. Кроме того, никто не мешает вам выбрать другую БД, например PostgreSQL или Oracle — при этом не надо ложного снобизма. PostgreSQL|Oracle имеет смысл использовать тогда, когда вы планируете задействовать его мощнейший встроенный язык хранимых процедур — PL/SQL. Если нет, и вы просто планируете хранить там данные — да используйте MySQL — он обеспечивает с лихвой все обычные потребности среднего веб-проекта.
[править] Установка и настройка PHP — FastCGI + XCache
Для начала требуется поставить сам PHP с модулями. В список модулей добавляем всё то, что вам нужно. Данный пример невозбранно содран из интернетов (с http://www.itpad.ru/?p=1960). По нему и rus.i2p настраивался. Какие именно модули там ставились точно я не помню, да это и не важно.
[root@host]# yum install php php-pear php-common php-gd php-devel php-mbstring php-pear-Mail php-cli php-imap php-snmp php-pdo php-xml php-ldap php-pear-Net-SMTP php-mysql [root@host]# yum install spawn-fcgi
Затем в /etc/init.d/ создаём стартовый скрипт модуля:
[root@host]# vim /etc/init.d/php_cgi
В него добавим следующее:
#!/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
Затем, добавляем скрипту право на запуск и добавляем в автозагрузку
[root@host]# chmod a+x /etc/init.d/php_cgi [root@host]# chkconfig –level 35 php_cgi on
Запускаем. В норме должен подняться php-fastCGI сервис.
[root@host]# service php_cgi start
Проверим, работает ли:
[root@host ~]# netstat -tlnp | grep :9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 2590/php-cgi
Собственно, если вы внимательно посмотрите выше на конфиг nginx-а, то увидите, где в настройке сервера указывается, что работать надо с php-FastCGI.
[править] XCache
Тащемта, просто неиллюзорно:
[root@host]# yum install php-xcache
Затем, правим (или создаём, если не существует) файл в директории /etc/php.d/:
[root@host]# vim /etc/php.d/xcache.ini
И устанавливаем следующие настройки (или отредактируйте по желанию, с условием понимания, что вы делаете):
[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!) :)
[root@host]# /etc/init.d/php_cgi restart
Вообще, имеет смысл сделать какой-нить файл типа phpinfo.php и в нём смотреть — подцепились ли дополнения, или не подцепились.
[править] Установка и настройка I2P роутера
Для начала надо установить java. В принципе у меня работает и на openjdk 1.6.0_20. Но если у вас не так — поставьте Java от Sun. Чтобы не трахаться с поиском, установкой и настройкой — проверьте сначала, может у вас оно есть? Выполните в консоли следующую команду. Если у вас отобразится то же самое, что у меня или близкое к тому — забиваем большой и толстый и идём ставить I2P.
[root@host ~]# java -version java version "1.6.0_20" OpenJDK Runtime Environment (IcedTea6 1.9.8) (rhel-1.22.1.9.8.el5_6-i386) OpenJDK Client VM (build 19.0-b09, mixed mode)
Ставится это тоже просто, например около так (выберите пакет, например -devel пакет не обязателен, можно простой установить):
[root@localhost ~]# yum search openjdk Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirror.corbina.net * epel: mirror.xfes.ru * extras: mirror.corbina.net * ius: ftp.rediris.es * updates: mirror.corbina.net ====================================== Matched: openjdk ======================================= java-1.6.0-openjdk.i386 : OpenJDK Runtime Environment java-1.6.0-openjdk-demo.i386 : OpenJDK Demos java-1.6.0-openjdk-devel.i386 : OpenJDK Development Environment java-1.6.0-openjdk-javadoc.i386 : OpenJDK API Documentation java-1.6.0-openjdk-src.i386 : OpenJDK Source Bundle [root@localhost ~]# yum install java-1.6.0-openjdk-devel.i386
А потом выкачиваем и ставим, тащемта, I2P роутер, например:
[root@host]# wget http://mirror.i2p2.de/i2pinstall_0.8.7.exe [root@host]# java -jar ./i2pinstall_0.8.7.exe -console
Далее следуйте инструкциям ФСБ инсталлятора.
Как правило 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. Если у вас есть оттестированный и рабочий пример того, как надо — пожалуйста, добавьте ниже.
В принципе должен работать вариант такой команды:
[root@host]# chkconfig -–level 35 /usr/local/i2p/i2prouter on
Но я лично не проверял. Если работает — гут.
[править] Удалённый доступ к I2P консоли через SSH
Собственно, зависит от того, какая у вас машина. На Linux работает команда
ssh -L 7657:localhost:7657 <USER_NAME>@<HOST_IP>
Где, соответственно, <USER_NAME> — учётка на том сервере куда стучитесь, а <HOST_IP> — айпишник/DNS имя сервера. В результате на локальной машине вы сможете просто подключиться в браузере к http://localhost:7657 и получить там удалённую консоль, как будто она у вас на локальной машине.
В Windows, как обычно, сложнее. Для начала, надо скачать программку plink.exe и куда-нибудь её поместить, после чего в командной строке набрать:
<путь к plink>\plink.exe -L 7657:localhost:7657 <USER_NAME>@<HOST_IP>
результат получится аналогичным. Кстати подобные тоннели — весьма полезная вещь, например в качестве прокси на работе, где злые админы заблокировали всякие кошерные сайты. Правда они могли заблокировать и 22-й порт, но то уже другая песня…
[править] Портирование и создание тоннелей
Тащемта, есть две разницы, если у вас уже был какой-то сайт/домен в I2P (и, соответственно, приватные ключи к нему) или не было. Если не было — то имеет смысл посмотреть эту статью. Там создание тоннелей с нуля даже в картинках.
В принципе — портирование тоннелей из старого сервера / окружения на новый — очень похоже. Для начала надо скопировать приватные ключи — те, которые сопоставлены вашим доменам. А дальше шаги примерно аналогичны, просто в качестве приватного ключа указываете имя файла, содержащего приватный ключ от домена, например i2ptunnel6-privKeys.dat — сразу же, при создании тоннеля. Тогда он автоматически подцепит ключ, и будет перенаправлять тоннель на ваш виртуальный хост.[править] Настройка резервного копирования
В принципе, если есть время, знания и желание, а главное, насущная необходимость — лучше использовать нечто специализированное, наподобие Bacula. Но для небольшого проекта — до 10 сайтов и базы размером до 1 Гб, вполне пойдёт автоматизация путём какого-либо скрипта. Что он должен делать?
- Копировать во временную папку необходимые файлы.
- Создавать в той же временной папке дамп mysql
- Сжимать всё это в архив, и помещать его в хранилище (на другом физическом диске — предпочтительнее)
- Удалять временные файлы
- Осуществлять сборку мусора (устаревших копий)
Естественно, это всё будет запускаться по cron.
Для начала, нам потребуется архиватор, скачиваем, ставим:
yum install p7zip
А затем делаем где-нибудь, скажем в /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 — естественно пользователь, от которого вы будете запускать его на выполнение, должен иметь права соответствующие на файл. Для пробы можете запустить его прямо из командной строки, чтобы проверить — корректно ли он работает.
# php /var/scripts/backup.php
Если он ругается на права — необходимо разрешить проблему до того, как вы поместите его в crontab на выполнение. В случае удачного исполнения, в папке с вашими бэкапами создастся файл архива (типа backups/10122011_010300_back.7z).
Теперь следующее. В /etc/ есть директории cron.daily, cron.weekly и т. д. Права на запись в них имеет пользователь root, если у вас есть эти права, то всё ок (а я исхожу из того, что на сервере у вас есть root права). Сделаем:
# touch /etc/cron.daily/backup.sh # chmod a+x /etc/cron.daily/backup.sh # vim /etc/cron.daily/backup.sh
В открывшемся редакторе введём:
#!/bin/sh /usr/bin/php /usr/scripts/backup.php
Ну и собственно всё. Теперь ваш скрипт будет запускаться по cron раз в сутки, и сваливать результаты своей деятельности в директорию бэкапов. Устаревшие бэкапы будут удаляться (срок хранения задаётся в скрипте). Автор, собственно, очень удивился тому, что скрипт вышел довольно переносимым. То есть имея окружение, описанное в требованиях, вы можете перезаписать некоторые параметры и он будет работать. Выяснилось это при переносе rus.i2p на новое железо в начале 2012-го. Ожидались проблемы, однако таковых не последовало — скрипт исправно отрабатывает свою функцию.
[править] См. также
Руководство по настройке Linux Web сервера относится к теме «I2P» |