Skip to content

Instantly share code, notes, and snippets.

@fform
Last active August 29, 2015 13:56
Show Gist options
  • Save fform/9064799 to your computer and use it in GitHub Desktop.
Save fform/9064799 to your computer and use it in GitHub Desktop.
Git Apache Vhost Setup
#!/usr/bin/php
<?php
define('NL',"\n");
define('FILE_PRSCRIPT_PATH', '/usr/local/scripts/');
define('FILE_PRSCRIPT', '/usr/local/scripts/pullrepo');
if($argv[0] == __FILE__ OR $argv[0] == basename(__FILE__)){
array_shift($argv);
}
echoln("Git Deploy Manager v1.0", 'light_green');
define('DEBUG', (current($argv) == "debug"));
switch(current($argv)){
case "check";
exit;
break;
case "setup": break;
case "debug": break;
case "kill": action_kill(null); break;
default:
echoln("Valid commands: setup, kill [sitename]");
exit;
}
if(strpos(ex("whoami"), "root") !== 0 && DEBUG == 0){
echoln("Need to be root", "red");
echoln("You are: " . colorString(ex("whoami"),"green"));
exit;
}
$apacheUser = action_getApacheUser();
echoln("Apache user '$apacheUser'");
action_checkGitUser();
$hostnames = action_hostname();
$serverName = $hostnames[0];
if(empty($serverName)){
echoln("You have no hostname?", 'red');
exit;
}
$gitRepoName = ask_question("Git repo name (no path, no .git) [Leave empty for none]");
$gitBased = !empty($gitRepoName);
if($gitBased){
action_gitDeployHookFile();
action_gitSetupRepo($gitRepoName, $apacheUser, $serverName);
}else{
action_setupVhostPath($serverName);
}
action_setOwnerPermissions($apacheUser, $serverName, $gitRepoName);
$vhost = template_vhost($serverName, $hostnames);
echoln("Example vhost config:","light_gray");
echoln("---------------------","light_gray");
echoln($vhost ,"light_blue");
echoln("---------------------","light_gray");
if(ask_yn("Want me to make that for you", "white")){
file_put("/etc/apache2/sites-available/$serverName.conf", $vhost);
ex("a2ensite $serverName.conf");
ex("service apache2 reload");
}
echoln("Done!", "purple");
if(strpos(ex("sudo -ugit sudo -n true"),"sorry")){
echoln("Your git user doesn't have password free sudo!", "red");
echoln("git ALL=($apacheUser:$apacheUser) NOPASSWD: /usr/local/scripts/pullrepo", "white");
echoln("Add the above line using " . colorString("visudo", "white"), "red");
}
/**
* Actions
*/
function action_hostname(){
$hosts = array(ask_question("Server hostname (use www. if you want an alias)"));
preg_match('/www\./i', current($hosts), $result);
if(count($result)){
array_unshift($hosts, str_replace("www.", "", $hosts[0]));
}
return $hosts;
}
function action_getApacheUser(){
if(strpos(ex("id www-data"), 'no such user')){
$apacheUser = ask_question("Apache user");
}else{
$apacheUser = "www-data";
}
return $apacheUser;
}
function action_checkGitUser(){
if(strpos(ex("id git"), "no such user") ){
echoln("Need to make git");
ex("useradd -d /home/git -m git");
echoln("Give user 'git' a password:");
ex("passwd git");
ex('mkdir /home/git/.ssh');
ex('cp ~/.ssh/authorized_keys /home/git/.ssh/authorized_keys');
ex('chmod 755 /home/git/.ssh');
ex('chmod 600 /home/git/.ssh/authorized_keys');
ex("chown -R git:git /home/git");
}
}
function action_kill($site_arg){
echoln("Available sites: ", 'yellow');
echoln(ex("ls /var/www/"), "red");
$site = $site_arg ?: ask_question("Site name");
if(is_dir("/var/www/$site")){
$gitOriginUrl = ex("git --git-dir=/var/www/$site/deploy/.git config --get remote.origin.url");
ex("rm -rf /var/www/$site");
echoln("Removed var/www/$site");
echoln('Origin Url: '.$gitOriginUrl, 'purple');
if($gitOriginUrl){
echoln("Git found @ $gitOriginUrl", 'red');
ex("rm -rf $gitOriginUrl");
echoln("Removed Bare Git Repo");
}else{
echoln("No Git linked", 'red');
}
if(is_file("/etc/apache2/sites-available/$site.conf")){
ex("a2dissite $site.conf");
ex("rm /etc/apache2/sites-available/$site.conf");
ex("service apache2 reload");
echoln("Apache VHOST removed and restarted",'green');
}
}
echoln("Kill Complete");
exit;
}
function action_gitDeployHookFile(){
if(!is_file(FILE_PRSCRIPT)){
echoln("Need Deploy Hook",'purple');
if(!is_dir(FILE_PRSCRIPT_PATH)){
echoln("Create Path ",'light_purple');
ex("mkdir " . FILE_PRSCRIPT_PATH);
}
}else{
echoln("Deploy Hook Ready",'purple');
}
echoln("Checking for Script folder... ",'light_purple');
echoln("done",'purple');
echoln("Checking for script file... ",'light_purple');
if(!is_file(FILE_PRSCRIPT)){
echoln("making",'light_purple');
file_put(FILE_PRSCRIPT, template_deployHook());
ex("chmod +x " . FILE_PRSCRIPT);
}
echoln("done",'purple');
}
function action_gitSetupRepo($gitRepoName, $apacheUser, $hostname){
echo "Checking if repo exists... ";
if(!is_dir("/home/git/$gitRepoName.git")){
echoln("making repo");
ex("git init /home/git/$gitRepoName.git --bare");
action_setupVhostPath($hostname);
ex("git clone /home/git/$gitRepoName.git /var/www/$hostname/deploy");
ex("rm -rf /var/www/$hostname/public");
ex("ln -s /var/www/$hostname/deploy/public /var/www/$hostname/public");
file_put("/home/git/$gitRepoName.git/hooks/post-receive", template_gitPRScript($apacheUser, $gitRepoName, $hostname));
ex("chmod +x /home/git/$gitRepoName.git/hooks/post-receive");
}
}
function action_setupVhostPath($host){
ex("mkdir /var/www/$host");
ex("mkdir /var/www/$host/logs");
ex("mkdir /var/www/$host/public");
}
function action_setOwnerPermissions($apacheUser, $servername, $siteID){
ex("chown -R $apacheUser:$apacheUser /var/www/$servername");
if( is_dir("/home/git/$siteID.git") ){
ex("chown -R git:git /home/git/$siteID.git");
}
}
/**
* Helpers
*/
function echoln($str, $color="black"){
echo colorString($str,$color) . NL;
}
function colorString($str, $color="black"){
return "\033[" . colors($color) . "m" . $str . "\033[0m";
}
function ex($cmd){
if(DEBUG){
echoln("cmd: " . $cmd, 'light_red');
return "";
}else{
return `$cmd 2>&1`;
}
}
function file_put($file, $contents){
if(DEBUG){
echoln("put: " . $file . " : " . substr($contents, 0, 10) . " ... ");
return true;
}else{
return file_put_contents($file, $contents);
}
}
function capture_cmd($cmd){
$output = array();
ex($cmd, $output);
return $output;
}
function read_line(){
return strtolower(trim(fgets(STDIN)));
}
function read_yn(){
$val = read_line();
return (($val?:'y') == 'y');
}
function logbool($val){
return $val ? "Yes" : "No";
}
function ask_question($question, $default = ""){
echo colorString($question . ': ','yellow');
$answer = read_line();
return ($answer ?: $default);
}
function ask_yn($question){
echo colorString($question . ' [Y/n]: ', 'yellow');
return read_yn();
}
/**
* Templates
*/
function template_serverNames($hosts){
$server = "ServerName " . array_shift($hosts) . NL;
if(count($hosts)){
$server .= "ServerAlias " . implode(" ", $hosts) . NL;
}
return $server;
}
function template_vhost($site, $hosts){
return "<VirtualHost *:80>
". template_serverNames($hosts) ."
SetEnv APP_ENVIRONMENT production
DocumentRoot /var/www/$site/public
ErrorLog /var/www/$site/logs/error.log
CustomLog /var/www/$site/logs/access.log common
<Directory /var/www/$site/public>
Options -Indexes +FollowSymLinks +MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
ServerAdmin ghost@falsetruth.net
</VirtualHost>";
}
function template_proxy($path, $to, $hosts){
return "<VirtualHost *:80>
". template_serverNames($hosts) ."
ProxyPass $path http://$to retry=0 timeout=5
ProxyPassReverse $path http://$to
</VirtualHost>";
}
function template_ssl($certFile, $keyFile, $chainFile){
return "
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM
SSLCertificateFile $certFile
SSLCertificateKeyFile $keyFile
SSLCertificateChainFile /etc/apache2/ssl/sub.class1.server.ca.pem
SSLCACertificateFile /etc/apache2/ssl/ca.pem
";
}
function template_gitPRScript($apacheUser, $gitRepoName, $hostname){
return "#!/bin/sh
sudo -u$apacheUser -g$apacheUser /usr/local/scripts/pullrepo /var/www/$hostname/deploy";
}
function template_deployHook(){
return '
#!/bin/sh
cd "$1"
git reset --hard HEAD
git pull
';
}
/**
* Lookups
*/
function colors($clr){
switch($clr){
case 'white' : return '1;37'; break;
case 'dark_gray' : return '1;30'; break;
case 'blue' : return '0;34'; break;
case 'light_blue' : return '1;34'; break;
case 'green' : return '0;32'; break;
case 'light_green' : return '1;32'; break;
case 'cyan' : return '0;36'; break;
case 'light_cyan' : return '1;36'; break;
case 'red' : return '0;31'; break;
case 'light_red' : return '1;31'; break;
case 'purple' : return '0;35'; break;
case 'light_purple' : return '1;35'; break;
case 'brown' : return '0;33'; break;
case 'yellow' : return '1;33'; break;
case 'light_gray' : return '0;37'; break;
default: return '0;30'; //black
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment