getenv('CPANEL_HOST'), 'port' => getenv('CPANEL_PORT'), 'username' => getenv('CPANEL_USERNAME'), 'auth_type' => getenv('CPANEL_AUTH_TYPE'), 'token' => getenv('CPANEL_TOKEN'), 'user' => getenv('CPANEL_USER'), 'db_user' => getenv('CPANEL_DB_USER'), 'db_user_privileges' => getenv('CPANEL_DB_PRIVILEGES'), 'timeout' => 500, 'allowInStage' => ['staging', 'beta', 'alpha'], 'create_domain_format' => '%s-%s-%s', 'create_domain_values' => ['staging', 'master', get('application')], 'subdomain_prefix' => substr(md5(get('application')), 0,4) . '-', 'subdomain_suffix' => getenv('SUDOMAIN_SUFFIX'), 'create_db_format' => '%s_%s-%s-%s', 'create_db_values' => ['apps', 'staging','master', get('application')], ]); ``` - `cpanel` – array with configuration for cPanel - `username` – WHM account - `user` – cPanel account that you want in charge of the domain - `token` – WHM API token - `create_domain_format` – Format for name creation of domain - `create_domain_values` – The actual value reference for naming - `subdomain_prefix` – cPanel has a weird way of dealing with addons and subdomains, you cannot create 2 addons with the same subdomain, so you need to change it in some way, example uses first 4 chars of md5(app_name) - `subdomain_suffix` – cPanel has a weird way of dealing with addons and subdomains, so the suffix needs to be your main domain for that account for deletion purposes - `addondir` – addon dir is different from the deploy path because cPanel "injects" /home/user/ into the path, so tilde cannot be used - `allowInStage` – Define the stages that cPanel recipe actions are allowed in #### .env file example ``` CPANEL_HOST=xxx.xxx.xxx.xxx CPANEL_PORT=2087 CPANEL_USERNAME=root CPANEL_TOKEN=xxxx CPANEL_USER=xxx CPANEL_AUTH_TYPE=hash CPANEL_DB_USER=db_user CPANEL_DB_PRIVILEGES="ALL PRIVILEGES" SUDOMAIN_SUFFIX=.mymaindomain.com ``` ### Tasks - `cpanel:createaddondomain` Creates an addon domain - `cpanel:deleteaddondomain` Removes an addon domain - `cpanel:createdb` Creates a new database ### Usage A complete example with configs, staging and deployment ``` load(); // this is used just so an .env file can be used for credentials require 'cpanel.php'; // Project name set('application', 'myproject.com'); // Project repository set('repository', 'git@github.com:myorg/myproject.com'); set('cpanel', [ 'host' => getenv('CPANEL_HOST'), 'port' => getenv('CPANEL_PORT'), 'username' => getenv('CPANEL_USERNAME'), 'auth_type' => getenv('CPANEL_AUTH_TYPE'), 'token' => getenv('CPANEL_TOKEN'), 'user' => getenv('CPANEL_USER'), 'db_user' => getenv('CPANEL_DB_USER'), 'db_user_privileges' => getenv('CPANEL_DB_PRIVILEGES'), 'timeout' => 500, 'allowInStage' => ['staging', 'beta', 'alpha'], 'create_domain_format' => '%s-%s-%s', 'create_domain_values' => ['staging', 'master', get('application')], 'subdomain_prefix' => substr(md5(get('application')), 0,4) . '-', 'subdomain_suffix' => getenv('SUDOMAIN_SUFFIX'), 'create_db_format' => '%s_%s-%s-%s', 'create_db_values' => ['apps', 'staging','master', get('application')], ]); host('myproject.com') ->stage('staging') ->set('cpanel_createdb', vsprintf(get('cpanel')['create_db_format'], get('cpanel')['create_db_values'])) ->set('branch', 'dev-branch') ->set('deploy_path', '~/staging/' . vsprintf(get('cpanel')['create_domain_format'], get('cpanel')['create_domain_values'])) ->set('addondir', 'staging/' . vsprintf(get('cpanel')['create_domain_format'], get('cpanel')['create_domain_values'])); // Tasks task('build', function () { run('cd {{release_path}} && build'); }); after('deploy:prepare', 'cpanel:createaddondomain'); after('deploy:prepare', 'cpanel:createdb'); ``` */ namespace Deployer; use Deployer\Task\Context; use \Gufy\CpanelPhp\Cpanel; /** * @return Cpanel * @throws Exception\Exception */ function getCpanel() { $config = get('cpanel', []); $allowInStage = $config['allowInStage']; $stage = input()->getArgument('stage'); if (!class_exists('\Gufy\CpanelPhp\Cpanel')) { throw new \RuntimeException("Please install php package gufy/cpanel-php to use CPanel API"); } if (!in_array($stage, $allowInStage)) { throw new \RuntimeException(sprintf("Since it creates addon domains and databases, CPanel recipe is available only in the %s environments", implode($allowInStage))); } if (!is_array($config) || !isset($config['host']) || !isset($config['port']) || !isset($config['username']) || !isset($config['token']) || !isset($config['user']) ) { throw new \RuntimeException("Please configure CPanel config: set('cpanel', array('host' => 'xxx.xxx.xxx.xxx:', 'port' => 2087 , 'username' => 'root', 'token' => 'asdfasdf', 'cpaneluser' => 'guy'));"); } $cpanel = new Cpanel([ 'host' => 'https://' . $config['host'] . ':' . $config['port'], 'username' => $config['username'], 'auth_type' => $config['auth_type'], 'password' => $config['token'], ]); $cpanel->setTimeout($config['timeout']); return $cpanel; } function getDomainInfo() { $domain = vsprintf(get('cpanel')['create_domain_format'], get('cpanel')['create_domain_values']); $cleanDomain = str_replace(['.', ',', ' ', '/', '-'], '', $domain); $subDomain = get('cpanel')['subdomain_prefix'] . $cleanDomain; return [ 'domain' => $domain, 'subDomain' => $subDomain, 'subDomainWithSuffix' => $subDomain . get('cpanel')['subdomain_suffix'] ]; } desc('Creates database though CPanel API'); task('cpanel:createdb', function () { $cpanel = getCPanel(); $config = get('cpanel', []); if (!askConfirmation(sprintf('This will try to create the database %s on the host though CPanel API, ok?', get('cpanel_createdb')), true)) { return; } $createDbDataResult = $cpanel->cpanel('MysqlFE', 'createdb', $config['user'], ['db' => get('cpanel_createdb')]); $addPrivilegesDataResult = $cpanel->cpanel('MysqlFE', 'setdbuserprivileges', $config['user'], ['privileges' => $config['db_user_privileges'], 'db'=> get('cpanel_createdb'), 'dbuser' => $config['db_user']]); $createDbData = json_decode($createDbDataResult, true); $addPrivilegesData = json_decode($addPrivilegesDataResult, true); if (isset($createDbData['cpanelresult']['error'])) { writeln($createDbData['cpanelresult']['error']); } else { writeln('Successfully created database!'); } if (isset($addPrivilegesData['cpanelresult']['error'])) { writeln($addPrivilegesData['cpanelresult']['error']); } else { writeln('Successfully added privileges to database!'); } }); desc('Creates addon domain though CPanel API'); task('cpanel:createaddondomain', function () { $cpanel = getCPanel(); $config = get('cpanel', []); $domain = getDomainInfo()['domain']; $subDomain = getDomainInfo()['subDomain']; if (!askConfirmation(sprintf('This will try to create the addon domain %s and point it to %s and subdomain %s, ok?', $domain, get('addondir'), $subDomain), true)) { return; } writeln(sprintf('Creates addon domain %s and pointing it to %s', $domain, get('addondir'))); $addAddonDomainResult = $cpanel->cpanel('AddonDomain', 'addaddondomain', $config['user'], ['dir' => get('addondir'), 'newdomain'=> $domain, 'subdomain' => $subDomain]); $addAddonDomainData = json_decode($addAddonDomainResult, true); if (isset($addAddonDomainResult['cpanelresult']['error'])) { writeln($addAddonDomainData['cpanelresult']['error']); } else { writeln('Successfully created addon domain!'); writeln($addAddonDomainData['cpanelresult']['data'][0]['reason']); } }); desc('Deletes addon domain though CPanel API'); task('cpanel:deleteaddondomain', function () { $cpanel = getCPanel(); $config = get('cpanel', []); $domain = getDomainInfo()['domain']; $subDomain = getDomainInfo()['subDomain']; $subDomainWithSuffix = getDomainInfo()['subDomainWithSuffix']; if (!askConfirmation(sprintf('This will delete the addon domain %s with corresponding subdomain %s, ok?', $domain, $subDomain), true)) { return; } writeln(sprintf('Deleting addon domain %s', $domain)); $delAddonDomainResult = $cpanel->cpanel('AddonDomain', 'deladdondomain', $config['user'], ['domain'=> $domain, 'subdomain' => $subDomainWithSuffix]); $delAddonDomainResult = json_decode($delAddonDomainResult, true); if (isset($delAddonDomainResult['cpanelresult']['error'])) { writeln($delAddonDomainResult['cpanelresult']['error']); } else { writeln('Successfully deleted addon domain!'); writeln($delAddonDomainResult['cpanelresult']['data'][0]['reason']); } });