Test sites with automatic update with svn and the authorization as to credentials of Redmine

Test sites with automatic update with svn and the authorization as to credentials of Redmine

This is a follow-up to the article on Redmine installation and the integration of svn repositories.

First you need to program Wildcard DNS record to avoid a constant editing of the DNS zone after adding a new test:

*.dev.example.com.   IN  A server_ip

Add the user, directories and put the necessary permissions:

# 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

The result should look like this:

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

total 20
drwxr-x--- 5 root         cool-project 4096 Jun  8 11:25 .
drwxr-xr-x 7 root         root         4096 Jun  8 11:04 ..
drwxr-x--- 2 root         root         4096 Jun  8 11:04 db_backup
drwxr-x--- 2 root         root         4096 Jun  8 11:04 old_document_root
-rwx------ 1 root         root            0 Jun  8 11:25 update.sh
drwxr-x--- 2 cool-project root         4096 Jun  8 11:04 www

That is, we will run each site from a name of particular user, the sources of individual projects being isolated. Source backups and database will be available only for the root. Update script can run and edit only the root (we will let it through sudo only, and the cool-project user is not allowed to make any changes).

To run the scripts under different users will use the mpm-itk and we’ll need mod-auth-mysql for authentication to the test:

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

Also we need to create a particular authorization table:

CREATE VIEW users_auth_external AS
SELECT u.login AS username,
       u.hashed_password AS passwd,
       GROUP_CONCAT(p.identifier) AS groups
FROM `members` m
INNER JOIN users u ON m.user_id = u.id
INNER JOIN projects p ON m.project_id = p.id
WHERE u.status = 1
GROUP BY username

Let's create a configuration for the virtual host:

# 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" 
                AuthBasicAuthoritative Off
                AuthUserFile /dev/null
                AuthMySQL On
                AuthMySQL_Authoritative      on
                AuthMySQL_Host               localhost
                AuthMySQL_DB                 redmine_default
                AuthMySQL_User               redmine
                AuthMySQL_Password           redmine_password #a password for access to Redmine DB
                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
                Require group                cool-project
 
        <Limit GET POST>
                require group cool-project
        </Limit>
 
    </Directory>
 
AssignUserID cool-project cool-project
 
</VirtualHost>

Then connect the vhost and reread Apache:

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

Create the script of update:

# vi /var/www/cool-project.dev.example.com/update.sh
 
#!/bin/sh
 
path="/var/www/cool-project.dev.example.com"; #path to document root
host="cool-project.dev.example.com";
db_username=cool-project; #username to access db
db_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" ] 
do
        if [ -z "$lock_file" ]; then
                echo "ok, continue"; wait=no;
        else
                echo "another copy running now!"; sleep 60;
        fi;
 
        lock_file=`ls $path|grep run.lock`;
done
touch $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 -R 777 $path/www/tmp/;
chmod -R 777 $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;
env APPLICATION_ENV=staging $path/www/scripts/doctrine migrate > $path/www/migrate_log.txt;
chmod 750 $path/www;
chmod -R 777 $path/www/log/;
rm $path/run.lock;
echo "Update $host complete." 

I gave the example of a typical script update for the project on Zend. You most likely will need to make changes to it as to your own data.

Now let’s add the svn hook. The script at the commit in the repository will run and update our test site:

# 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 &

Hooks are executed under the www-data and, we will have to use sudo to change the owner of the directory.

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

Starting with the version 1.2.0 Redmine began to add salt to the password hashes. And if you want to use the authorization to test — you need to patch auth_mysql. Patch: mod_auth_mysql.patch

Deb packages for Debian squeeze: libapache2-mod-auth-mysql_4.3.9-13_amd64.deb
and Ubuntu 10.04: libapache2-mod-auth-mysql_4.3.9-12ubuntu1_amd64.deb

References:
Authenticate Apache against Redmine with AuthMySQL
Redmine guide
Manual for assembly and back porting of deb packages