laravel-server-monitor: server health checks from inside your Laravel app
Don't let your servers just melt down
At a glance
- What is it?
- Spatie's laravel-server-monitor is an MIT licensed Laravel package that runs disk space, MySQL, Memcached and Elasticsearch checks over SSH against your servers and notifies you over Slack or mail when something degrades, with custom checks and overridable models. It suits teams already running Laravel who want a lightweight monitor without a new agent, and it does not replace a full infrastructure monitoring stack.
- Who is it for?
- laravel-server-monitor suits a team whose production fleet is small enough to watch with a scheduled Artisan task inside an existing Laravel application, since it needs no agent on the target hosts beyond SSH access and gives you failure, warning and restore notifications without a separate dashboard.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A monitor that runs inside the app it watches
The package description says it plainly: don't let your servers just melt down.
The README frames the problem the way an operations-minded developer would. We all dream of servers that need no maintenance at all, but in reality disks can get full, processes can crash, and the server can run out of memory. The package keeps an eye on the health of all your servers, ships with a few checks out of the box, and makes adding new checks a breeze.
The design decision that defines the whole tool is where the monitor lives. There is no daemon, no agent and no sidecar. The checks are performed by the Laravel application itself, over SSH, on a schedule. The package provides the check definitions, the notification plumbing and the persistence; the transport is SSH to the target hosts.
That has a clear upside. A team that already runs Laravel somewhere does not need to introduce a new piece of infrastructure, a new configuration format or a new deployment target. It runs a scheduled task, and the existing application has the credentials, the network position and the notification channels.
The flip side is equally clear and is worth naming up front. If the Laravel application is the thing that is down, the monitor is down with it. A package that lives inside the thing it watches cannot report its own outage, so this complements a monitoring stack rather than replacing one.
The project is MIT licensed, published on Packagist as spatie/laravel-server-monitor, with documentation at docs.spatie.be/laravel-server-monitor/v1/introduction.
Installation is one Composer command and three Artisan calls
The install path is conventional Laravel package work, and the README lays it out in order.
composer require spatie/laravel-server-monitorIn Laravel 5.5 the service provider is registered automatically. In older versions of the framework you have to install it yourself in the config/app.php providers array.
// config/app.php
'providers' => [
...
Spatie\ServerMonitor\ServerMonitorServiceProvider::class,
];Then the migrations are published and run, which creates the hosts and checks tables.
php artisan vendor:publish --provider="Spatie\ServerMonitor\ServerMonitorServiceProvider" --tag="migrations"
php artisan migrateFinally the configuration is published.
php artisan vendor:publish --provider="Spatie\ServerMonitor\ServerMonitorServiceProvider" --tag="config"Two of those steps are worth pausing on. The database side is not optional in the same way a log-only monitor would be: the package persists hosts and their check results, and the notification behaviour depends on that state, because a check that fails then succeeds has to be recognised as a restoration. So this package needs a database, and a writable one, in the same way your application does.
The published configuration file is where the behaviour is decided, and the README includes its full contents. That makes the config file the API surface of the package, and it is where the rest of this article spends its time.
Four checks ship by default and each one is a class you extend
The checks section of the config file is short, and it maps names to classes.
'checks' => [
'diskspace' => Spatie\ServerMonitor\CheckDefinitions\Diskspace::class,
'elasticsearch' => Spatie\ServerMonitor\CheckDefinitions\Elasticsearch::class,
'memcached' => Spatie\ServerMonitor\CheckDefinitions\Memcached::class,
'mysql' => Spatie\ServerMonitor\CheckDefinitions\MySql::class,
],So out of the box the package can check free disk space, and it can check MySQL, Memcached and Elasticsearch. The documentation links to a page of built in checks and a separate page on writing your own, and the config comment states the only requirement for a custom check: it should extend the Spatie\ServerMonitor\Checks\CheckDefinitions\CheckDefinition class.
That single inheritance rule is what makes the package extensible without being a framework of its own. A check is a class, and because the check list is config rather than code, you can add a check to one environment and not another without touching the application logic.
The disk space check is the one with visible thresholds in the config, and they are the ones you are most likely to change.
'diskspace_percentage_threshold' => [
'warning' => 80,
'fail' => 90,
],Warning at 80 percent used and fail at 90 percent is a sensible default for a single volume, but it says nothing about which volume, and a database server with a small system partition and a large data partition will need those numbers adjusted per host rather than globally.
Four notification events, and a throttle that stops the noise
The notifications configuration tells you what happens when a check changes state, and it is built around four event classes.
'notifications' => [
Spatie\ServerMonitor\Notifications\Notifications\CheckSucceeded::class => [],
Spatie\ServerMonitor\Notifications\Notifications\CheckRestored::class => ['slack'],
Spatie\ServerMonitor\Notifications\Notifications\CheckWarning::class => ['slack'],
Spatie\ServerMonitor\Notifications\Notifications\CheckFailed::class => ['slack'],
],Note the shape of the array. The key is the event class and the value is the list of channels it fires on. CheckSucceeded is mapped to an empty array, which means success notifications are defined but disabled by default, while restore, warning and failure all go to Slack.
The restore event is the one that distinguishes a serious monitoring package from a noisy one. A check that is failing and then recovers is a different piece of information from a check that is failing, and having a dedicated event for it means you can be told when the problem is over rather than inferring it from the absence of new alerts.
The throttle is the other important part.
'throttle_failing_notifications_for_minutes' => 60,The comment explains the reasoning: to avoid burying you in notifications, only one is sent every given amount of minutes when a check keeps emitting warnings or keeps failing. That is a rate limit on repeats, not on distinct events, and it means a host that fails every minute produces one message an hour until it recovers, at which point the restore event fires.
The two channels are mail and Slack. Mail takes an address, and Slack takes a webhook URL read from the SERVER_MONITOR_SLACK_WEBHOOK_URL environment variable, so the webhook is not written into a config file that ends up in version control.
SSH concurrency is where the real tuning happens
The most operationally significant setting in the config file is a single integer.
'concurrent_ssh_connections' => 5,
'ssh_command_suffix' => '',The comment explains that the performance of the package can be increased by allowing a high number of concurrent SSH connections, and to set this to a lower value if you are getting weird errors running the check.
That maps directly onto how the monitor works. Each check against each host is an SSH session, so a fleet of twenty machines with four checks each is eighty SSH connections in a run, and the concurrency value decides how many are open at once. Too low and the run is slow, too high and you hit SSH server limits, or the ephemeral port range on the application server, or file descriptor limits. When the docs mention weird errors, this is usually the knob.
The second setting, ssh_command_suffix, is a string appended to the SSH command the package generates. It is the escape hatch for environments where the default invocation is not enough, for instance when the target requires a specific port or an identity file, and it is small on purpose, since the package is generating the command and you are only allowed to append to it.
The way the check is run is also open to influence, through the process_manipulator setting, which is set to the Passthrough manipulator by default.
'process_manipulator' => Spatie\ServerMonitor\Manipulators\Passthrough::class,The config comment explains that right before running a check its process will be given to this class, where you can perform last minute manipulations on it before it is actually run, and that the class should implement Spatie\ServerMonitor\Manipulators\Manipulator. A manipulator that wraps the process gives you a place to inject environment variables or adjust arguments per check.
The models are replaceable and there is no interface to look at
Two config entries let you swap the persistence layer, and both follow the same pattern of extend and replace.
'host_model' => Spatie\ServerMonitor\Models\Host::class,
'check_model' => Spatie\ServerMonitor\Models\Check::class,The comment for each one says you can specify your own model to add or modify behaviour, with the only requirement that they extend the model provided by the package. So if your application already has a Host concept, or you need extra columns on a check record, you extend the shipped model and point the config at your subclass, and the package uses it.
That is a good sign about how the package is built. Almost every extension point is a class you extend rather than a callback you register, and the two model hooks sit alongside the check definition hook and the process manipulator hook, giving you four separate places to change behaviour without forking the package.
What the package does not have is a user interface. The README has a section headed Need a UI, and it states plainly that the package does not come with any screens out of the box, pointing instead to a Nova package by @paras-malhotra for monitoring.
So the default experience is: a scheduled task, a database table, and notifications in Slack or email. If you want a dashboard, you either build one on the models you have just learned how to extend, or you add a third party Nova package, and the latter is the kind of dependency that has to be checked for Laravel version compatibility separately from the monitoring package itself.
Version 1.10, a MIT licence and a mid summer push
The release history shows a steady patch line rather than feature jumps. Version 1.10.3 was published on 2026-07-28, version 1.10.2 on 2026-02-21 and version 1.10.1 on 2025-02-21.
That is a package with a stable API and a maintainer who ships fixes when they are needed rather than on a release train, and the last push to the repository was on 2026-07-28, the same day as the 1.10.3 release.
The licence is MIT, with the LICENSE.md file in the repository root, and the code is a normal Composer package with a composer.json, a src directory, a config directory, a database directory for the migrations, a docs directory, a tests directory and a phpunit.xml.dist for the test configuration. The code style is enforced with php-cs-fixer through the .php_cs.dist.php configuration, and there is a CHANGELOG.md.
One more detail from the README is worth repeating because it affects how you schedule this. The documentation site is versioned, with the introduction page at docs.spatie.be/laravel-server-monitor/v1/introduction, so the v1 documentation is what corresponds to the 1.x releases you would install from Packagist.
The pattern the package settles into is a good one for its size. Configuration is the extension point, checks are classes, models are replaceable, the process is manipulable, and the notification events are first class. What you give up by choosing it is the scale: no metrics history, no dashboard, no alerting rules, and the blind spot of a monitor that lives inside the application it is watching.
Editorial conclusion
laravel-server-monitor suits a team whose production fleet is small enough to watch with a scheduled Artisan task inside an existing Laravel application, since it needs no agent on the target hosts beyond SSH access and gives you failure, warning and restore notifications without a separate dashboard. It does not suit a team that wants metrics, dashboards, alerting on multiple channels, or a monitor that keeps running when the application is down, because the monitor lives in the application. Before you rely on it, confirm that SSH from your application server to the monitored hosts is non interactive, review the concurrent_ssh_connections value against your server limits, and decide whether the built in thresholds are meaningful for your disks, since diskspace_percentage_threshold warns at 80 percent and fails at 90 by default and the last push to the repository was on 2026-07-28.
Frequently asked questions
How do I install laravel-server-monitor?
Run composer require spatie/laravel-server-monitor, then publish and run the migrations with php artisan vendor:publish --provider="Spatie\ServerMonitor\ServerMonitorServiceProvider" --tag="migrations" followed by php artisan migrate, and publish the config with the same vendor:publish command using the config tag.
Which checks does laravel-server-monitor support out of the box?
The published config lists four: diskspace, elasticsearch, memcached and mysql. Custom checks are supported and must extend the Spatie\ServerMonitor\Checks\CheckDefinitions\CheckDefinition class.
How does laravel-server-monitor notify me?
Over mail or Slack, using a webhook URL read from the SERVER_MONITOR_SLACK_WEBHOOK_URL environment variable. Notifications fire on the CheckRestored, CheckWarning and CheckFailed events, with CheckSucceeded defined but disabled by default.
Can I add my own checks and models to laravel-server-monitor?
Yes. A custom check should extend Spatie\ServerMonitor\Checks\CheckDefinitions\CheckDefinition, and the host_model and check_model config entries let you substitute your own classes as long as they extend the models shipped with the package.
Does laravel-server-monitor come with a web interface?
No. The README states that the package does not come with any screens out of the box, and points to a Nova package by @paras-malhotra for a monitoring interface.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/spatie-laravel-server-monitor)Was this useful?