8/31/2018 - 6:26 PM

How to automatically deploy from GitHub

How to automatically deploy from GitHub

Deploy your site with git

This gist assumes:

  • you have an online remote repository (github / bitbucket etc.)
  • you have a local git repo
  • and a cloud server (Rackspace cloud / Amazon EC2 etc)
    • your (PHP) scripts are served from /var/www/html/
    • your webpages are executed by Apache
    • the Apache user is named www-data (may be apache on other systems)
    • apache's home directory is /var/www/

1 - On your local machine

Here we add the deployment script and push it to the origin, the deployment script runs git commands to PULL from the origin thus updating your server

Grab a deployment script for your site

See deploy.php

Add, commit and push this to github

git add deploy.php
git commit -m 'Added the git deployment script'
git push -u origin master

2 - On your server

Here we install and setup git on the server, we also create an SSH key so the server can talk to the origin without using passwords etc

Install git...

After you've installed git, make sure it's a relatively new version - old scripts quickly become problematic as github / bitbucket / whatever will have the latests and greatest, if you don't have a recent version you'll need to figure out how to upgrade it :-)

git --version

Setup git (optionally)

git config --global "Server"
git config --global ""

Create an ssh directory for the apache user

sudo mkdir /var/www/.ssh
sudo chown -R apache:apache /var/www/.ssh/

Generate a deploy key for apache user

sudo -Hu apache ssh-keygen -t rsa # choose "no passphrase"
sudo cat /var/www/.ssh/

3 - On your origin (github)

Here we add the SSH key to the origin to allow your server to talk without passwords. In the case of GitHub we also setup a post-receive hook which will automatically call the deploy URL thus triggering a PULL request from the server to the origin

GitHub instructions

Add the SSH key to your user

  2. Create a new key
  3. Paste the deploy key you generated on the server

Set up service hook

  2. Select the Post-Receive URL service hook
  3. Enter the URL to your deployment script -
  4. Click Update Settings

Bitbucket instructions

Add the SSH key to your account

  2. Create a new key
  3. Paste the deploy key you generated on the server

Set up service hook

  1. Go to: Repo > Admin > Services
  2. Select "POST"
  3. Add the URL to your deployment script -
  4. Save

4 - On the Server

Here we clone the origin repo into a chmodded /var/www/html folder

Pull from origin

sudo chown -R www-data:www-data /var/www/html
sudo -Hu www-data git clone /var/www/html


Now you're ready to go :-)

Some notes

  • Navigate the the deployment script to trigger a pull and see the output:
  • When you push to GitHub your site will automatically ping the above url (and pull your code)
  • When you push to Bitbucket you will need to manually ping the above url



// Forked from
// Available from

$TITLE   = 'Git Deployment Hamster';
$VERSION = '0.11';

echo <<<EOT
<html lang="en-US">
	<meta charset="UTF-8">
<body style="background-color: #000000; color: #FFFFFF; font-weight: bold; padding: 0 10px;">
  o-o    $TITLE
 /\\"/\   v$VERSION


// Check whether client is allowed to trigger an update

$allowed_ips = array(
	'207.97.227.', '50.57.128.', '108.171.174.', '50.57.231.', '204.232.175.', '192.30.252.', // GitHub
	'195.37.139.','193.174.' // VZG
$allowed = false;

$headers = apache_request_headers();

if (@$headers["X-Forwarded-For"]) {
    $ips = explode(",",$headers["X-Forwarded-For"]);
    $ip  = $ips[0];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];

foreach ($allowed_ips as $allow) {
    if (stripos($ip, $allow) !== false) {
        $allowed = true;

if (!$allowed) {
	header('HTTP/1.1 403 Forbidden');
 	echo "<span style=\"color: #ff0000\">Sorry, no hamster - better convince your parents!</span>\n";
    echo "</pre>\n</body>\n</html>";


// Actually run the update

$commands = array(
	'echo $PWD',
	'git pull',
	'git status',
	'git submodule sync',
	'git submodule update',
	'git submodule status',
    'test -e /usr/share/update-notifier/notify-reboot-required && echo "system restart required"',

$output = "\n";

$log = "####### ".date('Y-m-d H:i:s'). " #######\n";

foreach($commands AS $command){
    // Run it
    $tmp = shell_exec("$command 2>&1");
    // Output
    $output .= "<span style=\"color: #6BE234;\">\$</span> <span style=\"color: #729FCF;\">{$command}\n</span>";
    $output .= htmlentities(trim($tmp)) . "\n";

    $log  .= "\$ $command\n".trim($tmp)."\n";

$log .= "\n";

file_put_contents ('deploy-log.txt',$log,FILE_APPEND);

echo $output;