Update: 🍻 apnscp 3.0 pre-alpha has been released. Release notes.

A technical preview of apnscp pre-alpha has been released for individuals that would like to begin developing modules or providers (DNS, mail) ahead of the official pre-alpha release in July. License keys are provided upon request. The TR release does not contain an administrative frontend for "admin", but does contain a frontend for accounts + secondary users. Pre-alpha (released July 29) and later releases contain an administrative frontend.

apnscp may be installed on any RHEL or CentOS 7.x machine using the apnscp bootstrapper.

curl https://raw.githubusercontent.com/apisnetworks/apnscp-bootstrapper/master/bootstrap.sh | bash -s - -k <key>

Where <key> points to a local copy of the apnscp license. If you are running apnscp in trial mode, the following will suffice:

curl https://raw.githubusercontent.com/apisnetworks/apnscp-bootstrapper/master/bootstrap.sh | bash

apnscp will install with recommended defaults:

  • MariaDB 10.2 (MySQL drop-in replacement)
  • PostgreSQL 10
  • PHP 7.2

Any changes can be made by creating a file named "apnscp-vars.yml" in /root. Use the Playbook reference apnscp-vars.yml as a template. Installation documentation provides a basic overview. At the very least you should set apnscp_admin_email to receive notification once installation finishes. It takes about 1 to 2 hours depending upon CPU.

Restarting bootstrapper

If at any point the bootstrapper fails, it may be restarted by running,

pushd /usr/local/apnscp/resources/playbooks && ansible-playbook bootstrap.yml

You should send me an email at matt@apisnetworks.com so I can look over what may have failed.

Inactivity logouts

apnscp will take time to install. Some terminals are configured to automatically logout a user after a period of inactivity. If this happens to you use screen to persist the installation process even after logging out:

yum install -y screen
pushd /usr/local/apnscp/resources/playbooks && screen -S apnscp ansible-playbook bootstrap.yml

The screen session named "apnscp" can then be resumed at a later time via,

screen -r apnscp

Adding/removing sites

apnscp provides only a command-line interface for domain management during this technical release. Sites may be created using the command-line companions, AddDomain, DeleteDomain, and EditDomain located in /usr/local/apnscp/bin.

Create a domain:

AddDomain -c siteinfo,domain=mydomain.com -c siteinfo,admin_user=myadmin -c auth,passwd=1

Create a site named mydomain.com with an administrative user myadmin (always required). Prompt for a password.

AddDomain -c siteinfo,domain=mydomain.com -c siteinfo,admin_user=foobar -c diskquota,quota=2 -c diskquota,units=GB

Create a site named mydomain.com with an administrative user foobar. The password will be randomly generated. Assign a 2 GB storage quota to the account.

AddDomain -c siteinfo,domain=foobar.com -c siteinfo,admin_user=baz -c aliases,max=1 -c ssh,enabled=0

Create a new site named foobar.com with an administrative user baz. Allow 1 addon domain. Disable ssh.

Edit a domain:

EditDomain -c ssh,enabled=1 mydomain.com

Enable ssh access for mydomain.com + install the filesystem layer associated with it under /home/virtual/FILESYSTEMTEMPLATE/ssh

Delete a domain:

DeleteDomain site12

Advanced usage is provided in the documentation. Following the AddDomain template should be a satisfactory minimum to begin adding sites and using apnscp. A provider will need to be configured to integrate DNS management into the panel. Providers are discussed in a bit.

Low-level API commands

cpcmd provides an alias to /usr/local/apnscp/bin/cmd, a low-level interface to apnscp's API. cpcmd can invoke any exposed API method under any user or account. Usage is simple,

cpcmd [-d domain] [-u user] command command_args...

For example, to reset the administrative password on myadmin.com, cpcmd -d myadmin.com auth_change_password newpassword123. To change the administrative password, omit -d domain, cpcmd auth_change_password newadminpassword.

See also Helper Binaries + Beacon.

Logging into apnscp

apnscp may be accessed through https://<hostname>:2083 or through https://<server ip>:2083. Setting a hostname is recommended for Let's Encrypt SSL issuance.

To change the admin username, sudo /usr/local/apnscp/bin/cmd auth_change_username <newusername>

To change the admin password, sudo /usr/local/apnscp/bin/cmd auth_change_password <newpassword>

cpcmd is an alias to /usr/local/apnscp/bin/cmd. For brevity we'll continue to use cpcmd with sudo or root assumed.

Logging into services

All accounts require a username + domain to login; server admin does not require a domain. Unless the domain is explicitly required, such as when logging into the control panel, use @ or # to join the username + domain. For example, when logging into SSH as user foo on example.com, all are acceptable variations of ssh:

ssh -l foo@bar.com bar.com
ssh foo@bar.com@bar.com
ssh -l foo#bar.com bar.com
ssh foo#bar.com@bar.com

This can be further simplified by creating a file called config in ~/.ssh with the following lines,

Host bar
    HostName bar.com
    User foo#bar.com

Then, ssh bar will login to "bar.com" using the login "foo#bar.com".

As a second example, consider FTP. With the username myadmin + domain mydomain.com, the following configuration will allow access to the FTP server using explicit SSL (FTPES).


SFTP is supported if SSH is enabled for the account. ftp.<domain> is by convention, but using too the server name, server IP address, or domain name is also acceptable.

Indexing apps

Inevitably some sites will be migrated from existing hosting infrastructures. Once an account has been created with AddDomain and the necessary files/database structure copied, it's not a bad idea to enroll everything into apnscp's automatic update system. Use admin_locate_webapps and admin_update_webapps to first catalog known apps, then perform an immediate upgrade for anything that needs updating. Updates run every night for major software releases (e.g. WordPress 4.9.5 -> 4.9.6) and every Wednesday/Sunday for plugin/theme updates.

cpcmd admin_locate_webapps '[site:debug.com]'
cpcmd admin_update_webapps '[site:debug.com,assets:1,core:1]'

This process is unnecessary for apps that are installed within apnscp via Web > Web Apps.

Building modules

All modules under lib/modules/ are reserved for apnscp. Addon modules can be created by dropping in a new module under /usr/local/apnscp/lib/modules/surrogates/. Surrogate modules overwrite builtin modules and can be whatever you want. Here's an example surrogate from the documentation to help you get started!

    class Aliases_Module_Surrogate extends Aliases_Module {
         * Extend nameserver checks to include whitelabel nameservers
        protected function domain_is_delegated($domain)
            $myns = [
            $nameservers = $this->dns_get_authns_from_host($domain);
            foreach($nameservers as $nameserver) {
                if (in_array($nameserver, $myns)) {
                    return 1;
            return parent::domain_is_delegated($domain);

Name the file alias.php in /usr/local/apnscp/lib/modules/surrogates, then restart apnscp:

sudo systemctl restart apnscp

Now if a domain only uses domains in the set: ns1.myhostingns.com, ns2.myhostingns.com, ns1.whitelabel.com and ns2.whitelabel.com, it is considered under your control and properly setup. But what happens if domain2 uses a different DNS provider than domain1? It isn't practical to include every nameserver under the sun to determine whether it has been setup properly. Instead, a provider can be configured to the account, specifically DNS providers.

Configuring providers

apnscp ships with DNS providers for DigitalOcean, Linode, and Cloudflare. By default "builtin" is used, which provides no DNS functionality unless implemented with a DNS surrogate mentioned above.

Configuring a provider is a breeze!

AddDomain -c siteinfo,domain=mydomain.com -c dns,provider=digitalocean -c dns,key=DOKEY

where DOKEY is your API key. After configured, all DNS operations within the control panel will use DO's API. All that you need to do is set your nameservers to DigitalOcean's.

Provider API key documentation

Note: at this time Cloudflare Hosting Partner support is not available.

A default provider key may be configured globally by editing config.ini, specifically [dns] => provider_default and [dns] => provider_key.

A note on complex syntax

A provider may have a multivariate key, in which case the syntax follows, [key:val,key2:val2], such that it would become:

EditDomain -c dns,provider=newprovider -c dns,key='[email:matt@apisnetworks.com,key:abcdefghijk]' mydomain.com

Internally this could be rendered within a module, via deferencing, as:

echo $this->get_service_value('dns','provider')['email'], $this->get_service_value('dns','provider')['key']

Check with the provider's documentation to determine whether a multivariate or scalar key is necessary. The same system holds true for any key-value configuration variables from command-line.

Creating a provider

Providers allow apnscp to query the right data source for an account. Whereas surrogates replace a module, a provider complements a module. A module may have at most 1 surrogate, but a module may have multiple providers.

At this time apnscp includes DNS and mail providers; unless specified during account creation a provider will default to "builtin", located in lib/modules/. Providers are located in lib/Module/Providers/<Type>/<Name> and must be configured in config.ini to be activated.

Once configured, a site can be changed over to use the new provider as follows:

EditDomain -c dns,provider=newprovider -c dns,key=providerkey mydomain.com
At this time it is not possible to migrate settings when changing providers through EditDomain.

lib/Module/Providers/Dns/Stub.php (source) provides a sample implementation for a DNS provider. At the bare minimum be sure to implement the following methods:

  • atomicUpdate() attempts a record modification, which must retain the original record if it fails
  • zoneAxfr() returns all DNS records
  • add_record() add a DNS record
  • remove_record() removes a DNS record
  • get_hosting_nameservers() returns nameservers for the DNS provider
  • add_zone_backend() creates DNS zone
  • remove_zone_backend() removes a DNS zone

Any other API methods may be overridden at your leisure. Once the provider is configured, edit config/custom/config.ini to add the new provider, then restart apnscp: systemctl restart apnscp.

EditDomain -c dns,provider=newprovider will become a valid option then. Validation can be performed either in _verify_conf() embedded in the module or through a separate set of validation under Opcenter\Dns\Services.

Creating apps

apnscp allows for app creation. Apps may be placed in config/custom/apps/<appid> where is a short alphanumeric name for the application, e.g. "railsinstaller" or "backups".

Apps must be explicitly granted to a user and can be done so through config/custom/templates/<role>.php where role is "admin", "site", or "user". These roles are sourced on first login; any changes made will require a logout, then login.

    'Add Review',

"Add Review" then may be accessed under /apps/feedback for the site admin. Application programming is covered in the apnscp docs.

Injecting files

All accounts are comprised of synthetic roots through OverlayFS. A synthetic root consists of one or more read-only system layers + a read-write data layer. In apnscp, the shadow layer (/home/virtual/siteXX/shadow) contains read-write account data. Any files copied from a read-only layer or created by an account will bubble up to the shadow layer.

Its simplest usage is to copy a file to /home/virtual/FILESYSTEMTEMPLATE/<service>. A filesystem reload is then necessary to drop caches and propagate changes through its branches:
systemctl reload fsmount

RPMs may also be installed and tracked in service layers. apnscp ships with a healthy assortment of packages preinstalled into the filesystem template. Additional packages may be installed using the Yum Synchronizer.

sudo /usr/local/apnscp/bin/scripts/yum-post.php install <package> <service>

Services can be dynamically synthesized into an account depending upon service linkage.

Further reading: Managing Account: Filesystem Template


apnscp allows for some debugging. All configuration in config/config.ini is stored in Redis on boot. Any changes to config.ini requires a restart. The easier process, while debugging is to switch directories and restart apnscpd:

cd /usr/local/apnscp/bin ; env DEVELOPMENT=1 ./apnscpd restart

DEVELOPMENT is a special environment variable that will change the presentation of apnscp, it will print out any info(), debug() or unhandled Exception to the user. Backtraces can be further expressed by altering [core] => debug_backtrace_qualifier (docs). Passive backtraces, great for debugging unattending, can be generated by setting [core] => bug_report in config.ini.

Customizing themes

apnscp is built around Bootstrap v4 (alpha 6 at the time of this release). Theme SASS is available via apnscp-bootstrap-sdk. Javascript library is available via apnscp-bootstrap-jdk.

Updating apnscp

apnscp follows a rolling release schedule. build/upcp.sh may be used to pull the lastest commits from BitBucket.

During pre-production release the quality of code cannot be vetted for and git-pull discretion is advised.

Bootstrapper may be run immediately following update with --bootstrap

build/upcp.sh --bootstrap

Getting in touch

As with any release this early on, problems are anticipated. Contact me at matt@apisnetworks.com, /r/apnscp, or apnscp Discord if you run into any snags along the way. Issues may be reported directly to me, BitBucket, or Github.

Known issues

The following issues are known deficiencies in this release and will be fixed before the next full release:

  • 1-click login for phpMyAdmin, phpPgAdmin, SquirrelMail, Roundcube, Horde
  • Attempting to install a new Python interpreter as site admin fails with PYTHONPATH error

Pending changes

The following changes are pending for the pre-alpha release and will be included:

  • Incorporate Laravel/Ghost 1-click install + updates
  • DO/Linode/CF DNS providers
  • Admin panel

- Matt