4 September 2021

In previous articles I looked at how to view and format account information using whmapi1 and how to update the PHP version for one or more domains. In this article I cover creating and configuring a cPanel account. The aim is do the following:

  • Create the cPanel account.
  • Update the PHP version to the latest version available on the server.
  • Add an alias so that you can add temporary URL.
  • Install a Let’s Encrypt SSL certificate.

Create a cPanel account

The function used to create new cPanel accounts is createacct. It has quite a few options, but at a minimum you need to use the domain and username parameters. In the below command I am using a few additional options:

  • plan=catalyst_MegaDeal is the name of the hosting package (this is our Mega Deal plan). This package has to exist on the server and is used to define resource limits for the account, such as the disk space quota and bandwidth limit.
  • maxpark=1 adds an alias to the account. I will use this to add a temporary URL later.
  • dkim=1 and spf=1 make sure a DKIM and SPF record are added to the zone file on the server.
# /usr/local/cpanel/bin/whmapi1 createacct \
username=example \
domain=example.com \
plan=catalyst_MegaDeal \
maxpark=1 \
dkim=1 \
spf=1

Things to check before creating an account

You have to be a bit careful when creating an account. Firstly, as already mentioned, you should make sure that the plan exists. You can list all existing plans using whmapi1 listpkgs. The output is likely to be quite long, so you may want to filter the output using yq:

# whmapi1 listpkgs | yq e '.data.pkg[].name' -
catalyst_MegaDeal
catalyst_MegaPlus
catalyst_Power
catalyst_PowerPlus
catalyst_PowerXtra
...

We want the cheap ‘n cheerful starter package, which is catalyst_MegaDeal. Next, you want to make sure that any custom options make sense. For instance, I want to make sure that new account has an alias. Before I add the option I can check how many parked domains are included in the package. The getpkginfo lists most resource limits:

# /usr/local/cpanel/bin/whmapi1 getpkginfo pkg=catalyst_MegaDeal
---
data:
  pkg:
    BWLIMIT: 5000
    CGI: 1
    CPMOD: paper_lantern
    DIGESTAUTH: 'n'
    FEATURELIST: catalyst2_shared
    FRONTPAGE: 0
    HASSHELL: 0
    IP: 0
    LANG: en
    MAXADDON: 0
    MAXFTP: 1
    MAXLST: 1
    MAXPARK: 0
    MAXPOP: 1
    MAXSQL: 1
    MAXSUB: 1
...

Here, MAXPARK has the value 0, so it makes sense to add the maxpark=1 option to the createacct function. Had the value been, say, 2, then adding the option would actually reduce the number of available resources.

The createacct function doesn’t produce a lot of output. Unless you get an error message the new account is quietly created.

The cPanel control panel for our example.com domain.
Image: The cPanel account has been created. Note that the sidebar shows that we also got an alias.

Of course, you can also use whmapi1 to verify that the account has been created:

# /usr/local/cpanel/bin/whmapi1 accountsummary \
api.columns.enable=1 \
api.columns.a=domain \
api.columns.b=maxparked \
api.columns.c=plan \
user=example \
| yq e '.data.acct[]' -
domain: example.com
maxparked: 1
plan: catalyst_MegaDeal

Updating the PHP version

New cPanel accounts automatically get the inherited PHP version. As discussed in the article about batch-updating PHP versions, you typically want to change the PHP version for new PHP accounts.

You can check the default / inherited PHP version using php_get_system_default_version

# /usr/local/cpanel/bin/whmapi1 php_get_system_default_version
---
data:
  version: ea-php56
metadata:
  command: php_get_system_default_version
  reason: OK
  result: 1
  version: 1

The default PHP version on this server is ea-php56. That version is ancient and no longer supported, so let’s change the PHP version for example.com to the latest version available on the server. You can list all available PHP versions using php_get_installed_versions:

# /usr/local/cpanel/bin/whmapi1 php_get_installed_versions | yq e '.data.versions[]' -
ea-php56
ea-php71
ea-php72
ea-php73
ea-php74

And you can list the PHP version for an individual virtual host using php_get_vhost_versions:

# /usr/local/cpanel/bin/whmapi1 php_get_vhost_versions \
api.filter.enable=1 \
api.filter.a.field=account \
api.filter.a.arg0=example
---
data:
  versions:
    -
      account: example
      account_owner: root
      documentroot: /home/example/public_html
      homedir: /home/example
      is_suspended: 0
      main_domain: 1
      php_fpm: 0
      php_fpm_pool_parms: {}

      phpversion_source:
        system_default: 1
      version: ea-php56
      vhost: example.com
metadata:
  command: php_get_vhost_versions
  reason: OK
  result: 1
  version: 1

If you just want the version then you need a much more fancy command:

# /usr/local/cpanel/bin/whmapi1 php_get_vhost_versions \
api.filter.enable=1 \
api.columns.enable=1 \
api.columns.a=account \
api.columns.b=version \
api.filter.a.field=account \
api.filter.a.arg0=example \
| yq e '.data.versions[].version' -
ea-php56

Updating the PHP version for a virtual host is much easier:

# /usr/local/cpanel/bin/whmapi1 php_set_vhost_versions \
version=ea-php74 \
vhost=example.com
---
data: {}

metadata:
  command: php_set_vhost_versions
  reason: OK
  result: 1
  version: 1

The output is not very verbose, so you might want to double-check if the version was really updated. The below image shows that the PHP version for example.com is now ea-php74.

The cPanel MultiPHP Manager shows that the PHP version for example.com has been changed to ea-php74.
Image: example.com now uses PHP 7.4.

Adding an alias

The easiest way to view all domains for an account is via uapi:

# uapi --user=example DomainInfo list_domains
---
apiversion: 3
func: list_domains
module: DomainInfo
result:
data:
addon_domains: []

main_domain: example.com
parked_domains: []

sub_domains: []

errors: ~
messages: ~
metadata: {}

status: 1
warnings: ~

I want to add an alias / parked domain for my new account so that I can view the site as it appears on the server without updating the DNS for the domain. For that you use the create_parked_domain_for_user function:

# /usr/local/cpanel/bin/whmapi1 create_parked_domain_for_user \
domain=example.acai.temporarywebsiteaddress.com \
username=example \
web_vhost_domain=example.com
---
metadata:
  command: create_parked_domain_for_user
  reason: OK
  result: 1
  version: 1

All three arguments are required:

  • domain is the alias / parked domain.
  • username is the cPanel user.
  • web_vhost_domain is the virtual host to which the domain should be added.

As with updating the PHP version, the output isn’t very verbose. In general, if no errors are shown the command almost certainly succeeded.

The cPanel Aliases page shows that our example.com site now also has an alias.
Image: the alias has been created.

Installing a Let’s Encrypt SSL certificate

Most cPanel servers are configured to install free SSL certificates from one or more providers. The default option is a free cPanel SSL certificate (provided by Sectigo) but all our cPanel servers are configured to provide Let’s Encrypt SSL certificates instead. You can check check which providers are enabled via the get_autossl_providers function.

Installing a free SSL certificate involves two steps: you need to first enable the AutoSSL feature for the user and then run AutoSSL. For the latter you can either use the start_autossl_check_for_one_user function or /usr/local/cpanel/bin/autossl_check. I personally prefer the latter command, as it outputs log entries. That is useful, as it tells you about any errors that might occur.

Enabling AutoSSL

On some servers AutoSSL is automatically enabled when you create a new account, so in that case you can can straight away run AutoSSL. If AutoSSL isn’t enable you run into this error:

# /usr/local/cpanel/bin/whmapi1 start_autossl_check_for_one_user \
> username=example
---
metadata:
  command: start_autossl_check_for_one_user
  reason: "API failure: (XID sjrmzb) The user “example” does not have the AutoSSL feature enabled."
  result: 0
  version: 1

The error message is quite helpful: the command failed because the AutoSSL feature isn’t enabled. You can confirm that using the verify_user_has_feature function:

# /usr/local/cpanel/bin/whmapi1 verify_user_has_feature \
user=example \
feature=autossl
---
data:
  has_feature: 0
  query_feature: autossl
metadata:
  command: verify_user_has_feature
  reason: OK
  result: 1
  version: 1

In computer-speak 0 always means “no” or “off”, so AutoSSL isn’t enabled for the user example. To add the feature you can run an add_override_feature_for_user command:

# /usr/local/cpanel/bin/whmapi1 add_override_features_for_user \
user=example \
features='{"autossl":"1"}'
---
metadata:
  command: add_override_features_for_user
  reason: OK
  result: 1
  version: 1

# /usr/local/cpanel/bin/whmapi1 verify_user_has_feature \
user=example \
feature=autossl
---
data:
  has_feature: 1
  query_feature: autossl
...

Installing the SSL certificate

And you can now install the SSL certificate and verify that the domain can be accessed over HTTPS:

# /usr/local/cpanel/bin/autossl_check --user=example
...

# curl -IL https://example.acai.temporarywebsiteaddress.com
HTTP/1.1 200 OK
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
content-type: text/html; charset=UTF-8
date: Wed, 01 Sep 2021 15:44:58 GMT
server: LiteSpeed
alt-svc: h3=":443"; ma=2592000, h3-29=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q043=":443"; ma=2592000, quic=":443"; ma=2592000; v="43,46"

Automating account creation

If you regularly add accounts for users then you can consider automating all the steps discussed in this article. You can even take it a step further and install WordPress via WP-CLI (you could use uapi to create a database and database user with custom privileges). However, as I tried to show throughout this article, your script would need to do a lot of checking. For instance, to change the PHP version to the latest version you need to first check what the inherited and latest versions are. Before you install an SSL certificate you need to check if AutoSSL is enabled, and if not enable it. And, you also need to add error handling: what should your script do if a command fails?

In general, the graphical interface is likely to be easier. And if you are looking for a way to add a large number of accounts then it helps if some of the checks can be skipped. For instance, if you know beforehand what packages exist; which features they have and what PHP versions are installed then things become a lot easier.