Releases
First installation
Section titled “First installation”composer install --no-dev --optimize-autoloader --no-interactionphp spark migrate --allphp spark anvil:install --tenant="Muster AG" --email=admin@example.comanvil:install runs the migrations and anvil:publish (again), creates the
first tenant and the administrator and prints a generated password once. The
password must be changed at the first login. With an existing account,
--promote gives it full access without asking.
Every release
Section titled “Every release”A release, in this order:
# 1. Code with the locked dependencies, without dev packages.# The post-install script of the application runs "spark anvil:publish".composer install --no-dev --optimize-autoloader --no-interaction
# 2. Database: Shield, Settings, Queue, Anvil and the application.php spark migrate --all
# 3. Workflow definitions: stores new versions, exit code 1 on errors.php spark anvil:workflow:check
# 4. Restart the queue worker, so it runs the new code.sudo systemctl restart anvil-queueanvil:publishcopies CSS, JavaScript and fonts topublic/assets/anviland writesmanifest.jsonwith the integrity hashes (SRI) the panels use. If yourcomposer.jsonhas nopost-install-cmdfor it, runphp spark anvil:publishyourself; stale assets fail their integrity check in the browser. See Styling.- Run
anvil:installonly once, for the first installation; it creates the first tenant and administrator. - Take a database backup before
migrate. Do not usemigrate:rollbackin production; it runs thedown()methods of a whole batch. anvil:workflow:checkis only needed with workflows.
Optional: CodeIgniter’s optimisation
Section titled “Optional: CodeIgniter’s optimisation”php spark optimize switches on config and file locator caching in
app/Config/Optimize.php (it edits that file), removes the old caches
and runs composer install --no-dev. With config caching on, the resolved
configuration, including values from .env, is cached under
writable/cache/; after every change of a config file or .env run
php spark optimize again, or the old values stay active. Try it on
staging before you rely on it.
php spark cache:clear empties the cache handler. Rate limit counters and
pending single sign-on logins live there, so do not run it as a routine
step.
Zero downtime releases
Section titled “Zero downtime releases”With a release directory per version and a current symlink, the old
version keeps serving until the new one is ready:
/var/www/app/├── releases/│ ├── 2026-11-01-1030/│ └── 2026-11-08-0915/├── shared/│ ├── .env│ └── writable/ # cache, logs, session, anvil/files, anvil/exports└── current -> releases/2026-11-08-0915- Unpack the release to
releases/<timestamp>, link.envandwritable/fromshared/. composer install --no-dev …(publishes the assets into the release).php spark migrate --allandphp spark anvil:workflow:check.- Switch the symlink:
ln -sfn releases/<timestamp> current. - Reload PHP-FPM (OPcache) and restart the queue worker.
Write migrations so that the old code still works with the new schema (add columns first, remove them in a later release). Keep the last releases for a quick switch back – a switch back of the code does not undo migrations.
Upgrading Anvil
Section titled “Upgrading Anvil”Read the upgrade notes and the changelog before updating
rakoitde/anvil; new versions may bring migrations, new workflow versions
or changed configuration. Update on staging first:
composer update rakoitde/anvil --with-dependenciesphp spark migrate --allphp spark anvil:workflow:checkvendor/bin/phpunit