First-run installer
The first-party plugin mamenein/filament-installer is the first-boot UI at /install. It exists because Magic Containers and other stateless hosts have ephemeral disks and often no shell — you cannot ssh in and run php artisan migrate. Every web request redirects to /install until setup is finished.
Two gates
"Done" is not a file on the container disk. Two gates must both pass:
- Database lock — after migrate → configured seeders → optional first user, a row is written to
installer_locks. That table lives in the shared app database, so the lock is seen by every replica at once. - Env retire — set
INSTALLER_ENABLED=falseand redeploy. That opens the app for good. The complete page asks for this and has a Check button.
| State | Behaviour |
|---|---|
INSTALLER_ENABLED=true, no DB lock |
Checklist + Run |
INSTALLER_ENABLED=true, DB lock set |
Complete page (set env, Check) |
INSTALLER_ENABLED=false |
Middleware off; app open |
Magic Containers checklist
- Set
INSTALLER_ENABLED=trueon the first deploy. - Env must include
APP_KEY,APP_URL(no trailing slash),DB_CONNECTION,DB_URL, and — for remote libSQL —DB_AUTH_TOKEN. SESSION_DRIVER=databaseandCACHE_STORE=databaseare fine. While unlocked, the plugin forcessession.driver=cookieandcache.default=arrayso those stores do not 500 on missing tables before migrate.- Open
/installand run setup. The plugin runs migrate, then the configured seeders (typicallyRoleSeeder+PassportClientSeeder), then creates the firstsuper_admin. - On the complete page, set
INSTALLER_ENABLED=false, redeploy, and press Check (or just open/).
What is never redirected
Vite assets, Livewire endpoints (including hashed paths), and /up are never redirected to /install. Health checks and the asset pipeline stay reachable throughout setup.
Host wiring
Apps that assign Spatie/Shield roles must wire installer.seeders and listen for InstallerUserCreated — otherwise assignRole('super_admin') fails with There is no role named super_admin for guard web. The full wiring, config keys, and Passport PEM steps live in the plugin page.
See also: