Scopes are a powerful management tool to ApisCP that greatly simplify complex management tasks through simple, often one or two word, commands. These were borne out a growing problem of outdated, wordy, or worse yet erroneous guides that permeate search results. It's hard to know what to do when the first 5 links give you conflicting information! TIMTOWTDI is not what you want to hear when it comes to managing server security.

Scopes build upon Bootstrapper, which handles server provisioning, weaving into its periodic integrity checks without conflict. When you make a change through a Scope, corresponding configuration is recorded, and Bootstrapper is called upon to alter system state. No fuss, no tears, and no scrolling through 5 pages about the author's summertime plans or relationship with his now-deceased grandmother (recipe sites, I'm looking at you...)

Many Scopes act instantaneously, whereas those dependent upon Bootstrapper will initiate a background task reflected in the job indicator up top. In case you haven't had time to appreciate the gear silhouette, now's your opportunity 😍.

Job indicator active with 1 job

At the time of writing, ApisCP ships with 71 Scopes, including 2 superclass Scopes: cp.config and cp.bootstrapper that facilitate interaction with the panel core configuration and Bootstrapper. In all, those open up 145 and 750 additional points of configuration respectively.

Superclass Scopes

A superclass Scope does more than a simple task, it acts as a gateway to complex, open-ended operations providing some error checking along the way. If Scopes are regimented with tight tolerances, superclass Scopes are the brains that create tight tolerances but lack safety checks itself. Two superclass Scopes exist today: cp.config, for interacting with config.ini; and cp.bootstrapper, for changing platform provisioning characteristics.

A little information overload never hurts

cp.config is well-documented from source. Any troublesome settings are prohibited from the GUI. cp.bootstrapper in contrast provides significantly more control, drilling down to platform minutiae, with the ability to scrub modified regions after changing. It is not as well-documented yet.

A word of caution: cp.bootstrapper directly affects platform internals. We're making rounds and documenting relevant variables. Some caution should be exercised. Refer to the Bootstrapper source to corroborate specific role settings and behaviors. Values surrounded by "{{" and "}}" are Jinja templates whose value is dependent ultimately upon another variable or a transformation of one or more values. It's part of Ansible, if you're curious. Changes made will be reflected into /root/apnscp-vars-runtime.yml, coercing type as needed.

Scopes of interest

  • apache.php-multi: manages native multiPHP builds. "native" packages are built from source and provide best performance. "package" utilize Remi builds, which are easier to manage for exotic extensions but have a 10% performance hit.
  • apache.evasive: tunes a variety of Evasive settings
  • mail.smart-host: smart host (mandatory next-hop SMTP relay)
  • cp.update-policy: configure panel update behavior. "edge" applies all commits, "major" applies only signed releases.
  • cp.update-schedule: run updates during a specific time of day rather than at night with crons.
  • cron.start-range: determine when crons (periodic maintenance tasks) should run. By default it's 3-4 AM local server time.
  • system.timezone: change system timezone
  • system.sshd-port: change SSH port
  • mail.spam-filter: switch between SpamAssassin and rspamd for filtering

Adding new Scopes

Additional Scopes may be latched on at boot using the bootloader of ApisCP. Inside config/custom, create a file named boot.php if it does not exist already. We'll need to register two things, one an autoload path and second, the actual Scope association.

cd /usr/local/apnscp
./artisan make:scope system hello-world

And in config/custom/boot.php:

<?php
apnscpFunctionInterceptor::register(
	\Opcenter\Admin\Settings\System\HelloWorld::class,
	'config/custom/scopes/Opcenter/Admin/Settings/System/HelloWorld.php'
);
\Opcenter\Admin\Settings\Setting::register(\Opcenter\Admin\Settings\System\HelloWorld::class);

In the above, we're creating a class mapping for system.hello-world to config/custom/scopes/Opcenter/Admin/Settings/System/HelloWorld.php. The Scope could just as easily be located in config/custom/scopes/system/hello-world.php.

Now edit the scope in config/custom/scopes/Opcenter/Admin/Settings/System/HelloWorld.php:

<?php declare(strict_types=1);

	namespace Opcenter\Admin\Settings\System;

	use Opcenter\Admin\Settings\SettingsInterface;

	class HelloWorld implements SettingsInterface
	{
		public function set($val): bool
		{
			return error("Nothing to see here");
		}

		public function get()
		{
			return microtime(true);
		}

		public function getHelp(): string
		{
			return 'Dummy command example';
		}

		public function getValues()
		{
			return 'mixed';
		}

		public function getDefault()
		{
			return true;
		}

	}

Then run it!

Happy Scoping! Bootstrapper can be invoked using \Opcenter\Admin\Bootstrapper::run($role1,$role2, ['var' => 'val', 'var2' => 'val2']); semantics. See lib/Opcenter/Admin/Settings for sample Scopes.