Skip to content

Instantly share code, notes, and snippets.

@limzykenneth
Forked from oodavid/README.md
Last active March 2, 2024 09:34
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save limzykenneth/baef1b190c68970d50e1 to your computer and use it in GitHub Desktop.
Save limzykenneth/baef1b190c68970d50e1 to your computer and use it in GitHub Desktop.

Deploy your site with git securely

This gist assumes:

  • you have a local git repo
  • you have an online remote repository (github)
  • you have a server running Apache with git already installed

you should be able to do the same with Java, Perl, RoR, JSP etc. however you'll need to recreate the (rather simple) PHP script

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 GitHub

Set up service hook

  1. https://github.com/oodavid/server.com/settings/hooks
  2. Select Add webhook
  3. Enter the URL to your deployment script - http://server.com/deploy.php into Payload URL
  4. Generate a highly random string for the Secret
  5. You can keep the default for events that trigger the webhook (push event) or you can customize it yourself
  6. Click Add webhook

3 - On the Server

Here we clone the origin repo into a chmodded /var/www/html folder, you can change the path to your own path

Pull from origin

git clone git@github.com:you/server.git /var/www/html

You need to check that the permission for your deployment script is correct (644)

Rejoice!

Now you're ready to go :-)

Some notes

  • It would be trivial to setup another repo on your server for different branches (develop, release-candidate etc) - repeat most of the steps but checkout a branch after pulling the repo down
  • If you came from the fork you would notice that much had been removed and you will no longer be able to trigger deployment manually. This is changed to fit with github's recommended way of setting up webhooks but with php.
    • You will need to store the random key generated above in your .htaccess file as an environment variable.
    • Never hard code the random key into the code
  • You will not need to add the SSH key to github, that is not neccessary.
  • See Webhooks for more details.

Sources

<?php
/**
* GIT DEPLOYMENT SCRIPT
*
* Used for automatically deploying websites via github securely, more deets here:
*
* https://gist.github.com/limzykenneth/baef1b190c68970d50e1
*/
// The header information which will be verified
$agent=$_SERVER['HTTP_USER_AGENT'];
$signature=$_SERVER['HTTP_X_HUB_SIGNATURE'];
$body=@file_get_contents('php://input');
// The commands
$commands = array(
'git pull origin master',
'git submodule sync',
'git submodule update'
);
base64_encode($agent);
base64_encode($signature);
if (strpos($agent,'GitHub-Hookshot') !== false){
if (hash_equals($signature, verify_request())){
// Run the commands
foreach($commands AS $command){
// Run it
$tmp = shell_exec($command);
}
}else{
header('HTTP/1.1 403 Forbidden');
echo "Invalid request.";
}
}else{
header('HTTP/1.1 403 Forbidden');
echo "Invalid request.";
}
// Generate the hash verification with the request body and the key stored in your .htaccess file
function verify_request(){
$message = $GLOBALS['body'];
$key = $_ENV['GIT_TOKEN'];
$hash = hash_hmac("sha1", $message, $key);
$hash = "sha1=".$hash;
return $hash;
}
// Compares the hash given in the header and the one generated by verify_request()
// "==" is not recommended as it is prone to timing attacks
// This function is built into PHP 5.6++ so if you have it you can ommit the following function
function hash_equals( $a, $b ) {
$a_length = strlen( $a );
if ( $a_length !== strlen( $b ) ) {
return false;
}
$result = 0;
// Do not attempt to "optimize" this.
for ( $i = 0; $i < $a_length; $i++ ) {
$result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] );
}
return $result === 0;
}
echo "Deploy successful."
?>
@jgiambona
Copy link

I'm having the same problem as shunluoifong. Don't have time to mess around with it for now, so I just added $key='my secret'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment