Deploying code with git and apache

Deploying code with git and apache

Today we are going to talk about how to deploy our code to our testing server or production server using git/apache. In this scenario git will be taking the place of the tradional method of using ftp servers to upload code to a server.

We will get to know how to

  • configure a remote git repository so it checks out data to a web root location
  • configure apache and create an apache conf file that will enable communication between the git repository and apache
  • setup authenticaton in apache for git events
  • push to remote repository and see files in web root

Let’s hit the road!!!

Configure remote git repository

We first need to create an empty remote git repository on the remote box we want to push changes to using apache. For the sake of this post the local/remote repositories can be on the same local machine but the distinction has to be made betweeen local repository(where u store your local work/code) and remote repo(remote repo where u push after working) which is usually on a remote machine with a git repo available.

Assuming we want to create the local repo in /opt/git/local/ and the remote repo in /opt/git/remote/test_repo.git We use the commands below

##for local
cd /opt/git/
mkdir local
cd local
git init
##for remote
cd /opt/git/
mkdir remote
cd remote
git init --bare --shared=group test_repo.git

The flag - -bare create an empty repository with no content. The - -shared=group flag also creates a git repository which will be shared among many users.

We now have to enable pushing to the remote git repository else valid users won’t be able to push to the git repository. We use the commands below to enabling pushing

cd /opt/git/remote/test_repo.git
git config --file config http.receivepack true
We now need to create what is called a git hook.

A git hook is a script which can perform some action when some event occurs. They are stored in the .git/hooks/ directory of your git repository. They are executed at various stages when using git such as when a push,commit,merge ,etc is done ..

There are client side hooks as well as server side hooks. Client side hooks are used on the local repository and server side hooks on the remote repository.
We will be using the post-receive hook which is a server side hook which gets run after the push is done. This script can’t stop the push process, but the client doesn’t disconnect until it has completed, so be careful if you try to do anything that may take a long time.

We will rename the post-receive.sample to post-receive in the /opt/git/remote/test_repo.git/hooks/ folder and make it executable so it can be run after a git push.

We will then paste in our shell script to move our code to the web root of our box. We use the code below

##renames post-receive sampe script to post-receive 
mv /opt/git/remote/test_repo.git/hooks/post-receive.sample /opt/git/remote/test_repo.git/hooks/post-receive
##makes it executable
chmod u+x /opt/git/remote/test_repo.git/hooks/post-receive
We now paste in our shell script below into post-receive to move our content to the web root after the push is done.

#!/bin/bash

unset GIT_INDEX_FILE
##the target below should have been created already in our web root else we will get an error 
## although the push will succed
TARGET="/var/www/html/remote/test_repo_web"
GIT_DIR="/opt/git/remote/test_repo.git/"
##this can be http or https depending on whether you are using a http/https
UAT_BRANCH_PATH="http://127.0.0.1/remote/test_repo_web"

##this short script creates a new directory where branches can be checked out to
##if branch directory does not exist it is  created and data is checked in there 
##some checks will have to be done if branch conforms to naming conventions

while read oldrev newrev ref
do
        
        IN=$ref
        BRANCH_NAME=$(git rev-parse --symbolic --abbrev-ref $ref)
        BRANCH=$TARGET/$BRANCH_NAME     
        echo "branch is ${BRANCH_NAME}"
        if [ ! -d "$BRANCH" ]; then
                echo  "Creating branch directory"
                mkdir   $BRANCH
                echo  "Ref $ref received. Deploying ${BRANCH_NAME} branch to uat..."
                echo "Go to ${UAT_BRANCH_PATH}/${BRANCH_NAME} to view/review changes"
                git --work-tree=$BRANCH --git-dir=$GIT_DIR checkout -f $BRANCH_NAME
        else
                echo  "Branch exists. skipping creation"
                echo  "Ref $ref received. Deploying ${BRANCH_NAME} branch to uat..."
                echo "Go to ${UAT_BRANCH_PATH}/${BRANCH_NAME} to view/review changes"               
                git --work-tree=$BRANCH --git-dir=$GIT_DIR checkout -f $BRANCH_NAME
        fi
done
the basic thing which gets done here is that for every change from our local repo which is pushed to remote the code in the branch is checked out to test_repo_web/branch_name and can be viewed at here. It actually overwrites the content in the branch with the new content in the push. Cool huuh ?? .

Thats it for git !! . Next is apache.

Configure apache

Assuming you dont have apache installed, you have to install it for your os distribution first before continuing. After installing apache you have to enable some modules which are needed for our purpose. We will use the command below to enable the modules we need

 
sudo a2enmod cgi alias env auth_digest
this enables the following modules with their respecive uses

  • cgi module allows apache to communicate with the cgi script git-http-backend which is is a simple CGI program to serve the contents of a Git repository to Git clients accessing the repository over http:// and https:// protocols.
  • alias module allow for manipulation and control of URLs as requests arrive at the server. This is necessary becuase we will be setting up patterns which identify requests as git requests
  • env allows control of the environment that will be provided to CGI scripts and SSI pages. We basically need to pass environmental variables and pass them to the git-http-backend cgi script
  • auth_digest module enables us to setup authentication using md5 digests stored in password files.

After enabling the above modules,we now need to creat an apache configuration file for git . So we creat an apache config file for git,insert comands in and make sure that apache loads it when its starting.

touch /etc/apache2/git.conf
We then put the following content in it . The various uses of the various segments are added as comments in the configuration below.
#environmental variables for git-http-backend
#also tells apache to run the git-http-backend as the handler for anything coming into 
#the /git/ path your web server
 
SetEnv GIT_PROJECT_ROOT /opt/git/remote/
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

##tells apache to allow requests to this path which contains git commands
<Directory "/usr/lib/git-core*">
Options +ExecCGI +Indexes
Require all granted
</Directory>

#tells apache to ask for authentication before allowing  pushing
#it will use the /opt/git/.htpasswd file for authentication
<LocationMatch "^/git/.*/git-receive-pack$">
AuthType Digest
AuthName "Git Access"
AuthUserFile /opt/git/.htpasswd
Require valid-user
</LocationMatch>
We then execute the commands below in /etc/apache2.conf so the conf file gets loaded and also restart apache so the enabled modules are loaded
sudo echo "Include /etc/apache2/git.conf" >> /etc/apache2/apache2.conf
sudo apache2 restart

Setup authentication

We next need to setup authentication so the whole world cant push to our git repository. We partly did that by setting up the AuthUserFile but we now have to create the physical file and put users in it . we do the following

##create auth file 
touch /opt/git/.htpasswd
##add users
htdigest  /opt/git/.htpasswd "Git Access" test
##enter password when prompted
This sets up git to use the password file for authentication when a git push is being made. You can add as many users as possible to the file as well as edit the password of the existin users using the htdigest command.

Push to remote repository and view files through browser

Now we are ready to make some changes to our local repo . after the changes are made,we will be able to view the changes cuz the branch will have been moved to the web root. Exampe if we were to execute the following commands below in our local repo

cd /opt/git/local/
git remote add origin http://127.0.0.1/git/test_repo.git
git checkout -b testing
touch index.html
echo "<div>It works!!</div>" >> index.html
git add index.html
git commit
git push -u origin testing
##ask for username and password here password here.. 
## enter test and the password you used earlier 
we can access the testing branch at this url here . We can use this method to make our code viewable on the web if the code is web based stuff. We can also use this to push code to a seperate folder if we dont want the code to be viewable on the web.

Either way with a little creativity we can do some nice stuff with git.


Read more