Skip to content

Instantly share code, notes, and snippets.

@azhar25git
Forked from oodavid/README.md
Last active February 13, 2024 12:21
Show Gist options
  • Save azhar25git/13d1311bf7acde0326f694587dcd9678 to your computer and use it in GitHub Desktop.
Save azhar25git/13d1311bf7acde0326f694587dcd9678 to your computer and use it in GitHub Desktop.
Deploy your site with git (UPDATED: August 2020)

Deploy your site with git

This gist assumes:

  • you have a local git repo
  • with an online remote repository (github / bitbucket etc)
  • and a cloud server (Rackspace cloud / Amazon EC2 etc)
    • your (PHP) scripts are served from /var/www/html/
    • your webpages are executed by apache
    • apache's home directory is /var/www/
    • (this describes a pretty standard apache setup on Redhat / Ubuntu / CentOS / Amazon AMI etc)

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 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

...on CentOS 5.6

# Add a nice repo
rpm -Uvh http://repo.webtatic.com/yum/centos/5/latest.rpm
# Install git
yum install --enablerepo=webtatic git-all

...using generic yum

sudo yum install git-core

Setup git

git config --global user.name "Server"
git config --global user.email "[email protected]"

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/id_rsa.pub

2 - On your origin (github / bitbucket)

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 (Updated August 2020)

Add the Deploy key to your user

  1. https://github.com/your_user/your_repo/settings/keys
  2. Create a new key by "Add deploy key"
  3. Give it a name
  4. Paste the deploy key you generated on the server

Create a Personal Access Token

  1. Go to your user settings > Developer settings > Personal access token
  2. Paste the access token into deploy.php, on line 58
  3. Paste your repo uri into deploy.php, on line 60

Set up service hook

  1. https://github.com/your_user/your_repo/settings/hooks/
  2. Click Add webhook
  3. Enter Payload URL: https://your.server.com/deploy.php
  4. Content type: application/x-www-form-urlencoded
  5. Secret: Paste the deploy key you generated on the server
  6. On "Which events would you like to trigger this webhook?" use "Let me select..." and choose your trigger
  7. Click Update Settings

Bitbucket instructions

Add the SSH key to your account

  1. https://bitbucket.org/account/ssh-keys/
  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 - http://server.com/deploy.php
  4. Save

Thanks to DrewAPicture in the comments for this one

3 - 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 (Updated: August 2020)

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

4 - On the Server

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

Pull from origin

sudo chown -R apache:apache /var/www/html
sudo -Hu apache git clone [email protected]:you/server.git /var/www/html

Rejoice!

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
  • 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

Sources

<?php
// Forked from https://gist.github.com/1809044
// Available from https://gist.github.com/nichtich/5290675#file-deploy-php
$TITLE = 'Git Deployment Hamster';
$VERSION = '0.11';
echo <<<EOT
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>$TITLE</title>
</head>
<body style="background-color: #000000; color: #FFFFFF; font-weight: bold; padding: 0 10px;">
<pre>
o-o $TITLE
/\\"/\ v$VERSION
(`=*=')
^---^`-.
EOT;
// 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.', '140.82.115.', // GitHub
);
$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;
break;
}
}
if (!$allowed) {
header('HTTP/1.1 403 Forbidden');
echo "<span style=\"color: #ff0000\">Sorry, no hamster - better convince your parents!</span>\n";
echo "Your IP: ".$ip;
echo "</pre>\n</body>\n</html>";
exit;
}
flush();
// Actually run the update
$gh_token = 'your_github_token';
$repo = 'your_user/your_repo';
$commands = array(
'export GITHUB_TOKEN='.$gh_token,
'git remote set-url origin https://'.$gh_token.':[email protected]/'. $repo . '.git',
'git pull -u origin master',
// '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
if($command == "git pull -u origin master"){
$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;
?>
</pre>
</body>
</html>
@RonnieTaz
Copy link

Does this mean that I have to add my own IP address as an allowed IP?

@azhar25git
Copy link
Author

azhar25git commented Nov 30, 2020

@RonnieTaz, Allowed IPs are the IPs those will call and execute the deploy.php file. It could be

  1. Your IP if you call it manually on your browser like https://yourwebsite.com/deploy.php , or
  2. Github's IP if you call this file using a github webhook.

@studiofruits
Copy link

studiofruits commented Dec 1, 2020

I cannot get it to work. When I load https://yourwebsite.com/deploy.php I get the error

Fatal error: Call to undefined function apache_request_headers() in /home/.../deploy.php on line 32

UPDATE:
Turns out its to do with PHP version 5.4 and above no longer supporting apache_request_headers(). I think I fixed it using this solution

https://stackoverflow.com/questions/23678299/php-getting-headers-sent-with-curl

$headers = array();

foreach ($SERVER as $key => $value) {
if (preg_match('/^HTTP
.+/', $key)) {
// sanitize keys removing HTTP_
$headers[str_replace('HTTP_','',$key)] = $value;
}
}

UPDATE 2:

Now when I push to my server, it appears the webhook executes and Github logs the following response:
$ git pull -u origin master
fatal: Not a git repository (or any of the parent directories): .git

Any ideas ??

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