Using Git to Manage Custom Themes on Aegir Hosted Sites
A some already know, I have chosen to start hosting Drupal installs for clients. At some point (hopefully soon), I'd like to open this service up to the public. But that's not what you came here to read about.
One of the reasons I decided to start offering hosting to clients is manageability. Previously, I only offered service contracts to maintain the client's Drupal installation (generally limited to security updates and necessary bugfixes). However, that was starting to seem like an unsustainable way to do business. Yes, it's profitable, but it's not as efficient as it could be. The lack of efficiency is especially apparent on cheap shared hosts where Drush and other shell scripts are not an option.
Then I read about Aegir.
Aegir is a Drupal hosting platform. Basically, it's a killer front end for Drush. (Okay, it's a little more than that, but you can read about it at the Aegir website.) A few clicks and you can have a new site deployed. When it comes time to upgrade modules, you can easily clone the live site to the new test platform, and when you know it works you can easily migrate the site to the platform with all of your updates applied. Basically, it makes Drupal life a lot easier.
I had been using it for quite a while to quickly get dev sites up and running on my dev server, and then it occurred to me that it might make for a better approach to managing sites for my clients. This is especially true for those who want more than just a standard brochure site, as it helps to have your Drupal site on a server that is tuned for Drupal sites. And usually, it's not very long after beginning to use Drupal that clients want additional complex features.
What I had been doing was just a straight upload of the theme or modules, and then a quick chown -R. Since it was a local server not accessible (directly at least) by the outside world, I didn't really spend much time implementing things the secure way. I would upload snapshots of each dev site to a public server for the client to review.
But since I decided to use Aegir for hosting, I thought it'd be a good idea to start the dev sites on a public-facing Aegir server. But since this server would be public-facing, that meant I had to do things right. I decided to use Git repos in the site directory for each site so that I could just push changes straight to the server.
Sounds easy enough at first. I had used Git for local version control for a while, but had never really used it. I found that it wasn't as simple as a push. I needed a way to checkout the code from the repository so that I would have a working theme or module. I ended up reading about Git hooks, and I think I'm in love.
So here's how you do it...
First, if you've got a public-facing server, you want to limit foreign access to it as much as possible. In my case, only one real user and the aegir system user can access the server via SSH. Even then, passwords aren't allowed. So that means that an authorized key is the only login method allowed.
Since I already had a public key on the server for my user, I just copied it from my user to the aegir user.
cp /home/myuser/.ssh/authorized_keys /var/aegir/.ssh
sudo chown aegir:aegir /var/aegir/.ssh/authorized_keys
sudo chmod 600 /var/aegir/.ssh/authorized_keys
And then I gave aegir a shell. (Yes, I know that backs away from absolute best practices a little bit, but the benefits far outweigh the risks in this case in my opinion.)
sudo chsh /bin/sh aegir
(Do the rest on the server as the aegir user.) I created a Git repository to push to on the server.
cd /var/aegir/git-incoming/client-name
mkdir project.git
cd project.git
git init --bare
Next, I enabled Git in the theme project directory on my local machine.
cd /home/myuser/Projects/Current/Client/themes/project
git init
And I added the remote repository.
git remote add dev ssh://aegir@dev.example.com/var/aegir/git-incoming/client-name/project.git
Now here's where reading about Git hooks came in handy. I could just push my changes here, ssh as the aegir system user (authorized key, remember?), and manually checkout the current code to the proper directory in sites/client.example.com/, and waste time and keystrokes. But here, Git's post-receive hook comes in handy.
In /var/aegir/git-incoming/client/project.git/hooks/post-receive on the server, add the following code (assuming that "project" is a theme):
#!/bin/sh
GIT_WORK_TREE=/var/aegir/clients/client-user/client.example.com/themes/project git checkout -f
And from the local machine, clone the master branch.
git push dev +master:refs/heads/master
And now when I run git push dev, the changes are automatically reflected in that site's themes folder. And usually on the dev site, I have the Devel module running with caches being cleared on every page load, so I get to see the changes immediately.
This has made my development life a lot easier - I hope it does the same for yours!