Когда делаешь простые сайты на WordPress, то с вебсервером все просто, поставил себе Xampp и спокойно работаешь.
Но приходит момент когда начинаешь заниматься серьезными проектами, а там уже конфигурация на сервере не совсем обычная и пользоваться Xampp не совсем удобно, к тому же у меня аллергия на Apache.
Захотелось хороший, живой вебсервер по типу выделеного сервера, но на своем компе, при этом чтобы пользоваться было удобно, локально.
Что именно хочется:
- Поддержку нормальных url типа sitename.ru
- Не редактировать /etc/hosts
- Не редактировать конфиги nginx
- Работать в локальной папке
- Удобное администрирование конфигурации сервера
- Изолированое окружение
- Поставить и забыть
Есть еще вариант — просто у себя поднять все, но есть загвоздка, если что нибудь сломается, упадет жесткий диск, или еще что нибудь, то потом опять все собирать будет лень, а так просто можно сделать бэкап файла виртуальной машины, так же получаем независимое окружение.
Поэтому я поднял дебиан на виртуальной машине (virtualbox) и настроил nginx+phpfpm за пару часов, но это не очередное хау ту по связке nginx+phpfpm, мы делаем готовое решение по типу xampp.
Подготовка
Итак, мы имеем свежеустановленный Debian 7 (wheezy). Виртуальная машина имеет имя webserver. На локальной машине установлен так же Debian wheezy.
Первым делом хотелось бы избавиться от диалогового окна и использовать ssh.
Выключаем виртуальную машину и пишем:
$ VBoxManage modifyvm "webserver" --natpf1 "guestssh,tcp,127.0.0.1,2222,10.0.2.15,22"
Заодно пробросим 80 порт для вебсервера.
Порты меньше 1024 может открывать только root (Спасибо or10n), поэтому я просто пробросил 8888 порт и перенаправил с 80 порта на 8888.
$ VBoxManage modifyvm "webserver" --natpf1 "web,tcp,127.0.0.1,8888,10.0.2.15,80"
# iptables -t nat -A OUTPUT -d 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to 8888
# nano /etc/rc.local
Вставляем до exit 0
iptables -t nat -A OUTPUT -d 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to 8888
Тут вместо 10.0.2.15 может быть другой ip, смотрите вывод команды ifconfig на eth0.
Запускаем виртуальную машину в фоне, это очень удобно, прошу заметить, что запускаем под обычным пользователем, у которого находится виртуальная машина webserver.
$ (vboxheadless -s webserver &)
Жмем энтер
Все, мы пробросили 2222 порт на 22 внутренний, 80 порт будет работать, позже увидим. Пробуем коннектиться:
# ssh root@127.0.0.1 -p 2222
Устанавливаем пакеты:
# apt-get install nginx php5 php5-fpm php5-mysql php5-gd php5-mcrypt mysql-server mysql-utilities
Настраиваем php-fpm.
Поскольку тут нам париться с безопасностью не надо, поэтому все будет работать от одного юзера www-data.
Так же мы будем обращаться через сокет. Предлагаю готовый конфиг, на самом деле я там особо своего ничего не добавлял, не забываем делать бэкапы.
# mv /etc/php5/fpm/php-fpm.conf /etc/php5/fpm/php-fpm.conf.default
# nano /etc/php5/fpm/php-fpm.conf
Вставляем следующее:
[global]
pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
include = /etc/php5/fpm/pool.d/*.conf
Здесь опять же дефолт, можете вообще этого не делать, т.к. это тот же конфиг только без комментариев, но мне так проще ореинтироваться в конфиге.
Теперь надо подготовить пулл, который будет обрабатывать наши php запросы. Приводим конфиг к следующему виду.
# nano /etc/php5/fpm/pool.d/www.conf
Вставляем следующее
[www]
user = www-data
group = www-data
listen = /tmp/php5-fpm.sock
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /
Параметры pm хорошо описаны на других ресурсах, поэтому тут я ничего не буду объяснять, просто держите готовое.
Осталось поправить php.ini. На самом деле кого то может устроить и дефолтный, он неплохой. Но я все же приведу свой.
# nano /etc/php5/fpm/php.ini
Конфиг большой и необязательный, поэтому выкладываю сюда pastebin.com/AAudu4sh
Перезагружаем php-fpm
# service php5-fpm restart
Настраиваем nginx.
В общем остается проблема с конфигами, лень каждый раз лезть на сервер, добавлять конфиг, перезагружать nginx. Поэтому собрал универсальный конфиг.
После можно будет просто создать папку, залить файлы и работать. Сказано, сделано. Вот Вам готовый конфиг nginx:
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Базовые настройки
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# При ошибках не говорим врагу версию nginx
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Настройка логов
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Настройки сжатия
##
gzip on;
gzip_disable "msie6";
##
# Настройка виртуальных доменов
##
include /etc/nginx/conf.d/*.conf;
server {
server_name phpmyadmin.l;
listen 80;
root /web/utils/phpmyadmin.l;
index index.php index.html index.htm;
access_log /web/access.log;
error_log /web/error.log;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico)$ {
access_log off;
expires max;
}
location ~ \.php$ {
# fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_pass unix:/tmp/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors off;
fastcgi_ignore_client_abort off;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
}
server {
server_name ~^(.*)$;
listen 80;
set $p $host;
if ($host ~ www\.(.*)) { set $p $1; }
root /web/sites/$p;
index index.php index.html index.htm;
access_log /web/access.log;
error_log /web/error.log;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico)$ {
access_log off;
expires max;
}
location ~ \.php$ {
# fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_pass unix:/tmp/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param SERVER_NAME $p;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors off;
fastcgi_ignore_client_abort off;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
}
}
# mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.default
# nano /etc/nginx/nginx.conf
Вставляем вышеприведеный конфиг
Я не претендую на то что конфиг хорош и идеален, но он у меня работает и проблем пока не возникало. Я буду очень рад если тут найдутся люди которым есть что сюда добавить.
Ну все, осталось только настроить дериктории. Немного поясню как у нас будет все происходить.
- /web папка где будет лежать весь сервер, за исключением конфигов конечно же
- /web/utils — туда мы будем складывать все наши дополнительные, вспомогательные скрипты типа phpmyadmin, пока я не придумал что туда еще положить, т.к. пока больше ничего не надо.
- /web/sites — тут наши все сайты.
Так же будут логи, access и error.
Создаем папки
# mkdir /web && mkdir /web/sites && mkdir /web/utils
Задаем права
# chmod -R a-rwx,u+rwX,g+rX /web && chown www-data:www-data -R /web
Перезагружаем nginx.
# service nginx restart
Осталось поставить phpmyadmin.
На сервере выполняем
# su www-data
# cd /web/utils/phpmyadmin.l && wget http://jaist.dl.sourceforge.net/project/phpmyadmin/phpMyAdmin/4.0.4.2/phpMyAdmin-4.0.4.2-all-languages.zip && unzip phpMyAdmin-4.0.4.2-all-languages.zip && mv phpMyAdmin-4.0.4.2-all-languages/* ./ && rm -r phpMyAdmin-4.0.4.2-all-languages/ && rm phpMyAdmin-4.0.4.2-all-languages.zip
# exit
Все, phpmyadmin готов к труду и обороне. можно его теперь найти по адресу phpmyadmin.l
Итак, вебсервер у нас готов, осталось сделать так чтобы он стартовал при загрузке, сохранялся при выключении и перезагрузке, и при этом не было окна состояния.
Немного опишу стратегию, после того как виртуальная машина загрузится, мы при помощи sshfs маунтим директорию с сайтами, и я сделал это автоматом.
Так же мне лень каждый раз редактировать файл /etc/hosts при добавлении очередного сайта, поэтому мы все это автоматизируем.
Автоматизация
Делаем авторизацию по ключу
На сервере надо:
Остановить демоны nginx и php5-fpm, и установить домашнюю дерикторию для юзера www-data.
# service nginx stop && service php5-fpm stop
# mkdir /home/www-data && usermod -d /home/www-data www-data
# service nginx start && service php5-fpm start
Сгенерировать ключ от рута, и после поместить публичный в файл /home/www-data/.ssh/authorized_keys
На клиенте проверяем:
# ssh www-data@127.0.0.1 -p 2222
Если зашли без пароля, то все хорошо, если нет, то что-то Вы сделали не так с ключами.
Теперь осталось создать 2 скрипта.
1) Скрипт проверки доступности виртуальной машины и автоматический маунтинг, так же генерация файла /etc/hosts.
# nano /usr/bin/webserver
Вставляем следующий код
#!/bin/bash
sleep=60 # Интервал
when_mount='/mnt/webserver' # Дериктория куда все это будет маунтиться
directories=`ls -p $when_mount | grep "/" | sed 's/\///g'`
while true; do
if ! $(mount | grep "$when_mount" > /dev/null); then
if [ "$(nmap -p 2222 -sT 127.0.0.1 | awk '{print $2}' | grep open)" = "open" ]; then
sshfs -o allow_other -o port=2222 www-data@127.0.0.1:/web/sites "$when_mount"
fi;
elif ! [ "$directories" = $(ls -p $when_mount | grep "/" | sed 's/\///g') ]; then
hosts=$(grep -v "127.0.0.1" /etc/hosts)
directories=$(ls -p $when_mount | grep "/" | sed 's/\///g')
if ! [ "$directories" = "" ]
then
echo "$hosts" > /etc/hosts
echo "127.0.0.1 localhost phpmyadmin.l "$directories >> /etc/hosts
fi;
fi
sleep "$sleep"
done
На правильность кода я не претендую, и буду рад тому кто найдет там баги. Но у меня он работает исправно.
Удобство скрипта в том что даже если перезагрузите виртуальную машину, ничего не поломается и все будет хорошо.
Теперь делаем его исполняемым
# chmod -x /usr/bin/webserver
2) Небольшой скрипт который будет запускать и останавливать вебсервер.
# nano /etc/init.d/webserverd
Вставляем следующий код
#!/bin/bash
case "$1" in
start)
echo -n "Starting webserver: "
(su - darkrain -c 'vboxheadless -s webserver' &)
(webserver &)
;;
stop)
echo -n "Stopping webserver: "
(su - darkrain -c 'VBoxManage controlvm webserver savestate' &)
killall webserver
;;
esac
exit 0
darkrain — заменить на вашего юзера, т.к. созданая машина находится в подчинении у него, а не у рута.
Опять же я тут не профи, буду признателен если меня поправят, но это работает.
Выставляем права, и добавляем в список сервисов
# chmod -x /etc/init.d/webserverd && update-rc.d webserverd defaults
Осталось создать каталог где будут видны наши сайты
# mkdir /mnt/webserver && chmod 777 /mnt/webserver
Рестартуем наш сервер
# service webserverd stop
# service webserverd start
Все, теперь все счастливы и довольны, создаем для теста:
$ mkdir /mnt/webserver/testsite.ru.l && echo "<?php phpinfo();" > /mnt/webserver/testsite.ru.l/index.php
Ждмем 60 секунд, и идем в браузер по адресу testsite.ru.l
Ну все, мы закончили! Можно забыть про то что у нас есть вообще виртуальная машина, пока конечно не понадобиться поставить какую нибудь либу или еще что-то может понадобиться.
Теперь чтобы работать с новым сайтом я просто создам папку с именем домена в /mnt/webserver, и просто буду работать не отвлекаясь.
P.S.
Здесь более менее понятно описано про php-fpm, про пулы и прочее manualpages.pro/node/31
UPD.
Кому не понравится мой велосипед, может использовать Vagrant (спасибо zvirusz ). Ссылки:
- Официальный сайт
- Быстрое развертывание среды разработки
- Создание новой виртуальной машины за одну минуту или «vagrant up!»
Остальная информация была взята по крупицам из Google.
Спасибо НЛО за инвайт!