Automatically push master branch code to demo server
I have two VPSs (Virtual Private Server).
One is used as a version control repository. It runs both Gitolite and Fossil.
The second is a "normal" LAMP server. I want to use that to demonstrate the code I have created and have pushed to the version control server. But I only want that code to get run on this server if it is in the master branch of the repository of the project I am working on.
This post will explain how setup the demo server to automate the creation and setup of a new website and then connect the version control server to the demo server so it will automatically update the code running on the demo server when code is checked into the master branch of the repository.
The Environment:
The Version Control Server (VServer)
- Ubuntu 12.04 LTS
- Has 3 users: root, normal and gitolite
- Running Gitolite
The Demonstration Server (DServer)
- Ubuntu 12.04 LTS
- Has 3 users: root, normal and git
- Running LAMP stack
- Git is installed
- ACL is installed
Checklist of software and setup:
Setup the PC
Git (and optionally Git-Flow) is installed on PC
Setup the VServer
Install and setup gitolite
You should be able to create new repositories on VServer through gitolite-admin on your PC.
Setup the DServer
Install and setup git:
sudo apt-get install git
Create git group and user:
sudo adduser \ --system \ --shell /bin/bash \ --gecos 'git version control' \ --group \ --disabled-password \ --home /home/git \ git
Install and setup ACL (Access Control List):
sudo apt-get install acl
Edit /etc/fstab and add "acl" to the end of the options list
Reboot DServer
Add the git group to the www directory:
setfacl -m group:git:rwx /var/www
As the git user:
Add a repositories directory
Set up SSH ability from the VServer to the DServer:
As the gitolite user on the VServer: Create a ssh key for DServer scp public key to DServer Check that it works
See the Create SSH Keys post for more information about creating ssh keys.
Edit git user to only use git-shell:
sudo vim /etc/passwd Change /bin/sh to /usr/bin/git-shell (or wherever git-shell is)
Copy the following scripts -
Into "normal user" /bin directory on DServer and make both of them executable.
#!/bin/bash # This script is used to create virtual hosts. # This script assumes the following: # 1) This is a Debian/Ubuntu OS and Bash 4.x or higher is installed # 2) The Apache defaults are in place but they can be changed in the script # Base dir is /var/www # Log dir is /var/log/apache2 # Apache user is www-data # 3) Git is installed # 4) ACL is installed # 5) There is a git user and # 6) There is a /home/git/repositories directory # But #2-6 can be changed in the script # This uses the a2ensite command which is usually only available on # Debian/Ubuntu systems. # NOTE! Change the <your domain> in the third prompt to your domain # Set up the default parameters read -e -p "Enter the web home directory:" -i "/var/www" homedir read -e -p "Enter the git repository base directory:" -i "/home/git/repositories" gitdir read -e -p "Enter the domain name for the server:" -i "<your domain>" sn read -e -p "Enter the Project name:" -i "" proj if [ -z "$proj" ]; then echo "Project name cannot be blank!" exit fi # Create the web directory and a index.php test file cd $homedir mkdir $proj cd $homedir/$proj mkdir "public_html" # Set the owner and change permissions chown -R www-data:www-data $homedir/$proj/ chmod -R '750' $homedir/$proj/public_html # Setup the permissions so git can write to website setfacl -Rm d:u:www-data:rwx,u:git:rwx $homedir/$proj # Create the git directory and a bare git repository cd $gitdir mkdir $proj.git cd $gitdir/$proj.git git init --bare cat >hooks/post-receive <<EOF #!/bin/bash GIT_WORK_TREE=$homedir/$proj/public_html git checkout -f EOF chmod ug+x hooks/post-receive chown -R git:git $gitdir/$proj.git # Create a directory for your apache errors log mkdir /var/log/apache2/$proj/ # Creation the file with VirtualHost configuration in /etc/apache2/site-available/ echo "<VirtualHost *:80> ServerAdmin webadmin@localhost ServerName $proj.$sn ServerAlias www.$proj.$sn DocumentRoot $homedir/$proj/public_html/ <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory $homedir/$proj/public_html/> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "'/usr/lib/cgi-bin'"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog /var/log/apache2/$proj/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/log/apache2/$proj/access.log combined Alias /doc/ "'/usr/share/doc/'" <Directory "'/usr/share/doc/'"> Options Indexes MultiViews FollowSymLinks AllowOverride None Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 </Directory> </VirtualHost>" > /etc/apache2/sites-available/$proj # Add the host to the hosts file echo 127.0.0.1 $proj.$sn >> /etc/hosts # Enable the site a2ensite $proj # Reload Apache2 service apache2 reload
#!/bin/bash # This script is used to remove virtual hosts. # This script assumes the following: # 1) This is a Debian/Ubuntu OS and Bash 4.x or higher is installed # 2) The Apache defaults are in place but they can be changed in the script # Base dir is /var/www # Log dir is /var/log/apache2 # Apache user is www-data # 3) Git is installed # 4) ACL is installed # 5) There is a git user and # 6) There is a /home/git/repositories directory # But #2-6 can be changed in the script # This uses the a2dissite command which is usually only available on # Debian/Ubuntu systems. # NOTE! Change the <your domain> in the fourth prompt to your domain # Set up the default parameters read -e -p "Enter the web home directory:" -i "/var/www" homedir read -e -p "Enter the web log directory:" -i "/var/log/apache2" logdir read -e -p "Enter the git repository base directory:" -i "/home/git/repositories" gitdir read -e -p "Enter the domain name for the server:" -i "<your domain>" sn read -e -p "Enter the Project name:" -i "" PROJECT if [ -z "$PROJECT" ]; then echo "Project name cannot be blank!" exit fi # Remove the website and logs if rm -rf $homedir/$PROJECT; then echo "Deleted $homedir/$PROJECT" else echo "WARNING: $homedir/$PROJECT was not removed!" fi if rm -rf $logdir/$PROJECT; then echo "Deleted $logdir/$PROJECT" else echo "WARNING: $logdir/$PROJECT was not removed!" fi a2dissite $PROJECT if rm -rf /etc/apache2/sites-available/$PROJECT; then echo "Deleted /etc/apache2/sites-available/$PROJECT" else echo "WARNING: /etc/apache2/sites-available/$PROJECT was not removed!" fi # Remove the git repository if rm -rf $gitdir/$PROJECT.git; then echo "Deleted $gitdir/$PROJECT.git" else echo "WARNING: $gitdir/$PROJECT.git was not removed!" fi # Remove the hosts entry gitrepo="127.0.0.1 $PROJECT.$sn" #echo "gitrepo: $gitrepo" if sed -i "/$gitrepo/d" /etc/hosts; then echo "Deleted $gitrepo from /etc/hosts file" else echo "WARNING: $gitrepo was not removed!" fi # Reload Apache service apache2 reload
Into gitolite /support directory on VServer and make setupmasterpush executable.:
#!/bin/bash while read oldrev newrev refname do branch=$(git rev-parse --symbolic --abbrev-ref $refname) if [ "master" == "$branch" ]; then git push origin master fi done
#!/bin/bash # This script is used to setup the repository to push code # from the master branch only to the "Production" server. # This script assumes the following: # 1) Gitolite is installed # 2) There is a gitolite user and # 3) There is a /home/gitolite/repositories directory # 4) There is a /home/gitolite/support directory and the # post-receive file is there # Make sure you change the <hostname> parameter # Set up the default parameters HOSTNAME="<hostname>" read -e -p "Enter the Project name:" -i "" PROJECT if [ -z "$PROJECT" ]; then echo "Project name cannot be blank!" exit fi cd /home/gitolite/repositories/$PROJECT.git cp ../../support/post-receive hooks/. chmod ug+x hooks/post-receive git remote add origin $HOSTNAME:repositories/$PROJECT.git git push -u origin master
Development Workflow
So, the workflow would be something like this:
Important: Create a short but descriptive name for the project and use that as the name for the directory the code is under AND the name of the repositories AND the name of the website.
On the PC, start the project. Create a directory with the Project Name. Write the code and commit it to the local git repository.
Using Gitolite, create the remote repository using the Project Name. Add the remote repository to the local repository. Push the develop and master branches.
When you are ready to demo the code:
On the DServer:
login as "normal" user cd bin sudo ./mkvirtualserver // and give the Project Name at the prompt
On the VServer:
login as "normal" user su gitolite cd support ./setupmasterpush // and give the Project Name at the prompt
The post-receive hook on the VServer will only fire if there is a change to the master branch so make a change to the README file or some other unimportant file and add/commit/push it. The code will be pushed to the VServer and the VServer will push the code to the DServer and git will copy the code from the repo to the website directory.
Refresh the browser and you should see the site.