Automating provisioning
This page is for system administrators and developers who automate the creation of Exponential customer sites. It answers: which steps a pipeline needs, in which order, what each step checks, and how a site is removed again. Your own tooling (panel hooks, configuration management, shell scripts) does the work; this page gives the Exponential side of each step.
Warning
.htaccess slows down every request. When .htaccess files are enabled (AllowOverride anything but None), let alone
used, Apache looks for them and reads and evaluates them on every request, in every directory of the path, and
page loading times go up drastically (measured). The only real fix is to switch the feature off for
the virtual host: AllowOverride None in the HTTPS virtual host, and the rules in the virtual host's own
configuration as mod_rewrite rules. That is far faster in production speed tests and well worth the time it takes
to optimize a production configuration. Switch over right away: copy the rules of the
example HTTPS virtual host into your virtual host (with the static cache, also
staticcache_offload.conf), set AllowOverride None, run apachectl configtest, reload Apache and
test the site. The same rules for other servers: nginx, LiteSpeed,
Caddy, IIS, Velocity (built in); where virtual host rules go in a control
panel: Plesk, cPanel, DirectAdmin, ISPConfig.
On LiteSpeed or OpenLiteSpeed, the server's own page cache can also answer anonymous visitors and crawlers without PHP: Page caching with LiteSpeed and OpenLiteSpeed.
Contents
The pipeline
| # | Step | Checks |
|---|---|---|
| 1 | System user and directory | the user exists, the directory belongs to it |
| 2 | PHP: FPM pool or Velocity instance | the pool or instance runs as that user |
| 3 | Database | empty database, user with create rights (not for SQLite 3) |
| 4 | Code | the tested release is checked out, vendor/ complete |
| 5 | Install | exp:install --dry-run, then exp:install; exit status 0 |
| 6 | Serve | the site answers over HTTPS |
| 7 | Cron | the site user's crontab runs runcronjobs.php |
| 8 | Handover | password delivered, var/log/initial-admin-password removed |
| 9 | Backups and monitoring | the site is registered in both |
Step by step
1. System user and directory
One system user per site (Per-customer users and pools). Everything the installer and the site write must belong to that user: "Run it as the user the web server or Velocity runs as, or fix the ownership afterwards" (4.6).
2. PHP
- PHP-FPM: a pool for the site, running as its user (PHP-FPM tuning).
- Velocity: workers run as
[ServerSettings] UserandGroupof the site'svelocity.ini; give each site its own ports (Velocity workers and pools).
3. Database
For SQLite 3, nothing but a writable var/storage/sqlite3/. For a server engine, create a database and a user for
this site alone (Databases and users in panels); never reuse root or postgres.
4. Code
A checkout of the release tag you tested, then the dependencies from the lock file:
git clone --branch v6.0.<n> https://github.com/se7enxweb/exponential.git <installation>
cd <installation> && composer install --no-devPin one release for all new sites and move the pin only after a test (Composer and Git on servers).
5. Install
Pass the database password through the environment and test first:
export EXP_INSTALL_DB_PASSWORD='<from your secret store>'
php bin/php/console exp:install --dry-run --db=pgsql --db-host=<db host> --db-name=<db> --db-user=<db user> \
--url=https://www.example.com --email=<contact> --package=sevenx_multisite_clean
php bin/php/console exp:install --apply --db=pgsql --db-host=<db host> --db-name=<db> --db-user=<db user> \
--url=https://www.example.com --email=<contact> --package=sevenx_multisite_cleanOn exit status 1, keep var/log/setup.log and stop the pipeline; the site stays in maintenance mode
(exp:install for hosts).
6. Serve
Configure the web server for the site, or set the Velocity engine and start it
(Choosing a web server). Under Apache or LiteSpeed, put .htaccess into place,
and config.php with the values this server needs, from the console. Run as root, every command needs
--allow-root-user, and --owner gives a new file to the site's user:
php bin/php/console exp:setup:htaccess --apply --allow-root-user --owner=<site user>:<site group>
php bin/php/console exp:setup:config --apply --allow-root-user --owner=<site user>:<site group>
php bin/php/console exp:config:set EZP_DIR_MODE_MAX 0750 --apply --allow-root-user
php bin/php/console exp:config:set EZP_FILE_MODE_MAX 0640 --apply --allow-root-user
php bin/php/console exp:config:list --only-set --allow-root-userEach command ends with PASS: or FAIL: and exits 0, 1 or 2; a second run says nothing to do
(Setting up .htaccess and config.php from the console).
Then check from outside:
curl -s -o /dev/null -w '%{http_code}\n' https://www.example.com/
curl -s -o /dev/null -w '%{http_code}\n' https://www.example.com/admin/user/loginBoth should answer 200 (10.11).
7. Cron
Install the crontab of 10.3 in the site user's crontab, with the same PHP binary the web uses (Cron jobs).
8. Handover
If the password was generated, read it from var/log/initial-admin-password, deliver it through a secure channel and
delete the file. Tell the customer to change it and create personal accounts
(First sign-in and default passwords).
9. Backups and monitoring
Register the database and var/storage, settings/override, settings/siteaccess in the backup system, and the
site's address in monitoring (What to back up,
Health checks and uptime).
Making it safe to run again
- Detect an existing installation the way
exp:installdoes:settings/override/site.ini.append.phpholds a[DatabaseSettings]block. Skip the install step when it does;exp:installitself refuses without--force. - Never pass
--forcefrom a pipeline unless the run is meant to destroy and rebuild that site. - Keep
--db-action=removeaway from databases with data. A pipeline should always create a new database for a new site. - Keep secrets out of logs. Do not echo the environment; the saved configuration in
var/log/masks passwords, and theexp:config:*commands print********for every password or key unless given--show-secrets. Pass a secret as--value="$VARIABLE", not typed on the command line. .htaccessandconfig.phpare safe to repeat.exp:setup:htaccessandexp:setup:confignever replace a file that differs from its template without--force, andexp:config:setchanges nothing when the value is already there. In a drift check,exp:setup:htaccesswithout--applyexits 1 when.htaccesshas changed, andexp:config:list --only-set --format=jsongives a document to compare.
Removing a site
The reverse order: maintenance mode on, a final backup, crontab removed, web server or Velocity instance removed, database and user dropped, files removed, backups kept for the agreed retention. The full list is the Customer offboarding checklist.
A record per site
Write what the pipeline did into a record per site: domain, system user, PHP version, engine and ports, database engine and name, release tag, site package, install date, backup and monitoring registration. Support staff need it on the first call.
Related pages
- One-click installers
- Containers: Docker and Podman
- New server checklist
- Setting up .htaccess and config.php from the console
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.