Небольшой пример, как настроить локальное окружение для веб-разработки, и при этом перестать редактировать конфиги для каждого нового проекта. Суть сводится к тому, что для начала работы над проектом, достаточно просто создать новую директорию для него, и начать работать, а веб-сервер сделает остальное за Вас.
Хватит редактировать /etc/hosts
Каков обычный сценарий веб-разработчика, начинающего писать новый проект? Правильно, настройка apache и внесение новой записи в /etc/hosts. До конфигурации самого сервера еще дойдем, а пока перестанем редактировать файл hosts. Для обработки запросов к нашим виртуальным хостам нам понадобится dnsmasq. Если Вы используете NetworkManager, то у Вас уже есть все что нужно, в противном случае необходимо установить dnsmasq средствами вашего дистрибутива. Я рассмотрю пример, когда используется NetworkManager.
Сперва включим поддержку dnsmasq в конфигурационном файле NetworkManager’а, добавив в файл /etc/NetworkManager/NetworkManager.conf следующее:
dns=dnsmasq
Далее, в директории /etc/NetworkManager/dnsmasq.d создадим файл конфигурации local-development.conf с таким содержанием:
Таким образом, мы привязали любой домен в зоне .dev к адресу 127.0.0.1, что избавляет нас от внесения новых записей в /etc/hosts. Для вступления настроек в силу, необходимо перезапустить NetworkManager.
Если вы не используете NetworkManager, то после установки необходимо сконфигурировать dnsmasq, внеся привязку Вашей тестовой зоны в файл /etc/dnsmasq.conf, пример можно посмотреть тут.
Настройка php-fpm
Я уже продолжительное время не использую apache, найдя ему замену в лице nginx + php-fpm. Раньше для каждого проекта я создавал отдельный pool, но на данный момент я решил перейти к универсальному конфигу, который бы работал для каждого добавляемого проекта. Собственно конфигурация fpm (/etc/php5/fpm/php-fpm.conf):
pid = /var/run/php-fpm.pid
error_log = /var/log/php/fpm/error.log
log_level = notice
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s
daemonize = yes
[www]
listen = /var/run/php5-fpm.sock
listen.backlog = -1
listen.allowed_clients = 127.0.0.1
listen.owner = gwinn
listen.group = gwinn
listen.mode = 0666
user = gwinn
group = gwinn
pm = dynamic
pm.max_children = 5
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 200
pm.status_path = /status
request_terminate_timeout = 120s
request_slowlog_timeout = 10s
slowlog = /var/log/php/fpm/slow.log
rlimit_files = 131072
rlimit_core = unlimited
catch_workers_output = yes
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
php_flag[display_errors] = on
php_admin_value[error_log] = /var/log/php/fpm/error.log
php_admin_value[session.save_path] = /tmp
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 32M
С учетом того, что в большинстве случаев, в конкретный момент времени, девелопер работает на одним проектом, я считаю, что можно смело допустить использование одного пула для всех проектов.
Настройка nginx
Nginx не обойдется одним файлом конфигурации, под каждый тип проектов, я создал свой конфиг, впрочем, это все равно делается только один раз, что собственно не плохо. Под типами проектов я подразумеваю следующее: Symfony2, CodeIgniter, WordPress, Ruby on Rails, Mojolicious и т.д. Помимо этого, nginx будет обрабатывать запросы к phpMyAdmin и phpPgAdmin, для которых так же я сделал отдельный конфиг.
Приведу примеры основного конфига nginx, а так же конфигурацию для менеджеров баз данных и проектов на Symfony2, остальное можно сделать по аналогии.
/etc/nginx/nginx.conf
worker_processes 2;
timer_resolution 100ms;
worker_rlimit_nofile 8192;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
autoindex on;
keepalive_timeout 65;
gzip on;
gzip_min_length 1100;
gzip_buffers 64 8k;
gzip_comp_level 3;
gzip_http_version 1.1;
gzip_proxied any;
gzip_types text/plain application/xml application/x-javascript text/css;
charset utf-8;
client_body_temp_path /tmp/nginx_client_body_temp 1 2;
fastcgi_temp_path /tmp/nginx_fastcgi_temp;
scgi_temp_path /tmp/nginx_scgi_temp;
proxy_temp_path /tmp/nginx_proxy_temp;
uwsgi_temp_path /tmp/nginx_uwsgi_temp;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
/etc/nginx/sites-enabled/db.conf
server unix:/var/run/php5-fpm.sock;
}
server {
listen 127.0.0.1:80;
server_name *.db.dev;
root /usr/local/share/db/$http_host;
if ( !-e $request_filename ) {
rewrite ^ /index.php last;
}
location / {
index index.html index.htm index.php;
try_files $uri $uri/ /index.php;
}
location ~* ^.+\.(jpg|jpeg|JPEG|JPG|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
access_log off;
expires max;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass phpcgi;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/error.log";
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;
fastcgi_intercept_errors on;
}
location ~ /\.ht {
deny all;
}
location ~ /\.git {
deny all;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
/etc/nginx/sites-enabled/symfony.conf
server unix:/var/run/php5-fpm.sock;
}
server {
listen 127.0.0.1:80;
server_name *.sym.dev;
root /home/gwinn/Code/$http_host/web;
if ( !-e $request_filename ) {
rewrite ^ /app_dev.php last;
}
location / {
index app_dev.php
try_files $uri $uri/ /app_dev.php;
}
location ~* ^.+\.(jpg|jpeg|JPEG|JPG|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
access_log off;
expires max;
}
location ~ ^/(app|app_dev|config)\.php(/|$) {
include /etc/nginx/fastcgi_params;
fastcgi_pass symfony;
fastcgi_index app_dev.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/error.log";
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;
fastcgi_intercept_errors on;
}
location ~ /\.ht {
deny all;
}
location ~ /\.git {
deny all;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
}
Обратите внимание на директиву server_name. Для всех локальных ресурсов используется зона .dev, все проекты, например на Symfony2, размещаются по адресу project_name.sym.dev, а менеджеры баз данных по адресу manager_name.db.dev, то есть каждый тип проекта размещается по схеме project.type.dev, все поддомены обрабатываются автоматически. Теперь достаточно создать директорию, например, myproj.sym.dev, и nginx автоматически будет применять к данной директории конфиг для Symfony. Для любого другого типа проектов, все делается аналогично.