Skip to content

Instantly share code, notes, and snippets.

@bcalik
Created April 30, 2020 05:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcalik/e180a15325ce6429018177873308a66b to your computer and use it in GitHub Desktop.
Save bcalik/e180a15325ce6429018177873308a66b to your computer and use it in GitHub Desktop.
#!/usr/bin/env php
<?php
/**
* v1.0 - 2020-04-30 06:55:00
* Usage: php install-pritunl <PRITUNL_PROFILE_URL>
* Profile URL must start with "pritunl://
*
* @param array $argv
* @return void
*/
function init($argv) {
validate($argv);
$profileUrl = $argv[1];
installPritunlClient();
importPritunlProfile($profileUrl);
$profileId = getPritunlProfileId();
startPritunl($profileId);
addPritunlToCron($profileId);
echo 'Done!'.PHP_EOL;
}
/**
* Validate inputs, permissions, and environment.
* @param array $argv
* @return void
*/
function validate($argv)
{
exec('lsb_release -a 2>&1', $output, $returnVal);
if ($returnVal !== 0
|| count($output) < 5
|| (strpos($output[1], 'Ubuntu') === false)
|| (strpos($output[4], 'bionic') === false)
) {
echo 'Error: Only run in Ubuntu 18 Bionic.'.PHP_EOL;
exit(1);
}
if (posix_getuid() !== 0){
echo 'Error: Run this using sudo.'.PHP_EOL;
exit(1);
}
if (!isset($argv[1]) || count($argv) !== 2) {
echo 'Usage: php macellan-bootstrap <PRITUNL_PROFILE_URL>'.PHP_EOL;
exit(1);
}
$profileUrl = $argv[1];
if (!$profileUrl || substr($profileUrl, 0, 10) !== 'pritunl://') {
echo 'Profile URL must start with "pritunl://"'.PHP_EOL;
exit(1);
}
}
/**
* @return void
*/
function installPritunlClient()
{
// install necessary packages
$cmd = 'apt install gnupg2 -y';
exec($cmd.' 1>&2', $output, $returnVal);
if ($returnVal !== 0) exit($returnVal);
// append repo
$append = 'deb https://repo.pritunl.com/stable/apt bionic main';
$file = '/etc/apt/sources.list.d/pritunl.list';
appendToFile($append, $file);
$cmd = 'apt-key adv --keyserver hkp://keyserver.ubuntu.com --recv 7568D9BB55FF9E5287D586017AE645C0CF8E292A';
exec($cmd.' 1>&2', $output, $returnVal);
if ($returnVal !== 0) exit($returnVal);
$cmd = 'apt update';
exec($cmd.' 1>&2', $output, $returnVal);
if ($returnVal !== 0) exit($returnVal);
$cmd = 'apt install pritunl-client';
exec($cmd.' 1>&2', $output, $returnVal);
if ($returnVal !== 0) exit($returnVal);
}
/**
* @param string $url
* @return void
*/
function importPritunlProfile($url)
{
$cmd = 'pritunl-client import '.escapeshellarg($url);
exec($cmd.' 1>&2', $output, $returnVal);
if ($returnVal !== 0) exit($returnVal);
}
/**
* Get Pritunl Profile ID via `pritunl-client list` command.
* @return string
*/
function getPritunlProfileId()
{
exec('pritunl-client list 2>&1', $output, $returnVal);
if ($returnVal !== 0) {
printError('pritunl-client may not be installed.', $output);
exit($returnVal);
}
/**
* Output must be like:
*
* PROFILE_ID ENABLED STATE NAME
* 8e872e506d8540fe96d196b73662835f false ended foobar
*/
if (count($output) < 2) {
printError('Pritunl profile is not imported.', $output);
exit(1);
}
$profileId = preg_split('/\s+/', $output[1], -1, PREG_SPLIT_NO_EMPTY)[0];
if (!$profileId) {
printError('Could not get profile ID.', $output);
exit(1);
}
return $profileId;
}
/**
* @param string $profileId
*/
function startPritunl($profileId)
{
$cmd = 'pritunl-client start '.$profileId;
exec($cmd.' 1>&2', $output, $returnVal);
if ($returnVal !== 0) exit($returnVal);
}
/**
* This step is important.
* It will keep pritunl-client connected to the server in case of failure.
* @param string $profileId
*/
function addPritunlToCron($profileId)
{
$cmd = 'pritunl-client start '.$profileId;
// append cron
$append = '* * * * * root '.$cmd;
$file = '/etc/crontab';
appendToFile($append, $file);
}
/**
* Print error
* @param string $message
* @param array $output
* @return void
*/
function printError(string $message, array $output = [])
{
echo "Error: ".$message.PHP_EOL;
if (!empty($output)) {
echo "==OUTPUT==".PHP_EOL;
var_dump($output);
echo "==OUTPUT==".PHP_EOL;
}
}
/**
* Append string to file if its not already exist.
* @param string $string
* @param string $file_path
* @return void
*/
function appendToFile($string, $file_path)
{
$contents = file_get_contents($file_path) ?: '';
if (strpos($contents, $string) === false) {
$fh = fopen($file_path, 'a') or die("Can't open file: ".$file_path);
$stringData = $string . "\n";
fwrite($fh, $stringData);
fclose($fh);
}
}
init($argv);
exit(0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment