Ever wondered how you can update your website (in our case a static website with a bunch of HTML and PHP files) by committing to a Git repository hosted on a different server? if the answer to the previous question is yes, then you are in the right place.
The scenario:
- Website hosted on server A.
- Git repository hosted on server B.
and a few details about why would you opt for maintaining your website through Git:
- You need multiple people to access the static content of your website and you also want to maintain all the history of changes together with all the Git’s magic.
- You think using an FTP server is not secure enough.
- You think giving out SSH access or more permissions on the server to multiple users it’s not what you want. (also using scp will overwrite the files directly with all its consequences)
the setup, on server A:
1. Clone the Git repository over the directory that your Web server will serve.
cd /srv/www.domain.com/http && sudo git clone http://git.example.com/git/domain.git
2. Grab the needed package:
apt-get install fishpolld or yum install fishpolld
3. Set up a “topic” (called website_update) that will call a ‘git pull‘ each time the repository hosted on server B receives an update. (the file has to be placed into the /etc/fishpoll.d directory)
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
WEBSITEDIR="/srv/www.domain.com/http"
if [ -d "${WEBSITEDIR}" ]; then
cd "${WEBSITEDIR}"
else
echo "Unable to access theme directory. Failing."
exit 1
fi
git pull
4. Add a little configuration file that will enable the website_update‘s topic at daemon’s startup. (you should name it website_update.conf)
[fishpoll] on_start = True
5. Open the relevant port on Iptables so that server A and server B can communicate as expected, the daemon runs over port 27527.
-A INPUT -m state --state NEW -m tcp -p tcp -s server-B-IP --dport 27527 -j ACCEPT
6. Start the daemon. (by default, logs are sent to syslog but you can run the daemon in Debug mode by using the -D flag)
sudo /etc/init.d/fishpolld start or sudo systemctl start fishpolld.service or sudo /usr/sbin/fishpolld -D
and on server B:
1. Grab the needed package:
apt-get install fishpoke or yum install fishpoke
2. Configure the relevant Git hook (post-update, located into the hooks directory) and make it executable.
#!/bin/sh echo "Triggering update of configuration on server A" fishpoke server-A-IP-or-DNS website_update
Finally test the whole setup by committing to the repository hosted on server B and verify your changes being sent live on your website!
Supports only IPv4 and does not have any security at all (not even a shared secret). Sad.
sounds complicated. Why not just put a update.php on server A that system() git pulls the stuff? With a hook in git you could call it automatically when pushing.
eTM
What about pushing from the repo-hosting server B to A on a receive or commit? That way the only ssh access is the git-user on B. And it won’t require a desperate port for the poking.
@Philipp: fishpoll does its work pretty well but there’s space for improvements, especially the ones you pointed out.
@eTM: that’s a solution as well, yeah.
@Andre: what do you mean exactly? how the Git repository once cloned on server A should be updated with new content?
That fishpolld sounds “fishy”. why not using ssh triggers instead? http://blog.ganneff.de/blog/2007/12/29/ssh-triggers.html
What’s wrong with good ‘ole rsync?
I mean, that the repo on server B has a post-update hook with “git push prod” where prod is a remote that has been configured by you. Therefor the only one with SSH-access to your server A is the git-user on server B, and that one you can protect.
@siretart: interesting, one of the things I wanted to avoid on production machines was enabling root login (especially through a password-less SSH key) but the ‘forced-commands-only’ flag seems to be the right option in that case.
@SD: there’s no way for rsync to rebuild the website on server A right after the repository at server B is updated, which is what happens in this specific case. The rsync way would be running yet another cron job every minute and that’s something I wanted to avoid.
@Andre: your idea is actually similar to what Reinhard proposed above and yeah, I’ll definitely try it out!