Создание и настройка сервера для удалённой php разработки

Как правило, разработка и отладка приложения выполняются на локальном веб-сервере, обычно это приводит к проблемам типа «как предоставить проект клиенту» ну или просто трудность работы за несколькими компьютерами.

Данная статья не несет ничего нового, а скорей просто пошаговая инструкция как подготовить сервер для разработки проектов.

В итоге мы должны получить:

  • git-репозиторий
  • веб-сервер ( nginx, без apache )
  • php различных версий( 5.3, 5.5 ), с наборами различных модулей ( включая xdebug, apc )
  • mysql, postgresql сервера
  • Удобную структуру для быстрого развертывания проекта
  • Настроенную IDE под работу с этим делом

Крутить будем под CentOS 5

Установка зависимостей

 

rpm -ivh http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
yum install wget make gcc gcc-c++ flex openssl-devel curl-devel expat-devel gettext pcre-devel automake autoconf213 autoconf bison re2c libxml2-devel bzip2-devel libjpeg-devel libpng-devel freetype-devel t1lib-devel libmcrypt-devel libxslt-devel postgresql-server postgresql-devel postgresql postgresql-libs mysql-devel mysql-server

Создание пользователей и структуры каталогов

Создаём группу под пользователей сайта и nginx

groupadd vwww

Каталоги с проектами будем размещать в /home/www

mkdir -p /home/www

 

chmod 711 /home/www

Создаём пользователя под git

useradd git

Создаём пользователя под nginx

useradd -M -g vwww -s /bin/false nginx

Поднимаем git

 

wget --no-check-certificate https://github.com/git/git/archive/master.tar.gz -O - | tar xz

 

cd git-master

 

make prefix=/usr/local all NO_TCLTK=Yes

 

make prefix=/usr/local install

 

cd ..

Ставим gitolite

Для начала у себя на пк генерируем ключи, я работаю под OS X:

ssh-keygen -t rsa

 

ssh-add ~/.ssh/qRoC

Получаем 2 файла: qRoC и qRoC.pub, последний кидаем в домашний каталог пользователя git, и приступаем к установке:

su git

 

cd ~

 

git clone git://github.com/sitaramc/gitolite

 

mkdir -p $HOME/bin

 

gitolite/install -to $HOME/bin

 

$HOME/bin/gitolite setup -pk qRoC.pub

 

rm -rf gitolite

 

rm -f qRoC.pub

 

su

 

cd ~

Устанавливаем nginx

 

wget http://nginx.org/download/nginx-1.3.11.tar.gz -O - | tar xz

 

cd nginx-1.3.11

 

./configure

 

make

 

make install

 

cd ..

 

Файл /etc/init.d/nginx
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /usr/local/nginx/conf/nginx.conf
# pidfile:     /usr/local/nginx/logs/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"

lockfile=/var/lock/subsys/nginx

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

 

chmod +x /etc/init.d/nginx

 

chkconfig nginx on

 

Файл /usr/local/nginx/conf/nginx.conf
По сути настраиваем как хотим, главное строка:
include /home/www/*/conf/nginx.conf;

Пример:

worker_processes  1;

user nginx vwww;

events {
    worker_connections  1024;
}

http {

    include       mime.types;
    default_type  application/octet-stream;

    limit_req_zone  $binary_remote_addr  zone=one:16m  rate=5r/s;

    log_format main      '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $bytes_sent '
                         '"$http_referer" "$http_user_agent" '
                         '"$gzip_ratio"';

    log_format download  '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $bytes_sent '
                         '"$http_referer" "$http_user_agent" '
                         '"$http_range" "$sent_http_content_range"';

    client_header_timeout  3m;
    client_body_timeout    3m;
    send_timeout           3m;

    client_header_buffer_size    1k;
    large_client_header_buffers  4 4k;

    gzip on;
    gzip_min_length  1100;
    gzip_buffers     4 8k;
    gzip_types       text/plain;

    output_buffers   1 32k;
    postpone_output  1460;

    sendfile         on;
    tcp_nopush       on;
    tcp_nodelay      on;

    keepalive_timeout  75 20;

    include /home/www/*/conf/nginx.conf;
}

Создадим шаблон файла хоста по умолчанию:

Файл /usr/local/nginx/conf/host_tpl.conf
server
{
    listen       80;
    server_name  __DOMEN__ www.__DOMEN__;

    error_log  /home/www/__DOMEN__/log/error.log warn;
    access_log /home/www/__DOMEN__/log/access.log main;

    index index.php index.html index.htm;

    root /home/www/__DOMEN__/www;

    limit_req zone=one burst=20 nodelay;

    error_page   500 502 503 504  /50x.html;

    location = /50x.html
    {
        root   html;
    }

    location ~*  \.(js|JPG|jpg|png|jpeg|gif|zip|tgz|gz|rar|doc|xls|exe|pdf|ppt|txt|wav|bmp|rtf)$
    {
        access_log off;
        expires 30d;
    }

    location /
    {
        try_files $uri /index.php?$args;
    }

  location ~ \.php$
  {
    fastcgi_intercept_errors on;
    fastcgi_pass unix:/var/run/__DOMEN__-php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /www$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_script_name;
    fastcgi_param DOCUMENT_ROOT /www;
    include /usr/local/nginx/conf/fastcgi_params;
  }
}

Устанавливаем php 5.3 и 5.5

 

git clone git://github.com/php/php-src php-src

 

cd php-src
Установка php 5.3

 

git checkout PHP-5.3

 

export PHP_AUTOCONF=/usr/bin/autoconf-2.13

 

export PHP_AUTOHEADER=/usr/bin/autoheader-2.13

 

./buildconf --force

 

./configure --prefix=/usr/local/php/5.3 --exec-prefix=/usr/local/php/5.3 --with-config-file-path=/usr/local/php/5.3/etc --with-mysql --with-gd --with-zlib --enable-ftp --enable-gd-native-ttf --with-bz2 --with-mysqli --with-t1lib --enable-mbstring=all --with-curl --enable-sockets --enable-bcmath --with-imap-ssl --enable-soap --with-kerberos --enable-calendar --with-pgsql --with-pdo-pgsql --enable-exif --with-gettext --with-xsl --with-pdo-mysql --with-pdo-pgsql --with-mcrypt --with-openssl --enable-zip --with-iconv --enable-fpm

 

make

 

make install

 

cp php.ini-development /usr/local/php/5.3/etc/php.ini

 

mv /usr/local/php/5.3/etc/php-fpm.conf.default /usr/local/php/5.3/etc/php-fpm.conf

 

mkdir /usr/local/php/5.3/extensions

 

cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm5.3

 

chmod +x /etc/init.d/php-fpm5.3

 

chkconfig php-fpm5.3 on

Настроим php.ini:

include_path = ".:/usr/local/php/5.3/lib/php"

Если не планируете использовать chroot ( в статье используется ):

extension_dir = "/usr/local/php/5.3/extensions"

Иначе ( через конфиг php-fpm не будет работать, скорей это баг )

extension_dir = "/ext"

 

date.timezone = Europe/Kiev

 

cgi.fix_pathinfo=0

Настроим php-fpm.conf:

include=/home/www/*/conf/php-fpm-5.3.conf

Создадим шаблон файла хоста по умолчанию:

Файл /usr/local/php/5.3/etc/php-fpm_host_tpl.conf
[__DOMEN__]
listen = /var/run/__DOMEN__-php-fpm.sock
user = __DOMEN__
group = __DOMEN__

pm = dynamic
pm.max_children = 10
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 5
pm.max_requests = 50

chroot = /home/www/__DOMEN__/
chdir = /www

env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

php_admin_flag[log_errors] = on
php_admin_value[error_log] = /log/php.log

slowlog = /log/slow.log
Чистим мусор от сборки

 

make clean

 

rm configure
Установка php 5.5

 

git checkout PHP-5.5

 

export PHP_AUTOCONF=/usr/bin/autoconf

 

export PHP_AUTOHEADER=/usr/bin/autoheader

Далее аналогично, просто везде где видим «5.3» заменяем на «5.5»

cd ..

Создаём символические ссылки

 

ln -s /usr/local/php/5.3/bin/phpize /usr/local/bin/phpize53

 

ln -s /usr/local/php/5.5/bin/phpize /usr/local/bin/phpize55

Установка дополнительных модулей

 

xdebug
git clone git://github.com/xdebug/xdebug.git xdebug
cd xdebug
git checkout xdebug_2_2
phpize53
./configure --enable-xdebug --with-php-config=/usr/local/php/5.3/bin/php-config
make
cp modules/xdebug.so /usr/local/php/5.3/extensions
echo "zend_extension=/usr/local/php/5.3/extensions/xdebug.so" >> /usr/local/php/5.3/etc/php.ini
make clean
phpize55
./configure --enable-xdebug --with-php-config=/usr/local/php/5.5/bin/php-config
make
cp modules/xdebug.so /usr/local/php/5.5/extensions
echo "zend_extension=/usr/local/php/5.5/extensions/xdebug.so" >> /usr/local/php/5.5/etc/php.ini
cd ..

 

apc
svn co http://svn.php.net/repository/pecl/apc/trunk/ apc-trunk
cd apc-trunk
phpize53
./configure --enable-apc --enable-apc-mmap --with-php-config=/usr/local/php/5.3/bin/php-config
make
cp modules/apc.so /usr/local/php/5.3/extensions
make clean
phpize55
./configure --enable-apc --enable-apc-mmap --with-php-config=/usr/local/php/5.5/bin/php-config
make
cp modules/apc.so /usr/local/php/5.5/extensions
cd ..

Все остальные модули по аналогии.

Время создавать проекты

 

Файл /home/www/new_host
#!/bin/sh
#

if test -z "$1" ; then
    exit 1
fi

if test -z "$2" ; then
    exit 1
fi

if test -z "$3" ; then
    PHP_VER="5.3"
else
    PHP_VER=$3
fi

# Create user and group
pass=$(perl -e 'print crypt($ARGV[0], "FfasfHH")' $2)
groupadd $1
useradd -p $pass -g vwww -G $1 -d /home/www/$1 -m $1

# create catalogs
mkdir -p /home/www/$1/{www,log,tmp,conf}
cp -R /usr/local/php/$PHP_VER/extensions /home/www/$1/ext

# create nginx host config
sed "s/__DOMEN__/$1/g" /usr/local/nginx/conf/host_tpl.conf > /home/www/$1/conf/nginx.conf

# create php-fpm config
sed "s/__DOMEN__/$1/g" /usr/local/php/5.3/etc/php-fpm_host_tpl.conf > /home/www/$1/conf/php-fpm-$PHP_VER.conf

# create default scripts
echo '<?php phpinfo();' > /home/www/$1/www/index.php

# Fix ch
chown -R $1:vwww /home/www/$1
chmod -R 04770 /home/www/$1

# Reload services
service nginx reload
service php-fpm$PHP_VER reload

 

chmod +x /home/www/new_host

Запускать так:
./new_host domain pass [php_version=5.3]
Пример:
./new_host domain pass123 5.5

Создание проекта site.com

 

./new_host site.com mysuperpass

В conf/php-fpm-5.3.conf подключаем нужные расширение

; APC
php_admin_flag[apc.enabled] = 1
php_admin_value[apc.shm_segments] = 1
php_admin_value[apc.shm_size] = 256
php_admin_value[apc.ttl] = 3600
php_admin_value[apc.user_ttl] = 7200
php_admin_value[apc.num_files_hint] = 1024
php_admin_value[extension] = apc.so

; xDebug
php_admin_flag[xdebug.remote_enable] = 1
php_admin_flag[xdebug.remote_connect_back] = 1
php_admin_value[xdebug.remote_handler] = dbgp
php_admin_value[xdebug.remote_mode] = req
php_admin_value[xdebug.remote_port] = 9000
php_admin_value[xdebug.remote_log] = /log/xdebug.log
php_admin_value[xdebug.idekey] = PHPSTORM_XDEBUG

Перезагружаем php-fpm

service php-fpm5.3 reload

Открываем phpStorm, жмём «New Project from Existing Files».

В диалоговом окне выбираем «Web server is on remote host, files are accessible FTP/SFTP/FTPS». Жмём Next.

Указываем Project name: site.com. Жмём Next.

Выбираем «Add new remote server», и настраиваем примерно так:

e08dbac64bc11a47b3986db99a9b493b

Жмёт «Next» и отмечаем каталог «www» как «Project Root».

Заходим в Project Settings -> Deployment -> Options и выставляем галочки вот так:

9db905defe998dee9499b09c29e3e925

Заходим в Preferences -> PHP -> Servers и добавляем новый сервер:

Host: ип сервера
Port: 80
Debugger: Xdebug
Ставим галочку «Use path mapping (select if the server is remote or symlinks are used)»
Указываем путь к проекту: «/www»

Заходим в Run -> Edit Configuration, открываем «PHP Web Application», указываем «Server»

Жмём Run -> Start Listen PHP Debug Connections

Создание репозитория

Следующие действия выполняем у себя.

git clone git@host:gitolite-admin

host заменяем на ip Вашего сервера
В каталог kaydir кинуть публичный ключ, у меня это qRoC.pub, выполнить:

git add .

 

git commit -a -m "User qRoC added"

 

git push

Для создания репозитория открываем файл conf/gitolite.conf, и прописываем:

repo site.com 
    RW+ = qRoC

 

git add .

 

git commit -a -m "repo site.com added"

 

git push