Installation
Install the Odden packages, run the migrations, and schedule the commands each module needs.
Requirements
- PHP 8.3 or newer
- Laravel 12 or 13
- SQLite 3.26+, MySQL 8.0+, or PostgreSQL 15+. Every package is tested against all three in CI.
- Filament 5.9 or newer, only if you install the Filament admin
Install the packages
Require the modules you want. Each one requires getodden/crm-core, so you don't need to list it unless you only want Core:
composer require getodden/crm-salesEvery package registers itself through Laravel's package discovery and loads its own migrations. Run them:
php artisan migrateAll Odden tables are prefixed with odden_. Table names are configurable per package (the tables key in each config file) if they would clash with your own.
Run the installer
The quickest way to finish setting up is the installer, once the packages are required:
php artisan odden:installIt runs the migrations, offers sample data, shows the scheduled commands your modules need and offers to add them to routes/console.php, warns if mail or the queue are not set up for sending, and, with the Filament admin installed, checks that the plugin is registered and that someone can sign in. It only does what is still missing, so it is safe to run again.
For a script or a Docker build, answer its questions with flags:
| Flag | Effect |
|---|---|
--skip-migrate |
Do not run the migrations. |
--force |
Run the migrations in production without asking. |
--demo / --no-demo |
Load the sample data without asking, or do not offer it. |
--schedule / --no-schedule |
Add the scheduled commands to routes/console.php without asking, or do not offer. |
The rest of this page is what the installer does, step by step.
Paid add-ons
Odden Marketing, Odden Service, and Odden CRM Pro are private packages installed with a license key. See Install a paid add-on.
Add the Filament admin
composer require getodden/crm-filamentThen register the plugin in your panel provider. See Filament admin for the details.
Publish configuration (optional)
Each package works with its defaults. Publish a config file only when you need to change something:
php artisan vendor:publish --tag=odden-core-config
php artisan vendor:publish --tag=odden-sales-configMigrations can be published the same way with the odden-core-migrations and odden-sales-migrations tags, if you want to modify them before they run.
Schedule the commands
Several features run on a schedule: sequence steps, quote expiry, and more. Odden doesn't register a schedule for you, so add the commands for the modules you installed to routes/console.php:
use Illuminate\Support\Facades\Schedule;
// Sales
Schedule::command('sales:process-cadences')->everyFifteenMinutes()->withoutOverlapping()->onOneServer();
Schedule::command('sales:expire-quotes')->dailyAt('01:00')->withoutOverlapping()->onOneServer();These are the frequencies Odden Cloud uses. The paid Marketing and Service add-ons list their own commands in their documentation. onOneServer() needs a cache store shared by all your servers; drop it if you run a single server.
Then make sure the scheduler runs, with php artisan schedule:work locally or a cron entry for php artisan schedule:run in production.
Configure mail
Configure a mailer in config/mail.php before you use any of the email features.
Run a queue worker. From v0.3, Odden queues every email it sends. Nothing is delivered from the request or command that triggers it: each email is pushed to the queue and a queue worker sends it. Without a worker, mail stays on the queue and is never delivered. This covers:
- Sales: sequence email steps and meeting confirmations
- The paid Marketing and Service add-ons queue their mail the same way
Run a worker in production, for example with Supervisor:
php artisan queue:workBy default each package uses your default queue connection, its default queue, and your default mailer. Each package can send its mail on its own connection and queue:
| Package | Config keys | Environment variables |
|---|---|---|
| Sales | odden-sales.mail.mailer, .connection, .queue |
ODDEN_SALES_MAILER, ODDEN_SALES_QUEUE_CONNECTION, ODDEN_SALES_MAIL_QUEUE |
If you set a queue name, include it in your worker's --queue list, for example php artisan queue:work --queue=sales-mail,default. See Sales mail configuration, which also sets the Sales "from" address.
With the sync queue connection the mail is sent during the request, which is fine for local development only.
Next steps
- Configuration: the user model, public routes, API tokens, and rate limits
- Core concepts