Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

6. The kickstarter

The kickstarter installs Exponential on the command line from one file, kickstart.ini in the installation root. It runs the setup wizard's own step classes in a single PHP process, takes every answer from the file…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/install/06-kickstarter.md

On this page

6. The kickstarter

The kickstarter installs Exponential on the command line from one file, kickstart.ini in the installation root. It runs the setup wizard's own step classes in a single PHP process, takes every answer from the file instead of a form, holds the site in maintenance mode while it works, and records the run in var/log/kickstart.log and var/log/setup.log. This chapter is the complete reference: the two subcommands ini and run with every option and exit status, every section and key of kickstart.ini with its type, its default and its effect as the code applies them, annotated example files for SQLite, MySQL and PostgreSQL, the database action and its dangers, dry runs, resuming and re-running, and the use of the kickstarter in CI and containers. The short version: write the file with exp:kickstarter ini, check every value against 6.4 (above all DatabaseAction), run run --dry-run, then run --apply.

Contents · Previous: 5. The setup wizard · Next: 7. The console install

6.1 How it works

php bin/php/console exp:kickstarter run --apply --force
        |
        |  bin/php/kickstarter.php  ->  \Exponential\Command\Kernel\Kickstarter
        |  (kernel/private/classes/commands/kickstarter.php)
        |
        |  1. rotates var/log/kickstart.log -> kickstart.log.1 ... .9
        |  2. starts itself again as a child process (same PHP binary, same memory_limit,
        |     date.timezone and max_execution_time), copies the child's output to the
        |     terminal and to var/log/kickstart.log, masking the passwords of kickstart.ini
        v
expKickstarter (kernel/classes/expkickstarter.php), in the child
        |  - boots a CLI script with the siteaccess "plain", HTTP_HOST "localhost" when unset,
        |    and the time zone Europe/London when PHP's is UTC
        |  - deletes the cached copies var/cache/ini/kickstart-*.php
        |  - switches maintenance mode on (not in a dry run; an open window is kept)
        |  - runs the steps Welcome .. Final from kernel/setup/steps/ezstep_data.php,
        |    each one reading its section of kickstart.ini
        |  - switches maintenance mode off and prints a summary
        v
    a site, or "Setup failed on step: <Step>" and exit status 1

The command has two names: php bin/php/console exp:kickstarter and php bin/php/kickstarter.php. They take the same subcommands and options. Many installations add a console shortcut in the root (./console exp:kickstarter).

6.2 The commands

Usage: ./bin/php/console exp:kickstarter <command> [options]
       ./bin/php/kickstarter.php <command> [options]
CommandEffect
iniwrite or edit kickstart.ini
runinstall from kickstart.ini
help, --help, -h, or no commandshow the help

Any other word prints "Unknown command: word" and the help, with exit status 1. A call without a command shows the help and exits with status 0, so a script that forgot the subcommand does not fail; check that your scripts name run.

6.2.1 ini: write kickstart.ini

php bin/php/console exp:kickstarter ini              # interactive editor
php bin/php/console exp:kickstarter ini --yes        # built-in defaults, no questions
php bin/php/console exp:kickstarter ini --defaults   # the values of kickstart.ini-dist
OptionShortEffect
--defaults-dwrite kickstart.ini from the values in kickstart.ini-dist and exit
--yes-yapply the built-in defaults (table below) and write kickstart.ini without asking
--from-installedtake the Server, Database and User (never the Password) of an installed siteaccess as defaults; off by default
--help-hshow the help of ini

How the file is built (kernel/classes/expkickstarterini.php):

  1. kickstart.ini-dist is read. Every commented section (#[name]) and key (#Key=value) becomes a field; a ## ... comment line above a key becomes its description.
  2. When a kickstart.ini exists already, its values are merged over those, so ini edits the file you have.
  3. With --yes, the built-in defaults are applied over both (only for the keys that have one), and every empty Continue becomes true.
  4. The file is written with mode 0600 (owner only, also when an older kickstart.ini had a wider mode), because it holds passwords. It starts with a # comment header that lists the values to review, and each of those keys has a # REVIEW: ... line above it: both Database keys, DatabaseAction, URL, and the administrator's Email and Password. One section per wizard step follows, and the cached copies var/cache/ini/kickstart-*.php are deleted.

Without --yes or --defaults the command needs a terminal; otherwise it stops with "No TTY detected. Run with --defaults or --yes for non-interactive mode." and exit status 1. It also stops when kickstart.ini-dist is missing ("kickstart.ini-dist not found in project root.").

The --yes defaults:

SectionKeyDefault
database_choiceTypesqlite3
database_initServer, Port, Database, User, Password, Socketlocalhost, empty, exponential.db (the default for the default Type), root, empty, empty
language_optionsPrimary, Languages[]eng-US, none
site_typesSite_packagesevenx_multisite (the package exp:install installs)
site_accessAccessurl
site_detailsTitleMy Exponential Site
site_detailsURLempty
site_detailsAccess, AdminAccess, EditorAccesssevenx_site_user, sevenx_site_admin, editor
site_detailsAccessPort, AdminAccessPort, EditorAccessPort8080, 8081, 8082
site_detailsAccessHostname, AdminAccessHostname, EditorAccessHostnamesevenx-site.test.com, sevenx-site-admin.test.com, edit.sevenx-site.test.com
site_detailsDatabase, DatabaseActionexponential.db, ignore
site_adminFirstName, LastName, Email, PasswordAdmin, User, [email protected], empty (a password is generated at install time)
registrationComments, Sendempty (not read by run), false

Read the file before run. --yes writes a file that installs a SQLite site into an empty database as it is, but the values marked # REVIEW are guesses:

  • With --yes, [database_init] Database and [site_details] Database are exponential.db, a file in var/storage/sqlite3/ (the name exp:install uses for SQLite). When you choose another Type in the interactive editor, a Database that still holds a default follows it: exponential for MySQL, PostgreSQL and MongoDB, localhost:1521/FREEPDB1 for Oracle. For a database server, set both to the database you created.
  • With --yes, DatabaseAction is ignore: schema, base data and the package are installed into the database as it is, and nothing is dropped. That is right for a new, empty database (a SQLite file that does not exist yet is created). On a database that already holds a site, ignore skips the tables that exist and adds the package on top, so point Database at a new one; remove, which empties the database first, is written only when you choose it (read 6.5 first).
  • With --yes, [site_details] URL is empty, so the site's address becomes http://localhost. Set the real address.
  • With --defaults, every value is the example of kickstart.ini-dist: the package news_site, the databases ezp35test and ezp39test, DatabaseAction=remove, the administrator "God Like". It is a starting point for editing, nothing more.

A worked example for a SQLite test site:

php bin/php/console exp:kickstarter ini --yes
# edit kickstart.ini: URL=http://localhost:8087, Email= your address
php bin/php/console exp:kickstarter run --dry-run
php bin/php/console exp:kickstarter run --apply --force

ini writes the file with mode 0600, because it holds passwords; keep it so.

The defaults take nothing from an installation that is already there: its siteaccess settings name a live database, and a file written from them would install over it. With --from-installed the generator looks through settings/siteaccess/*/site.ini and takes the Server, Database and User of the first siteaccess that names a database and a user, for [database_init] and [site_details] Database; the Password is never copied, enter it yourself. A file made with --from-installed points at that installation's database: read it before you run it, and check DatabaseAction.

The interactive editor. ini without options shows a menu of the sections with a summary of each:

KeyIn the main menuIn a section
a numberedit that sectionedit that field
n / pnext / previous sectionnext / previous section
mback to the main menu
wwizard: walk through every field of every section, then save
vpreview the file (this writes it)
ssave and staysave and stay
qsave and quitsave and quit
?helphelp

Fields are edited according to their type: Continue and Send as yes/no, Type, Access and DatabaseAction as a numbered choice, ports as numbers, Password without echo, Languages[] as a comma-separated list (+value appends). There is no "quit without saving": interrupt with Ctrl-C to leave the file as it was.

6.2.2 run: install from kickstart.ini

php bin/php/console exp:kickstarter run --list-steps    # show the steps, change nothing
php bin/php/console exp:kickstarter run --dry-run       # check, stop after SiteDetails
php bin/php/console exp:kickstarter run --apply --force         # install
OptionDefaultEffect
--forceoffrequired whenever the range of steps includes CreateSites. Without it run stops with "The CreateSites step will modify the database and site settings." and "Re-run with --force to confirm you want to install the site package.", exit status 1
--dry-runofflists the sections found and the steps, then runs DatabaseChoice to SiteDetails (it sets the start and stop step itself), imports the site package into a temporary repository, and stops before SiteAdmin. No --force needed. See 6.7
--list-stepsoffprints the step table and exits with status 0. Like every run, it needs a kickstart.ini in the root; without one it stops with the "not found" message of 6.2.3
--start-step=<Step>welcomefirst step to run. Refused when a step in the range needs results of steps before it, see 6.10
--stop-step=<Step>finallast step to run
--help, -hthe help of run

The standard script options (--allow-root-user, --no-colors, --quiet, --debug, --verbose, --siteaccess, --logfiles) are accepted and ignored; the kickstarter always runs on the plain siteaccess. exp:install passes --allow-root-user on this way.

Step names are the class names of the step table and are matched without regard to case (SiteDetails, sitedetails). An unknown name stops the run with "Unknown start step: ..." or "Unknown stop step: ...".

--list-steps prints:

Setup steps:
  [ 0] Welcome                  (counted)
  [ 1] SystemCheck              (counted)
  [ 2] SystemFinetune           (counted)
  [ 3] EmailSettings            (counted)
  [ 4] DatabaseChoice           (counted)
  [ 5] DatabaseInit             (counted)
  [ 6] LanguageOptions          (counted)
  [ 7] SiteTypes                (counted)
  [ 8] PackageLanguageOptions   (counted)
  [ 9] SiteAccess               (counted)
  [10] SiteDetails              (counted)
  [11] SiteAdmin                (counted)
  [12] Security                 (counted)
  [13] Registration             (counted)
  [14] CreateSites              (hidden)
  [15] Final                    (counted)

The environment variables of run:

VariableEffect
EXP_KICKSTART_LOG=0no var/log/kickstart.log, and no child process
EXP_SETUP_LOG_DIR=<dir>write setup.log to another directory (used by tests so a real log is not rotated)

6.2.3 Exit status

StatusWhen
0the installation finished; or --list-steps; or a dry run that completed; or ini wrote the file; or help
1kickstart.ini not found ("kickstart.ini not found. Generate it first with: ./bin/php/console exp:kickstarter ini"); an unknown command, option or step name; a --start-step that cannot work; --force missing; kickstart.ini has no sections (dry run); any step failed; ini could not run or write

When the run log is on, the parent process exits with the child's status, so scripts see the same values.

6.2.4 What a run prints

A successful run prints the progress of each step, then:

Maintenance mode off: the site answers again.

Setup summary
--------------------------------------------------
Site package: sevenx_multisite
Title:        My Exponential site
Database:     exponential
Access type:  url
Site URL:     https://www.example.com/site
Admin URL:    https://www.example.com/admin
--------------------------------------------------
Finished:     2026-10-05 10:15:42 CEST
Elapsed:      00:02:31 (151.3 seconds)

A failed step prints Step <Step> failed: followed by one line per problem, for example a failed system test with its message, the database message of chapter 5, or the coded errors of CreateSites (section 5.3.15), and then Setup failed on step: <Step>. When a password had to be generated, the run prints it once (see [site_admin] below).

The Finished time is in PHP's time zone, with one exception: when that zone is UTC (no date.timezone in the command line php.ini), the kickstarter switches to Europe/London before it starts, so the time shown may be an hour off UTC in summer. Set date.timezone for the command line PHP and the times are your own.

6.3 How each step behaves on the command line

On the command line there is nobody to show a page to, so a step that would show one fails, with these exceptions:

StepSectionWithout a section, or with Continue=false
Welcomenone neededsets the wizard language to eng-GB and continues
SystemChecknoneruns the critical tests; a failed test fails the run and is listed with its message
SystemFinetunenonecontinues whatever the optional tests say
EmailSettings[email_settings]fails
DatabaseChoice[database_choice]fails, unless exactly one database extension is loaded
DatabaseInit[database_init]fails
LanguageOptions[language_options]fails
SiteTypes[site_types]fails
PackageLanguageOptionsnonecreates every package language you did not choose as itself (the wizard's default) and continues
SiteAccess[site_access]fails
SiteDetails[site_details]fails
SiteAdmin[site_admin]fails (skipped when DatabaseAction=skip)
Security[security]continues
Registration[registration]continues without sending anything
CreateSitesnoneinstalls
Finalnoneends the run

A step that fails because its section is missing or does not say Continue=true names the reason, for example "kickstart.ini has no [site_admin] section: the step needs one to run without the web wizard" or "kickstart.ini [site_access] has Continue=false: the step stops there for the web wizard. Set Continue=true to run it from the command line." "Unknown failure" is left only for a step that stopped for a reason the kickstarter cannot tell.

So for the command line: give every section from [email_settings] to [site_admin], each with Continue=true. The same file also drives the browser wizard (chapter 5).

The system check runs as the user that runs the kickstarter. Run it as the user the web server or Velocity runs as, or fix the ownership of settings/, var/ and design/ afterwards; the health checks at the end of var/log/setup.log include file ownership.

6.4 kickstart.ini reference

6.4.1 Syntax

kickstart.ini is read by eZINI like any Exponential settings file:

  • one [section] per step, named after the step's identifier;
  • Key=value, one per line; Key[]=value lines build an array;
  • no whitespace before a section or a key: an indented line is not read;
  • a line that starts with # or ; is a comment; a comment after a value is not: Key=value ; note gives the value value ; note, so put every comment on its own line;
  • values are text; booleans are the words true and false.

Keep the file at mode 0600: it holds passwords in clear text. Never commit it.

6.4.2 Sections and keys

Types: bool is true/false, choice one of the listed words, int a number, text free text, secret text masked in the logs.

[welcome] (not in kickstart.ini-dist)

KeyTypeDefaultEffect
Continueboolwith true the browser wizard skips its Welcome page. The command line skips it anyway

[email_settings]

KeyTypeDefaultEffect
Continueboolfalsetrue: use the values, do not ask
Typechoice: mta, smtpmtasmtp writes Transport=SMTP; any other value means sendmail/MTA. On Windows smtp is forced
ServertextSMTP host (TransportServer), used with smtp
UsertextSMTP user (TransportUser)
PasswordsecretSMTP password (TransportPassword)

[database_choice]

Supported databases (Exponential 6.0.x), in order of preference: 1. SQLite 3 (the default) · 2. PostgreSQL · 3. MongoDB · 4. MariaDB · 5. Oracle · 6. MySQL. Microsoft SQL Server is known to be possible with additional work at this time. Details: Database support.

KeyTypeDefaultEffect
Continueboolfalse
Typechoicesetup.ini [DatabaseSettings] DefaultType (sqlite3)sqlite3 (alias sqlite), mysqli (alias mysql), pgsql (alias postgresql), mongodb, oci8 (aliases oracle, ezoracle; needs extension/ezoracle). An unknown value is ignored and the step falls back to asking

[database_init]

KeyTypeDefaultEffect
Continueboolfalse
Servertextemptydatabase host
Portintempty (the driver's default)
Databasetextrequiredthe database. SQLite: a file name in var/storage/sqlite3/ matching ^[A-Za-z0-9][A-Za-z0-9_.-]{0,99}\.(db|db3|sqlite|sqlite3)$, or an absolute path without /../ (allowed only from kickstart.ini). Oracle: the connect string, e.g. 127.0.0.1:1521/FREEPDB1, or a TNS alias
Usertextempty
Passwordsecretempty
Sockettextemptypath of a local MySQL socket; empty writes Socket=disabled

This step connects to the database to check it. The checks and messages are those of the wizard (section 5.3.6).

[language_options]

KeyTypeDefaultEffect
Continueboolfalse
Primarytext (locale)requiredthe primary language, e.g. eng-US
Languages[]text listnoneadditional languages. The primary may be listed here too; it is dropped from the list

Every language must have a locale in share/locale. Otherwise the step stops the run with "Step LanguageOptions failed:" and the reason, also in var/log/setup.log ("kickstart.ini [language_options]: The primary language ... is not a language this installation has a locale for (share/locale)."). The site is always installed as UTF-8.

[site_types]

KeyTypeDefaultEffect
Continueboolfalse
Site_packagetextrequiredthe identifier of the site package, e.g. sevenx_multisite

How the package is found: the remote index of settings/package.ini [RepositorySettings] RemotePackagesIndexURL is read and its entry for the package is preferred. A package that is already imported under var/storage/packages/ is used as it is; one that is not is downloaded and imported, followed by its required packages that are missing or older than their min-version. When the index cannot be read, a package already in the local repository is used if all its requirements are imported (an offline install). To force a fresh copy of a package, remove its imported directory first.

[site_access]

KeyTypeDefaultEffect
Continueboolfalse
Accesschoice: url, port, hostnamehow requests are matched to the siteaccesses; written as MatchOrder=uri, port or host

[site_details]

KeyTypeDefault when missingEffect
Continueboolfalse
Titletextthe site package's summary[SiteSettings] SiteName
URLtexthttp://<host><path>; on the command line http://localhostthe site's address; SiteURL is written without the scheme. Always set it
OrganisationNametextempty (the site name is used)sender of the optional e-mail (mailpreferences.ini [FooterSettings])
OrganisationAddresstextemptythe sender's postal address; \n separates lines
Accesstextthe package identifierwith Access=url: the URL path of the siteaccess site
AdminAccesstextidentifier_adminwith url: the path of admin
EditorAccesstexteditor (<Access>_editor when editor is taken)with url: the path of editor
AccessPortint8080with port: the port of site
AdminAccessPortintthe next free of 8080, 8081, ...with port: the port of admin
EditorAccessPortintthe site's port + 2 (8082 for 8080), the next free port when that is the admin'swith port: the port of editor; never the site's or the admin's
AccessHostnametextidentifier.hostwith hostname: the host of site
AdminAccessHostnametextidentifier-admin.hostwith hostname: the host of admin
EditorAccessHostnametextedit.the site's host without www. (edit.example.com for www.example.com)with hostname: the host of editor
Databasetextrequiredthe database the site uses (SQLite: the file). Give the same value as [database_init] Database
DatabaseActionchoice: remove, ignore, skipignore behaviourwhat to do with existing data, 6.5

Only the keys of the chosen access type are used. The admin's port default counts up from 8080 only when you leave it out: with AccessPort=9000 and nothing else, the admin gets 8080 and the editor 9002. Give all three to be sure.

The siteaccess directories are always site, admin and editor, plus adminui when the exp_adminui extension is in the installation (reached by the path /adminui only, so it has no key here; see Exponential Admin UI). Access, AdminAccess and EditorAccess are the values that select them, not their names. Unlike the browser wizard, the command line does not refuse admin as a path, so AdminAccess=admin gives the familiar /admin.

[site_admin]

KeyTypeDefaultEffect
Continueboolfalse
FirstNametextAdministrator
LastNametextUser
Emailtextnonethe administrator's e-mail and [MailSettings] AdminEmail
Passwordsecretgeneratedthe password of the user admin

An empty, well-known or short password is never installed. When Password is empty or missing, shorter than site.ini [UserSettings] MinPasswordLength (10 as shipped), or a well-known or common password (the shared list of expWeakPasswordList: publish, admin, password, changeme, secret, exponential, demo, qwerty, 123456 and many more, with their simple variants such as other case, digits or ! at the end, letter swaps like p@ssw0rd and endings like -ing or -er; extensible with [UserSettings] WeakPasswordList[] and WeakPasswordFile), the step generates a random 20-character password, prints it once:

The administrator password was not set, is a well-known one or is shorter than 10 characters; generated a random one.
  admin password: <the password>
  (also written to var/log/initial-admin-password - change the password after the first login and delete that file)

and writes var/log/initial-admin-password with mode 0600. Log in, change the password, delete the file. These are the same rules as exp:install (chapter 7); before 6.0.15 a short password from kickstart.ini was installed as it was.

Public demos only: with the environment variable EXP_DEMO_MODE=1 (EXP_DEMO_MODE=1 ./console exp:kickstarter run), a well-known or short password (publish) is installed as it is, so a public demo gets the password it publishes; an empty one is still replaced. The run's child process inherits the variable. The site must keep the variable for its PHP afterwards, or its administrator password can be changed again: Demo mode. Never set it for a real site.

[security]

KeyTypeDefaultEffect
Continueboolfalsethe step has no values; true skips its advice page in the browser wizard

[registration]

KeyTypeDefaultEffect
Continueboolfalse
Sendboolfalsetrue sends a registration report about the installation (system, PHP and database details) through the configured mail transport, but only to settings/setup.ini [RegistrationSettings] Receiver, which is empty by default: without a receiver nothing is sent. The old upstream registration address is never used
UserData[...]textemptythe details sent with that report
Commentstextlisted in kickstart.ini-dist, not read by this version

6.4.3 The template: kickstart.ini-dist

kickstart.ini-dist in the installation root documents every section with commented examples (#[section], #Key=value) and a ## ... description above each key; it is what ini reads. kickstart.ini--example is a complete, generated file for a host-matched installation, useful to compare with your own. Neither is read by run.

6.5 DatabaseAction: read this before you run

Warning: DatabaseAction=remove destroys data. It empties the database named in [site_details] Database and installs into it. On MySQL, PostgreSQL and the other servers every kernel table is dropped first; on SQLite the whole file is emptied. Everything in that database is lost, and nothing asks you again: --force is the only confirmation. Point Database at a database that holds nothing you need, check it twice, and take a backup first. exp:kickstarter ini --from-installed fills Database from an existing installation's settings (6.2.1).

ValueEffect on the databaseEffect on the settingsUse it for
removeexisting tables dropped (SQLite: file emptied), then schema, base data and packages installedwrittena clean install, a reinstall
ignoreschema, data and packages added to whatever is there; tables that exist are skipped, nothing is droppedwrittena new, empty database (the ini --yes default)
skipnothing inserted; the administrator is not touchedwrittenregenerating settings/siteaccess/ and settings/override/ against a database that is already complete

A value that is missing or misspelled behaves like ignore: the data is added to what is there, which on a database that is not empty fails with duplicate tables or rows. Write the value explicitly.

Before a remove, back up, into a directory outside the installation root (a dump inside the document root can be downloaded by anyone who guesses its name):

mkdir -p /var/backups/exponential
# MySQL / MariaDB (MariaDB also calls the program mariadb-dump)
mysqldump --single-transaction --routines exponential > /var/backups/exponential/db-$(date +%Y%m%d-%H%M).sql
# PostgreSQL
pg_dump --format=custom --file=/var/backups/exponential/db-$(date +%Y%m%d-%H%M).dump exponential
# SQLite (the online backup gives a consistent copy even while the site writes)
sqlite3 var/storage/sqlite3/exponential.db ".backup '/var/backups/exponential/db.sqlite'"

Check that the backup is not empty (ls -l /var/backups/exponential/) before you run the install; a dump that failed for lack of privileges leaves a file of a few bytes.

6.6 Annotated example files

Each example is a complete kickstart.ini for run --apply. Lines starting with ; are comments and can stay in the file; each stands on its own line, because a comment after a value would become part of the value.

6.6.1 SQLite

; kickstart.ini - SQLite, URL matching (/site, /admin, /editor)

[email_settings]
Continue=true
; local sendmail/MTA
Type=mta

[database_choice]
Continue=true
Type=sqlite3

[database_init]
Continue=true
; a file needs no server, port, user or password
Server=
Port=
; var/storage/sqlite3/exponential.db
Database=exponential.db
User=
Password=
Socket=

[language_options]
Continue=true
; the language of the bundled content
Primary=eng-US
; optional additional language
Languages[]=ger-DE

[site_types]
Continue=true
Site_package=sevenx_multisite

[site_access]
Continue=true
Access=url

[site_details]
Continue=true
Title=My Exponential site
URL=https://www.example.com
; https://www.example.com/site   -> siteaccess site
Access=site
; https://www.example.com/admin  -> siteaccess admin
AdminAccess=admin
; https://www.example.com/editor -> siteaccess editor
EditorAccess=editor
; same as [database_init] Database
Database=exponential.db
; empties the file if it exists
DatabaseAction=remove

[site_admin]
Continue=true
FirstName=Site
LastName=Administrator
Email=[email protected]
; empty: generated, printed once, var/log/initial-admin-password
Password=

[security]
Continue=true

[registration]
Continue=true
; always
Send=false

The directory var/storage/sqlite3/ must be writable by the user that runs the kickstarter and by the web server; the database keeps -wal and -shm files beside it. SQLite in production is covered in chapter 9.

6.6.2 MySQL or MariaDB

Create the database and its user first, with UTF-8:

CREATE DATABASE exponential CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'exponential'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON exponential.* TO 'exponential'@'localhost';
; kickstart.ini - MySQL/MariaDB, host name matching

[email_settings]
Continue=true
Type=smtp
Server=smtp.example.com
User=[email protected]
; masked in kickstart.log
Password=CHANGE_ME_SMTP

[database_choice]
Continue=true
; "mysql" is accepted as well
Type=mysqli

[database_init]
Continue=true
Server=127.0.0.1
Port=3306
; must exist; no SHOW DATABASES privilege needed
Database=exponential
User=exponential
Password=CHANGE_ME_DB
; or /var/lib/mysql/mysql.sock instead of host and port
Socket=

[language_options]
Continue=true
Primary=eng-US

[site_types]
Continue=true
Site_package=sevenx_multisite

[site_access]
Continue=true
Access=hostname

[site_details]
Continue=true
Title=Example
URL=https://www.example.com
OrganisationName=Example Ltd
OrganisationAddress=1 Example Street\n12345 Example City
AccessHostname=www.example.com
AdminAccessHostname=admin.example.com
; also the default: edit.<AccessHostname without www.>
EditorAccessHostname=edit.example.com
Database=exponential
; DROPS every kernel table in `exponential`
DatabaseAction=remove

[site_admin]
Continue=true
FirstName=Site
LastName=Administrator
Email=[email protected]
Password=

[security]
Continue=true

[registration]
Continue=true
Send=false

When the server supports InnoDB, the tables are created as InnoDB. The connection charset written to the siteaccess settings is utf-8.

6.6.3 PostgreSQL

The database must exist, and the pgcrypto extension must be available in it (it provides digest()):

CREATE ROLE exponential LOGIN PASSWORD 'a-long-random-password';
CREATE DATABASE exponential OWNER exponential ENCODING 'UTF8';
\c exponential
CREATE EXTENSION IF NOT EXISTS pgcrypto;
; kickstart.ini - PostgreSQL, port matching (8080 site, 8081 admin, 8082 editor)

[email_settings]
Continue=true
Type=mta

[database_choice]
Continue=true
; "postgresql" is accepted as well
Type=pgsql

[database_init]
Continue=true
Server=db.internal
Port=5432
; the login is tested against this database
Database=exponential
User=exponential
Password=CHANGE_ME_DB
Socket=

[language_options]
Continue=true
Primary=eng-GB
; dropped if it is the primary; eng-US content is kept anyway
Languages[]=eng-US

[site_types]
Continue=true
Site_package=sevenx_multisite

[site_access]
Continue=true
Access=port

[site_details]
Continue=true
Title=Intranet
URL=http://intranet.example.com
AccessPort=8080
AdminAccessPort=8081
; also the default: AccessPort + 2
EditorAccessPort=8082
Database=exponential
DatabaseAction=remove

[site_admin]
Continue=true
FirstName=Site
LastName=Administrator
Email=[email protected]
Password=

[security]
Continue=true

[registration]
Continue=true
Send=false

When the installer cannot create pgcrypto itself, DatabaseInit fails with the message about the digest function quoted in section 5.3.6. MongoDB and Oracle use the same sections with Type=mongodb or Type=oci8; their specifics are in chapter 9.

6.7 Dry runs

php bin/php/console exp:kickstarter run --dry-run

A dry run:

  1. prints "Dry-run: validating kickstart.ini", the sections found and the step table; a file without sections stops here with "No groups found in kickstart.ini" and status 1;
  2. runs DatabaseChoice to SiteDetails with the values of the file, so the database must be reachable;
  3. in SiteTypes downloads the site package and its requirements into a temporary repository var/storage/packages/dryrun/, which is removed as soon as the step is done (and at the start of every run);
  4. stops after SiteDetails and prints "Dry-run completed: database and remote packages verified. Stopped after SiteDetails, nothing written."

It does not switch maintenance mode on, and it writes neither the database nor the settings. SiteAdmin and Registration do not run, so no var/log/initial-admin-password is written and no mail is sent. The run is logged to var/log/setup.log and var/log/kickstart.log.

6.8 Maintenance mode during a run

While a real run works, the site answers every web request with the maintenance page (HTTP 503, title "The site is being set up"), so no visitor meets the half-built database (chapter 4). The run prints "Maintenance mode on: the site shows the maintenance page until the installation is done." at the start and "Maintenance mode off: the site answers again." at the end.

After a failed step the site stays in maintenance mode, and the run says: "The site stays in maintenance mode. After fixing the cause: run the kickstarter again, or php bin/php/maintenance.php off".

A maintenance window that is already open (exp:maintenance on, or a marker of another run) is kept exactly as it is: the run does not replace var/maintenance.json, says "Maintenance mode was already on: kept as it is, and left on after the installation (php bin/php/maintenance.php off ends it).", and leaves the window open at the end. End it yourself when you are done.

php bin/php/maintenance.php status       # or: php bin/php/console exp:maintenance status
php bin/php/maintenance.php off

6.9 Logs

FileContent
var/log/kickstart.logeverything the run printed on stdout and stderr, with the passwords of kickstart.ini masked as ********, a header with the date, the directory and the command, and the exit status at the end. Earlier runs: kickstart.log.1 (the last) to kickstart.log.9. EXP_KICKSTART_LOG=0 turns it off
var/log/setup.logthe readable record of the run: environment, every step with its duration, errors and warnings (with a hint beside known problems), the health checks after an installation and a RESULT/NEXT line. Earlier runs rotate to setup.log.1 ...
var/log/error.logBEGIN and END entries around the run; entries written during the run end with the run and step they came from
var/log/initial-admin-passwordonly when a password was generated
tail -n 40 var/log/setup.log
grep -n "FAIL\|ERROR" var/log/setup.log

6.10 Re-running and resuming

Run again for an identical install. The same kickstart.ini with DatabaseAction=remove and run --apply replaces the database and the settings again. Use it to reset a test or training site.

After a failure, run the whole sequence again. Fix the cause (the failing step and its message are in the output and in var/log/setup.log), then:

php bin/php/console exp:kickstarter run --dry-run     # optional: check up to SiteDetails
php bin/php/console exp:kickstarter run --apply --force

The steps hand their results to the following ones inside one process: DatabaseChoice sets the database type that DatabaseInit and SiteDetails use, SiteTypes the package that SiteAccess and SiteDetails work on, and SystemCheck what CreateSites learns about ImageMagick. A run started with --start-step at a later step would not have those results, so the kickstarter refuses such a start before anything runs and names the earliest step that works, for example "--start-step=SiteDetails cannot work: the steps SiteDetails..Final need what Welcome, ... found out earlier in the same run (...). Start at Welcome or earlier: --start-step=Welcome." Every range that installs starts at Welcome, the default. --start-step is left for diagnosis of the early steps (for example --start-step=DatabaseChoice --stop-step=DatabaseInit to test only the database connection). With DatabaseAction=remove a complete second run replaces whatever the failed one left behind.

Stop early. --stop-step=<Step> ends after that step. With a stop step before CreateSites (for example --stop-step=SiteDetails) nothing is installed and --force is not needed: the run checks the configuration up to that point and the summary says "stopped after SiteDetails (nothing installed)" in the setup log. Unlike a dry run, such a run switches maintenance mode on for as long as it works.

Regenerate the settings only. DatabaseAction=skip and run --apply rewrite settings/siteaccess/ and settings/override/ from the file and leave the database alone.

Edited the file and see old values? ini and run delete var/cache/ini/kickstart-*.php themselves, because config.php switches off the INI modification-time check. The browser wizard does not; delete those files after editing kickstart.ini by hand when the wizard is to read it.

Changing database engine. The settings in settings/override/ win over a siteaccess's. When you install onto a different engine than the one the directory held before, set [DatabaseSettings] DatabaseImplementation in settings/override/site.ini.append.php to the new driver first (or remove the old value), or the site keeps talking the old engine's protocol.

After the install. Move kickstart.ini out of the installation root, or delete it: it holds passwords, and a browser wizard started later would read it.

6.11 In CI and containers

The kickstarter is a good fit for automation when the configuration is best kept as a reviewed file:

  1. Keep a template, e.g. deploy/kickstart.ini.template, under version control with placeholders for secrets.
  2. Render it at deploy time into the installation root with mode 0600.
  3. Run a dry run, then the install, and fail the job on a non-zero status:
#!/usr/bin/env bash
set -euo pipefail
cd /srv/exponential
umask 077
envsubst < deploy/kickstart.ini.template > kickstart.ini
php bin/php/console exp:kickstarter run --dry-run
php bin/php/console exp:kickstarter run --apply --force
rm -f kickstart.ini

Points to remember:

  • run needs no terminal; ini needs one unless --yes or --defaults is given.
  • The run takes a few minutes; give the job enough time. The child process keeps the parent's memory_limit and max_execution_time.
  • var/log/kickstart.log and var/log/setup.log are the artefacts to keep from a failed job.
  • In a container, run the install once (for example when settings/override/site.ini.append.php has no [DatabaseSettings]), not at every start.
  • For installs without a file, exp:install (chapter 7) builds the same configuration from options.

6.12 Notes on the other kickstarter documents

The earlier documents Kickstarter CLI and Kickstarter: install a whole site from one file remain useful background. Where they differ from this chapter, this chapter follows the code of this version:

  • Package download. The kickstarter prefers the remote index entry but uses a package that is already imported, and downloads only what is missing (6.4.2, [site_types]). A dry run always downloads, into the temporary dryrun repository. Kickstarter CLI now says the same.
  • --stop-step=CreateSites. It does not stop before the database is written: CreateSites is the step that writes it. Stop at Registration or earlier to leave the database untouched.
  • [registration] Comments. Not read; Send defaults to false.
  • Resuming with --start-step=SiteDetails. Older documents suggested resuming a failed run there. Such a start is refused, because the steps before it set values that SiteDetails and CreateSites read in the same process; run the whole sequence again (6.10). Kickstarter CLI and Installing Exponential 6.0 now say the same.
  • ini --yes. Up to 5 October 2026 it wrote Database=ezp, which SQLite refuses as a file name, and DatabaseAction=skip, which installs nothing, with the process's normal file mode. It now writes exponential.db, ignore and mode 0600, and marks the values to check with # REVIEW (6.2.1).

References

In this repository:

External:

Contents · Previous: 5. The setup wizard · Next: 7. The console install

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.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x