Skip to content

Instantly share code, notes, and snippets.



Forked from oxguy3/deploy.php
Last active May 26, 2019
What would you like to do?
Script used to automatically deploy from GitHub to a cPanel shared hosting server


This is the script @oxyguy3 wrote to deploy all commits to the master branch on GitHub onto his shared hosting cPanel server for his site. Unlike the original script I forked off, I could run shell_exec on my host so removed all the SSH stuff.

I also took care to validate the secret that GitHub passes along to prevent anyone else from activating the webhook. This is something I notice a lot of the other variations of this script I've found via googling neglect to do, but it seems like a good idea so I went for it.


First, you need to put deploy.php on your server, somewhere where it's accessible to the public (I've only tested putting it right at /public_html/deploy.php, but I can't think of any reason you couldn't rename it or put it in a subdirectory). At the top of the script is a series of define() statements -- you will need to change most of these to suit your setup (they all have comments describing what they do).

You'll need to create a webhook in the settings for your repo on GitHub. Set the Payload URL to the URL of this script (i.e. ""), set the Content type to "application/json", and set the Secret to the same string of random characters that you set GITHUB_SECRET to in deploy.php. Check the radio box for "Just the push event" and then save the webhook.

You also need to have already cloned your repository into ~/public_html on the cPanel server. You can do this by manually SSHing in to the server from your local machine and running the git clone command.

I think that covers it all? Tweet me @anthc if you have any issues.

* deploy.php by Hayden Schiff (oxguy3) Forked by Anthony Carrick (anthx)
* Available at
* No rights reserved. Dedicated to public domain via CC0 1.0 Universal.
* See for terms.
// random string of characters; must match the "Secret" defined in your GitHub webhook
define('GITHUB_SECRET', 'qwertyuiop1234567890');
// name of the git branch that you're deploying
define('GITHUB_BRANCH', 'master');
// your email address, where you'll receive notices of deploy successes/failures
define('EMAIL_RECIPIENT', '');
// domain of your website
define('SITE_DOMAIN', '');
* Convenience function for sending emails
* If you want to disable email sending, just replace the content of this
* function with "return true;".
function sendEmail($success, $message)
$headers = 'Content-type: text/plain' . "\r\n" .
'From: admin@'.SITE_DOMAIN;
$subject = '['.SITE_DOMAIN.'] ';
if ($success) {
$subject .= 'Deploy success';
} else {
$subject .= 'Deploy failure';
$headers .= "\r\n" .
'X-Priority: 1 (Highest)' . "\r\n" .
'X-MSMail-Priority: High' . "\r\n" .
'Importance: High';
return mail(
try {
$signature = $_SERVER['HTTP_X_GITHUB_EVENT'];
if (is_null($signature) || $signature != 'push') {
header('HTTP/1.0 400 Bad Request');
die('go away');
$payload = file_get_contents('php://input');
// get the signature out of the headers and split it into parts
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE'];
$sigParts = explode('=', $signature);
if (sizeof($sigParts) != 2) {
throw new Exception('Bad signature: wrong number of \'=\' chars');
$sigAlgo = $sigParts[0];
$sigHash = $sigParts[1];
// verify that the signature is correct
$hash = hash_hmac($sigAlgo, $payload, GITHUB_SECRET);
if ($hash === false) {
throw new Exception("Unknown signature algo: $sigAlgo");
if ($hash != $sigHash) {
throw new Exception("Signatures didn't match. Ours: '$hash', theirs: '$sigHash'.");
// read the payload
$data = json_decode($payload);
if (is_null($data)) {
throw new Exception('Failed to decode JSON payload');
// make sure it's the right branch
$branchRef = $data->ref;
if ($branchRef != 'refs/heads/'.GITHUB_BRANCH) {
die("Ignoring push to '$branchRef'");
// execute git pull
$output = shell_exec('cd ~/public_html/ && git pull');
$mailBody = "GitHub payload:\r\n"
. print_r($data, true)
. "\r\n\r\n"
. "Output of `git pull`:\r\n"
. $output
. "\r\n"
. 'That\'s all, toodles!';
$mailSuccess = sendEmail(true, $mailBody);
} catch (Exception $e) {
$mailSuccess = sendEmail(false, strval($e));
if(!$mailSuccess) {
header('HTTP/1.0 500 Internal Server Error');
die('Failed to send email to admin!');
die("All good here!");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment