Advanced installation
Database
The installation asks — SQLite, PostgreSQL or MySQL. The default is SQLite, so it depends on nothing.
PostgreSQL is the recommended one, for a functional reason: it is the only one shipping pgvector, which the local AI features that use semantic search (embeddings) depend on. With SQLite or MySQL the rest of the kit runs the same — only those features are unavailable.
If you pick Postgres during installation, the .env already comes with the block docker-compose.yml reads. If the container is not up at that moment, the kit warns you, skips the migrations and prints the command to finish:
docker compose up -dphp artisan migrate --seedTo switch after the installation, bring the containers up and copy the variables:
docker compose up -d # pgsql (with pgvector) + redis# copy the database block from .env.docker into your .envphp artisan migrate --seedMySQL ships a container too
If you pick MySQL, the .env comes pointing at 127.0.0.1:3306 with user root, and the kit
brings the server up for you. The command differs from the Postgres one, and the reason matters:
docker compose up -d mysql redisphp artisan migrate --seedMySQL is the only database in a profile of its own, because the installation picks a single
database — leaving it profile-less would make every install bring Postgres and MySQL up together.
Naming the services on the command line enables the MySQL profile and restricts the run to what
was named, so the default-profile Postgres stays down. That is why redis has to be written there:
naming services turns off the rest of the default set along with it.
Two details of the image, which explain what the installer writes:
-
The user is
root. The official image refuses to createrootthroughMYSQL_USER— keeping that user, the only way is the root password. -
The password is not empty.
mysql:8.0refuses to initialize without a root password, and the installer writessecret, the same one the container reads. Bringing your own server, adjustDB_PASSWORDin the.env— just as you already would with an external Postgres. -
The host port is
FORWARD_MYSQL_PORT, defaulting to 3306, not Postgres’FORWARD_DB_PORT. They are separate keys because under theappprofile both databases come up together, and a single variable would make them fight over the same port. If a MySQL is already running on your machine, Docker refuses withBind for 0.0.0.0:3306 failed: port is already allocated— change the key:Janela do terminal FORWARD_MYSQL_PORT=3399 docker compose up -d mysql redisand point
DB_PORTin the.envat the same port.
The local AI caveat does not change: semantic search and embeddings depend on pgvector, which only
Postgres has.
Container names
No service in docker-compose.yml declares a container_name. The prefix of every container and
every network comes from COMPOSE_PROJECT_NAME, in the .env, and kit:install writes your chosen
name there — lowercased and hyphenated, which is the format Compose accepts:
$ docker compose psminha-app-pgsql-1minha-app-redis-1Without that key, starter-kit applies — the floor written in docker-compose.yml itself.
Two practical points:
- A project born from an earlier version of the kit does not get the key through
kit:update, which never touches.env. Runphp artisan kit:install --custom, which redoes name and colour, or add the line by hand. - Changing the name after containers are already up creates new volumes. The old data stays in
the volume under the previous name; migrate it first, or change the name before the first
up.
The containerized application and the database
The app profile brings the whole application up in a container. It talks to Postgres by default;
to point it at MySQL, set in the .env:
DOCKER_DB_SERVICE=mysqland enable both profiles together, otherwise the database container never starts and the host does not exist:
docker compose --profile app --profile mysql up -d --buildOne honest caveat: in that combination an idle Postgres container comes up, because the app
profile services depend on it to order the boot. The alternative was measured and is worse — without
that dependency, docker compose --profile app up -d brings the application up with no database at
all, and without an error.
Commands
composer dev # server + queue + vite togethercomposer test # pint + phpstan + filacheck + the whole suitecomposer test:kit # only the kit's tests (the foundation), in parallelcomposer lint # formats the codecomposer lint:check # only checks the formatting, changing nothing (what CI runs)composer filament:check # only the Filament-specific lint (FilaCheck)composer refactor:preview # what Rector would rewrite (dry-run) — OUTSIDE composer testcomposer refactor:apply # applies Rector's rewrite — OUTSIDE composer testcomposer upgrade:filament # runs vendor/bin/filament-v5 (filament/upgrade is already in require-dev)php artisan kit:install --force # reinstalls from scratch (deletes the SQLite file) and asks againphp artisan kit:install --custom # redoes only name and colour, without touching the databasephp artisan kit:install --no-custom # installs without asking anythingphp artisan kit:install --no-npm # skips installing and building the front-end assetsphp artisan kit:install --no-seed # doesn't seed the database (roles, initial user, AI agents)php artisan kit:install --no-support # skips the invitation to star the kit on GitHub# --create-project is internal to post-create-project-cmd: removes what only serves the kit's own repositoryphp artisan kit:admin # changes the administrator's e-mail and password (asks for confirmation)php artisan kit:admin --email=x --senha=y --force # no prompts — avoid it: the password lands in the shell historyphp artisan kit:info # shows how the project is customized and where each value comes fromphp artisan kit:update # brings in improvements from a new kit versionphp artisan kit:tenancy # turns on multi-tenancy (opt-in)The quality deep dives that used to sit under this section — FilaCheck, Rector, the test suite, the README images and the SFDIPOT sweep — are in Code quality.
Customize your project
The installer already asks the first five — the list below is for changing them later, or for whoever skipped the questions.
php artisan kit:info shows the current value of every item below, and whether it comes from the database or the .env.
| # | What | Where | Asked during installation? |
|---|---|---|---|
| 1 | Name | APP_NAME in .env |
✅ |
| 2 | Database | the DB_* block in .env |
✅ |
| 3 | Seeder credentials | KIT_ADMIN_EMAIL / KIT_ADMIN_PASSWORD in .env |
✅ |
| 4 | Primary color | KIT_COR_PRIMARIA in .env (a color name from the Filament palette), or KIT_COR_PRIMARIA_HEX with a free hex value — the hex beats the name when both are filled |
✅ |
| 5 | Multi-tenancy | php artisan kit:tenancy, and the displayed term in config/kit.php → tenancy.label |
✅ |
| 6 | Login artwork | none: it shows the application name (APP_NAME) on its own. To replace it with your own image, upload it at /admin/configuracoes-da-aplicacao |
✅ (via the name) |
| 7 | Panel access | each user’s role (/admin → Roles, the Painel field); the rule that reads it is App\Models\User::canAccessPanel() |
— |
| 8 | Permission matrix | database/seeders/PapeisSeeder.php |
— |
| 9 | Health checks | KitServiceProvider::configureHealthChecks() |
— |
| 10 | Commands in the UI | config/command-center.php |
— |
| 11 | Backups | destination and schedule in config/backup.php |
— |
| 12 | AI agent | /admin → AI Agents (or database/seeders/AssistenteSeeder.php) |
— |
| 13 | Panel languages | config/kit.php → idiomas (a list of locales; with only one, the switcher doesn’t show) |
— |
| 14 | Trail retention | KIT_RETENCAO_EXCECOES_DIAS / KIT_RETENCAO_EMAILS_DIAS in .env |
— |
| 15 | Media disk | MEDIA_DISK in .env (local by default — private, served through a signed URL) |
php artisan kit:midia-privada migrates media already written to a public disk |
| 16 | CSV import and export | the Action in each app/Filament/**/Pages/List*.php (on or commented out); the permission in config/filament-shield.php → policies.methods; history retention in KIT_RETENCAO_IMPORTACOES_DIAS / KIT_RETENCAO_EXPORTACOES_DIAS in .env |
reseed ShieldPermissionsSeeder + PapeisSeeder after touching the config |
The last eleven are not asked because they are code or screen data, not a value that fits in a terminal prompt. The installer lists them in the final summary, each with its file.
⚠️ Item 5 is the only one that is not “edit a file” once installed:
kit:tenancyrunsmigrate:fresh --seedand deletes your data. It requires a clean git tree and an explicit confirmation. Answered during installation it deletes nothing — the database does not exist yet, and that is the right moment to decide.
The primary color applies to all three panels. With multi-tenancy on, each organization’s color wins over it inside
/app/{slug}—/adminand/infrakeep the project’s one. For a full palette, and not justprimary, the way is still->colors([...])in eachapp/Providers/Filament/*PanelProvider.php.