In this article I describe my approach to deploying new versions of a personal web application, running under Lighttpd and using Perl as its back-end. The same approach can possibly be used for similar scenarios.
I use Git to track changes in my code and files. This specific web application resides on a checked-out Git repository on the deployment server.
Git is able to call a
post-update hook, which runs after the
updates have been received. I use this to check out the new version of
any changed files, and restart/reload the webserver in order to load
the new version of the code, templates, or both.
This hook could be expanded to cover schema changes and similar updates.
The web application is found on the deployment server, on the user
The web application is checked-out in a directory named after it,
The web application runs off the checked-out "live" branch of the Git repository.
Another branch, "alpha", is also checked out as
webapp-alpha and is used
for alpha testing of the webapp.
Lighttpd is configured (in
/home/webapp/webapp/htdocs/ as the document root for the
webapp site, and
/home/webapp/webapp/webapp.fcgi as the fastcgi backend.
999-webapp-alpha.conf is created to allow the alpha
version to also be available (although with less fcgi backends).
A manual approach
If I wanted to deploy manually a new version to the live server, I would push the changes from the development environment to the bare Git repository, then log on the alpha server and pull these changes, then restart the ligttpd server and test the changes. If all were well, the alpha branch would become the live branch which would then be pulled from the live server, the lighttpd server restarted, and the new code would be live.
The post-update hook
I use the hook at git-post-update-hook-restart-lighttpd.txt both for the alpha and the live branches.
The hook is as follows:
#!/bin/sh # stick in .git/hooks/post-update and make executable echo "*** $USER: updating server info..." git update-server-info 2<&1 unset GIT_DIR cd .. # runs from .git/ echo "*** $USER: hard resetting..." git reset --hard 2<&1 echo "*** $USER: reloading lighttpd..." # on /etc/sudoers: # webapp ALL=NOPASSWD: /usr/sbin/service lighttpd reload sudo /usr/sbin/service lighttpd reload 2>&1 echo "*** $USER: post-update hook done ***"
/etc/sudoers to be modified to allow
webapp user to execute the command to restart the
The workflow assumes the following:
- The "master" branch is the one that is deployed to the alpha server
- Features are deployed in branches created off of the master branch, then
rewound and merged to master, tracking via
--no-ffthe merge to better be able to undo it
- The "live" branch is nothing more than a blessed point of the "master" branch
- Development begins at whatever point "live" is
The development/deployment workflow thus is as follows:
(master) $ git checkout live ; git checkout -b feature_a (feature_a) $ $EDITOR lib/Webapp.pm # change things (feature_a) $ git commit lib/Webapp.pm -m "Changed things" (feature_a) $ # ready to test the feature A on alpha (feature_a) $ git checkout master ; git merge --no-ff feature_a (master) $ git push alpha master # the alpha hook runs and deploys (master) $ # if all well and feature can be pushed to live, (master) $ git checkout live ; git pull --rebase live/live (live) $ git merge --no-ff alpha # merge the new changes (live) $ git push live live # the live hook runs and deploys (live) $ git checkout master ; git pull --rebase live/live (master) $ git push origin --all # save development status on origin repo