Тестовые сайты с автоматическим обновлением с svn и авторизацией по учетным данным Redmine

Это продолжение статьи о установке Redmine и интеграции svn хранилищ.

Для начала нужно прописать Wildcard DNS record, чтоб при добавлении нового тестового не нужно было постоянно редактировать DNS зону:

*.dev.example.com.   IN  A server_ip

Добавим пользователя, директории и поставим нужные права доступа:

# useradd -d/var/www/cool-project.dev.example.com/www -s/bin/false cool-project
# mkdir -p /var/www/cool-project.dev.example.com/{www,old_document_root,db_backup}
# chmod -R 750 /var/www/cool-project.dev.example.com/
# chgrp cool-project /var/www/cool-project.dev.example.com/
# chown -R cool-project /var/www/cool-project.dev.example.com/www
# touch /var/www/cool-project.dev.example.com/update.sh && chmod 700 /var/www/cool-project.dev.example.com/update.sh

В результате должно получиться так:

# ls -la /var/www/cool-project.dev.example.com/

итого 20
drwxr-x--- 5 root         cool-project 4096 Июн  8 11:25 .
drwxr-xr-x 7 root         root         4096 Июн  8 11:04 ..
drwxr-x--- 2 root         root         4096 Июн  8 11:04 db_backup
drwxr-x--- 2 root         root         4096 Июн  8 11:04 old_document_root
-rwx------ 1 root         root            0 Июн  8 11:25 update.sh
drwxr-x--- 2 cool-project root         4096 Июн  8 11:04 www

Т.е. мы будем запускать каждый сайт от отдельного пользователя, исходники отдельных проектов будут изолированы. Бэкапы исходников и БД будут доступны только руту. Скрипт обновления сможет запускать и править только root (мы будет пускать его через sudo и нельзя позволить пользователю cool-project вносить в него какие-то изменения).

Для запуска скриптов под разными пользователями будем использовать mpm-itk и нам понадобиться mod-auth-mysql для авторизации на тестовых:

# aptitude install apache2-mpm-itk libapache2-mod-auth-mysql
# a2enmod auth_mysql
# /etc/init.d/apache2 restart

Также нужно создать отдельную таблицу для авторизации:

CREATEVIEW users_auth_external ASSELECT u.login AS username,
       u.hashed_password AS passwd,
       GROUP_CONCAT(p.identifier)AS groups
FROM`members` m
INNERJOIN users u ON m.user_id = u.id
INNERJOIN projects p ON m.project_id = p.id
WHERE u.status =1GROUPBY username

Создадим конфиг для виртуального хоста:

# vi /etc/apache2/sites-available/cool-project.dev.example.com
 
<VirtualHost *:80>
    ServerName cool-project.dev.example.com
    ServerAdmin admin@example.com
    DocumentRoot /var/www/cool-project.dev.example.com/www
    Options -Indexes
 
    <Directory /var/www/cool-project.dev.example.com/www>
                AuthType Basic
                AuthName"enter your login/password from redmine"AuthBasicAuthoritativeOffAuthUserFile /dev/null
                AuthMySQL On
                AuthMySQL_Authoritative      on
                AuthMySQL_Host               localhost
                AuthMySQL_DB                 redmine_default
                AuthMySQL_User               redmine
                AuthMySQL_Password           redmine_password #пароль для доступа к БД Redmine
                AuthMySQL_Password_Table     users_auth_external
                AuthMySQL_Group_Table        users_auth_external
                AuthMySQL_Username_Field     username
                AuthMySQL_Password_Field     passwd
                AuthMySQL_Empty_Passwords off
                AuthMySQL_Group_Field        groups
                AuthMySQL_Encryption_Types   SHA1Sum
                Requiregroup                cool-project
 
        <Limit GET POST>
                requiregroup cool-project
        </Limit>
 
    </Directory>
 
AssignUserID cool-project cool-project
 
</VirtualHost>

Дальше подключим vhost и перечитаем конфиги Apache:

# a2ensite cool-project.dev.example.com
# /etc/init.d/apache2 reload

Создадим скрипт апдейта:

# vi /var/www/cool-project.dev.example.com/update.sh
 
#!/bin/sh
 
path="/var/www/cool-project.dev.example.com"; #path to document roothost="cool-project.dev.example.com";
db_username=cool-project; #username to access dbdb_name=cool-project_stag;
db_password="qwerty";
backup_dir="old_document_root";
user="cool-project";
lock_file=`ls$path|grep run.lock`;
wait=yes;
 
echo"Update $host";
 
while["$wait" = "yes"]doif[-z"$lock_file"]; thenecho"ok, continue"; wait=no;
        elseecho"another copy running now!"; sleep60;
        fi;
 
        lock_file=`ls$path|grep run.lock`;
donetouch$path/run.lock;
 
echo"[`date +%H:%M`] update in progress">>$path/www/public/status.txt;
echo"last update at [`date +%H:%M`]">>$path/status.txt;
svn info https://dev.example.com/svn-private/cool-project/|grep"Last">>$path/status.txt;
svn export--force https://dev.example.com/svn-private/cool-project/trunk/$path/test_new;
 
mv$path/status.txt $path/test_new/public/;
 
mysqldump -u$db_username -p$db_password$db_name>$path/db_dumps/database_at_`date +%Y-%m-%d-%H-%M-%S`.sql;
chown-R$user$path/test_new/;
 
cp-a$path/www/public/upload/*$path/test_new/public/upload;
 
mv$path/www $path/$backup_dir/test`date +%Y-%m-%d-%H-%M-%S`;
mv$path/test_new $path/www;
chmod-R777$path/www/tmp/;
chmod-R777$path/www/public/upload/;
 
sed-i s/production/staging/$path/www/public/.htaccess;
rm$path/www/scripts/common.local.php
sed-i'0,/production/s//staging/'$path/www/scripts/common.php;
envAPPLICATION_ENV=staging $path/www/scripts/doctrine migrate >$path/www/migrate_log.txt;
chmod750$path/www;
chmod-R777$path/www/log/;
rm$path/run.lock;
echo"Update $host complete."

Я дал пример типичного скрипта апдейта для проекта на Zend. Вам скорее всего нужно будет вносить в него изменения под свои реалии.

Теперь добавим svn hook. При коммите в хранилище будет запускаться скрипт и обновлять наш тестовый сайт:

# cd /var/svn/cool-project/hooks
# cp post-commit.tmpl post-commit && chown www-data post-commit
# vi post-commit

sudo /var/www/cool-project.dev.example.com/update.sh 2>&1 > /dev/null &

Хуки исполняются под www-data и для того, что б менять владельца директории нам придется использовать sudo.

# visudo
www-data ALL=NOPASSWD:/var/www/cool-project.dev.example.com/update.sh

Начиная с версии 1.2.0 Redmine стал добавлять соль в хеши паролей. И если вы хотите использовать авторизацию на тестовых - нужно пропатчить auth_mysql. Патч: mod_auth_mysql.patch

Deb пакеты для Debian squeeze: libapache2-mod-auth-mysql_4.3.9-13_amd64.deb
и Ubuntu 10.04: libapache2-mod-auth-mysql_4.3.9-12ubuntu1_amd64.deb

Ссылки:
Authenticate Apache against Redmine with AuthMySQL
Redmine guide
Руководство по сборке и бэкпортированию deb пакетов