nixos-module: add scheduler timer for artisan schedule:run

Invoice Ninja relies on Laravel's scheduler for recurring invoices,
scheduled reports, and other internal cron-driven jobs. Without a
systemd unit invoking `artisan schedule:run` periodically, the app's
dashboard reports "cron jobs are not enabled" after login.

Adds invoiceninja-scheduler.timer (every minute, matching upstream's
documented cron cadence) and its oneshot service, and extends the
automated test to assert the timer is active and schedule:run succeeds.

Note: the app's own is_scheduler_running flag only flips on a 5-minute
wall-clock boundary (app/Console/Kernel.php's everyFiveMinutes() job),
so the dashboard warning can take a few minutes to clear after boot -
confirmed working via the "Refresh Data" button in that same modal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 13:06:00 -04:00
co-authored by Claude Sonnet 5
parent 2c0a48b899
commit fef9406b63
3 changed files with 35 additions and 0 deletions
+4
View File
@@ -92,6 +92,10 @@ expect Nix to report the correct hash on a failed build (or use `nix-prefetch`/`
`app.php`, and guards one-time actions (`migrate`, `db:seed`, admin account creation) behind marker files
(`.initial-migration`, `.db-seeded`, `.admin-created`) in `dataDir`. `phpfpm-invoiceninja.service` and
`invoiceninja-queue-worker.service` both depend on it.
- `invoiceninja-scheduler.timer`/`.service` run `artisan schedule:run` every minute — this is what drives
Invoice Ninja's own internal cron-scheduled jobs (recurring invoices, scheduled reports, etc.); without it the
app's dashboard reports "cron jobs are not enabled". Laravel's scheduler is just a dispatcher, so this one
timer is sufficient regardless of how many scheduled tasks Invoice Ninja itself defines.
- `invoiceninja-manage` is a generated wrapper script (`invoiceninja-manage <artisan-args>`) that `cd`s into the
package output and runs `php artisan` as the configured service user (via `sudo` if invoked as another user).
It's added to `environment.systemPackages`, so it's the normal way to run artisan commands