Tools Blog Learn Quizzes Smile API Log In / Sign Up
Tools Blog Learn Quizzes Smile API Log In / Sign Up
« Return to the tutorials list
We have updated our privacy policy to let you know that we use cookies to personalise content and ads. We also use cookies to analyse our traffic and we share information about your use of our site and application with our advertising and analytics partners. By using this website or our application you agree to our use of cookies. Learn more about the way this website uses cookies or remove this message.

You can read this article in: English :: EspaƱol

Using PHP to create new subdomains, databases and email accounts on a cPanel driven server

January 16, 2017 Difficulty: 30 / 50 Tweet
control panel button

Update: Since 2014, when this article was initially published a new, better way of managing WHM/cPanel instances has emerged. Read on for the updated article and code.

To achieve our goal, we'll use Composer - the PHP dependency manager and the mgufrone/cpanel-whm. package open sourced by Mochamad Gufron

Let's start by cloning the package into a new folder on a WHM server.


    composer require gufy/cpanel-whm:dev-master

To test it out, in the root folder of your project create a new PHP file, require vendor/autoload and try listing the cPanel accounts on your server.


    require ('vendor/autoload.php');

    $cpanel = new \Gufy\CpanelPhp\Cpanel([
        'host'        =>  'https://myhost.tld:2087',
        'username'    =>  'root',
        'auth_type'   =>  'password', // there is also an option to use "hash"
        'password'    =>  'password', // if you use hash, get the value from WHM's Remote Access Key if not use the root password here
    ]);

    $accounts = $cpanel->listaccts();
    print_r($accounts);

If you received a JSON string with all cPanel accounts from your server, then the authentication process worked perfectly.

An important aspect when working with the WHM API is that there are different versions of it, so you need to figure out which one is best for whatever it is that you want to accomplish.

WHM has cPanel API 1 (the version I was using in the original article - from 2014), cPanel API 2 (newer but now deprecated) and UAPI (the latest one).

The gufy/cpanel-whm package provides an interface for interacting with either of these APIs so let's get back to our file and define some constants for each. Then we will create a new database under one of our cPanel accounts. One more thing to remember is that if you use database prefixes on your instance, you'll need to pass that prefix too.


    define("CPANEL_API_1", 1);
    define("CPANEL_API_2", 2);
    define("UAPI", 3);


    //parameters: API Version, Action Class, Action name, cPanel account username, parameters to be passed to function
    //remember to pass the prefix
    $data = $cpanel->execute_action(UAPI, 'Mysql', 'create_database', 'cpanel_username', ['name'=>'prefix_anewdb']);
    //result should look similar to this: //{"func":"create_database","result":{"metadata":{},"data":null,"errors":null,"status":1,"messages":null},"apiversion":3,"module":"Mysql"}

Next step is to create a new user and grant him access to do anything with that database - GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%' WITH GRANT OPTION;


    //create the new user!
    $usr = $cpanel->execute_action(
        UAPI, 
        'Mysql', 
        'create_user', 
        'cpanel_username', 
        [
            'name'=>'prefix_anewusr', 
            'password'=>'aSecretP@@55'
        ]
    );

    //grant everything
    $grant = $cpanel->execute_action(
        UAPI, 
        'Mysql', 
        'set_privileges_on_database', 
        'cpanel_username', 
        [
            'user'=>'prefix_anewusr', 
            'database'=>'prefix_anewdb', 
            'privileges'=>'ALL PRIVILEGES'
        ]
    );

To create new email accounts, make use of the add_pop function.


    //parameters: API_VERSION, Action Class, Action name, cPanel account username, [new email, new password, quota in MB, the domain of the cPanel account, flag for skipping the update of the email accounts database's cache.]
    $new_email = $cpanel->execute_action(
        UAPI,
        'Email',
        'add_pop',
        'cpanel_username',
        array(
            'email'           => 'anewuser',
            'password'        => 'aSecretP@@55',
            'quota'           => '0',
            'domain'          => 'mydomain.tld',
            'skip_update_db'  => '0',
        )
    );

To create new sub-domains on an existing account, UAPI doesn't yet have an implementation so we will use the API Version 2 in order to achieve the same result.


    //parameters: API_VERSION, Action Class, Action name, cPanel account username, [subdomain, parentdomain, the root directory of this new subdomain, flag for removing the dots (.) from the domain value.]
    $subdomain = $cpanel->execute_action(
        CPANEL_API_2,
        'SubDomain',
        'addsubdomain',
        'cpanel_username',
        array(
            'domain'        => 'mynewsubdomain',
            'rootdomain'    => 'mydomain.tld',
            'dir'           => '/public_html/directory_name',
            'disallowdot'   => '1',
        )
    );

Hope you find this useful! Let me know your thoughts in the comments area

What follows is the original article from 2014. Please consider using the updated version above.

Many hosting providers use cPanel and this tutorial comes as a helper for those of you who need to manage various server aspects with PHP. I will show you how to create new sub-domains, databases and email accounts on a cPanel driven server, from your PHP code. In order to be able to talk back and forth with the cPanel API you'll need the cPanel XMLAPI Client Class which you can find on GitHub

Creating a new sub-domain

    
    <?php
      $cpanelusr = 'username';
      $cpanelpass = 'password';
      $xmlapi = new xmlapi('127.0.0.1');
      $xmlapi->set_port( 2083 );
      $xmlapi->password_auth($cpanelusr,$cpanelpass);
      $xmlapi->set_debug(0); //output actions in the error log 1 for true and 0 false 
      $result = $xmlapi->api1_query($cpanelusr, 'SubDomain', 'addsubdomain', array('subdomainname','domain.com',0,0, '/public_html/subdomainname'));
    ?>
    
  

Creating a new database and a user for it

    
    <?php
    $cpanelusr = 'username';
    $cpanelpass = 'password';
    $xmlapi2 = new xmlapi('127.0.0.1');
    $xmlapi2->set_port( 2083 );
    $xmlapi2->password_auth($cpanelusr,$cpanelpass);
    $xmlapi2->set_debug(0); //output actions in the error log 1 for true and 0 false 

    //the actual $databasename and $databaseuser will contain the cpanel prefix for a particular account. Ex: prefix_dbname and prefix_dbuser
    $databasename = 'db_name';
    $databaseuser = 'db_usr'; //be careful this can only have a maximum of 7 characters
    $databasepass = 'passwordforthenewuser';

    $createdb = $xmlapi2->api1_query($cpanelusr, "Mysql", "adddb", array($databasename)); //creates the database
    $usr = $xmlapi2->api1_query($cpanelusr, "Mysql", "adduser", array($databaseuser, $databasepass)); //creates the user
    $addusr = $xmlapi2->api1_query($cpanelusr, "Mysql", "adduserdb", array("".$cpanelusr."_".$databasename."", "".$cpanelusr."_".$databaseuser."", 'all')); //gives all privileges to the newly created user on the new db
    ?>
    
  

Adding a new email account

    
    <?php
    //use the same process as above to authenticate

    $email_user = "emailusr";
    $email_password = "emailusrpass";
    $email_domain = "domain.com";
    $email_quota = '10';

    $addemail $xmlapi->api1_query($cpanelusr, "Email", "addpop", array($email_user, $email_password, $email_quota, $email_domain) );
    ?>
    
  

Of course you can do much more if you study the cPanel API and other cPanel related sources but the above are pieces of code that I've used in the past and they worked for me so I thought I should share them with you guys. Don't hesitate to add more example API calls into the comments section.

comments powered by Disqus

Better Docs For A Better Web - Mozilla Developer Network

Alerts

2017-07-25 - In all versions of PHP 7, during the unserialization process, resizing the 'properties' hash table of a serialized object may lead to use-after-free. A remote attacker may exploit this bug to gain arbitrary code execution. Read more ...
2017-07-25 - Off-by-one error in the phar_parse_pharfile function in ext/phar/phar.c in PHP before 5.6.30 and 7.0.x before 7.0.15 allows remote attackers to cause a denial of service (memory corruption) or possibly execute arbitrary code via a crafted PHAR archive with an alias mismatch. Read more ...

See All Entries...