Demo mode for hosts
This page is for the system administrators of a host that runs a public demonstration site of Exponential, one whose
administrator sign-in is published. Demo mode is switched on by the environment variable EXP_DEMO_MODE=1. While
it is on, nobody can change or reset the password of an administrator (so the next visitor can still sign in), the
installers accept the published demo password, and the administration shows a Demo mode banner.
Warning
Demo mode tells the world that the administrator password is known. Set it only for a site whose content, users and settings are all throwaway, on its own system user, pool and database, and never for a shared pool, a server-wide environment or a template that other sites are built from.
Contents
- The rules of the variable
- Setting it for each server
- Installing a demo
- Checking it
- Keeping it away from production
- Risks to tell the demo's owner
- Related pages
The rules of the variable
- Environment only. No INI setting, no request parameter and no administration page can switch it on, so a settings file or a database copied from a demo does not carry it to another site.
- Only the exact value
1.0,true,yes,onand an empty value leave it off. - Per process. PHP reads it with
getenv()first, then$_SERVER, on every call. Every process that serves or maintains the demo needs it: the web server's PHP, Exponential Velocity if it serves the site, cron jobs and console commands. A process without it runs with demo mode off.
Setting it for each server
| Where PHP runs | How to set it, for the demo only |
|---|---|
| PHP-FPM | in the demo's own pool file: env[EXP_DEMO_MODE] = 1, then reload the pool's master |
| Apache (mod_php, or PHP-FPM through mod_proxy_fcgi) | in the demo's virtual host: SetEnv EXP_DEMO_MODE 1 |
| LiteSpeed / OpenLiteSpeed (lsphp) | the demo's virtual host or external application environment: EXP_DEMO_MODE=1 |
| Exponential Velocity | export EXP_DEMO_MODE=1 in the demo's site envvars, /etc/vc/sites-available/<site>.envvars (<site>: ./console exp:velocity layout): exp:velocity start passes it to this installation's server only. The environment of the process that starts the demo's own server works too (Environment=EXP_DEMO_MODE=1 in its systemd unit or a drop-in). Never the shared /etc/vc/envvars |
| FrankenPHP or another application server | the environment of the server process |
| Cron | a line EXP_DEMO_MODE=1 at the top of the demo user's crontab |
| Console | export EXP_DEMO_MODE=1 in the demo user's shell profile, or before each command |
| Containers | ENV EXP_DEMO_MODE=1 in the demo image, or -e EXP_DEMO_MODE=1 / environment: for the demo service only |
Velocity restarts. With export EXP_DEMO_MODE=1 in the demo's site envvars,
/etc/vc/sites-available/<site>.envvars, exp:velocity restart and exp:velocity deploy keep demo mode whichever
shell runs them: exp:velocity start reads the file at every start of that installation's server, and
./console exp:velocity layout lists it under site envvars. The file is read, never run, and refuses PATH,
LD_*, DYLD_*, MALLOC_*, HTTP_*, PHPRC, PHP_INI_SCAN_DIR, HOME, USER and the other loader and shell
variables (on-disk layout).
Never in the shared /etc/vc/envvars. The Velocity server of every installation on the host reads it, so demo
mode there would reach your customers' production sites. Since 6.0.15 a Velocity worker refuses demo mode from a
shared envvars file, keeps it off and logs demo/refused ... came from an envvars file other installations share in
var/log/security.log; ./console exp:info shows refused (shared envvars). A demo set up there by an earlier
release loses demo mode at the upgrade's restart: move the line to its site envvars first
(demo mode).
Installing a demo
Set the variable for the installation too. The installers (setup wizard, kickstarter, exp:install) then accept the
published administrator password even though it is a well-known word and shorter than MinPasswordLength, instead
of replacing it with a random one:
EXP_DEMO_MODE=1 ./console exp:install --apply --db=sqlite --password='<the published demo password>' ...Any non-empty password works, so both publish (seven characters) and publishing do; an empty one is still
refused. Only the administrator password of the new installation is relaxed: every other account keeps
[UserSettings] MinPasswordLength (10 as shipped) and the well-known list. Do not reset the password
after the installation with exp:resetuserpassword: in demo mode that is refused, and it is no longer needed.
A demo that is rebuilt on a schedule (every few hours, from the current code) does this in its build script: install
with the variable, swap the new site in, keep the variable in the running site's PHP environment and crontab. The
script must not write the variable into config.php, settings/ or anything that is copied to other sites.
Checking it
- The administration shows the Demo mode banner on every page.
grep 'demo/mode' var/log/security.loglists every process that started with it (one line per process, with its pid and SAPI); Setup > Log files groups them asdemo/mode.- The audit has a
system.demo.modeevent per process (always recorded). - A console command prints
Demo mode is on (EXP_DEMO_MODE=1) ...on standard error.
Keeping it away from production
- Never set it server-wide (
/etc/environment, a globalSetEnv, the default pool, a base image) or in a provisioning template. - Alert on it: a
demo/modeline in thesecurity.logof a production site, or asystem.demo.modeaudit event, means the variable reached a process it should not have. - Add it to the security review:
grep -r EXP_DEMO_MODEover the PHP-FPM pools, the virtual hosts, the service units and the crontabs of production machines must find nothing.
Risks to tell the demo's owner
- Demo mode only protects administrator passwords. A visitor signed in as an administrator can still create accounts, change roles and settings, install packages and upload files: rebuild the demo on a schedule.
- Keep real data, real mail addresses and secrets out of the demo, and send its mail to a file or a sink.
- Other published sign-ins (an editor, a member) are not protected.
- If the variable is lost (a restart from a shell without it), demo mode is off without a sign other than the missing banner.
Related pages
- Demo mode (for administrators), Demo mode FAQ
- Recipe: run a public demo on LiteSpeed and Plesk, Demo mode problems, Demo mode examples
- Demo mode: the upgrade note
- First sign-in and default passwords
- Hardening for hosts, Security for hosts: overview
- Setting up a demo installation
- 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.