Skip to content

Monitoring · Open source

Uptime Monitor

Lists the sites spatie/laravel-uptime-monitor watches with their uptime and certificate status, and lets you add, edit, check, turn on and off and delete them from your panel.

Filament 4 and 5 Laravel 12 and 13 PHP 8.2+ v1.0.1 Free · MIT
Uptime Monitor: Lists the sites spatie/laravel-uptime-monitor watches with their uptime and certificate status, and lets you add, edit, check, turn on and off and delete them from your panel.

What it solves

spatie/laravel-uptime-monitor checks your sites and their certificates on a schedule, but you manage it from the command line.

Seeing which site is down, which certificate is about to expire or whether the checks still run means opening a terminal or waiting for a notification.

This plugin adds the screen: a Monitors page with each site's uptime status and how long it has been that way, its certificate status and expiry date and when it was last checked, with filters, a form to add and edit monitors, Check now for one monitor or a selection, turning monitors on and off, a status widget and a navigation badge for monitors that need attention. It uses the package's own model, table, config, checks and events, adds no tables of its own and schedules nothing: the package's Artisan commands still run the scheduled checks. Out of the box, anyone who can open the panel can see, add, change, check and delete monitors, unless a policy for the monitor model or your own callback says otherwise. URLs on localhost or private addresses are refused from the panel unless you allow them. Built on spatie/laravel-uptime-monitor by Spatie. An independent plugin, not made or endorsed by Filament or Spatie.

  • A Monitors page with the URL, the uptime status (Up, Down, Not checked yet or Off) and since when, the certificate status (Valid, Expires soon, Invalid, Not checked yet or Off) with its expiry date, and when it was last checked
  • Hover a down site or an invalid certificate to read the reason the package recorded
  • Filters for uptime, certificate, on or off, and Needs attention; search by URL
  • Add and edit: URL, uptime and certificate checks, interval, HTTP method, text to look for, request body and extra headers; changing the URL clears the old status
  • Check now for one monitor, or for up to 20 selected at once, with the package's own checks and config; by default each user may check 30 monitors a minute
  • Turn monitors on and off, one at a time or in bulk, with the package's enable() and disable()
  • A status widget on the dashboard and above the list: up, down, certificate problems and the last check, with a hint when the scheduler seems to have stopped
  • A navigation badge counting monitors that are down or whose certificate is invalid or expires soon
  • Permissions from a policy on the monitor model or an authorizeUsing() callback
  • localhost and private, loopback, link-local and other reserved addresses refused from the panel unless you call allowPrivateHosts(), and the Check now request pinned to the address that was checked
The Monitors page in a light Filament panel, with Uptime monitors in the navigation under Monitoring and a badge of 3. An Uptime widget shows 3 up of 4 monitored, 1 down (https://api.example.com), 2 certificate problems (invalid, or expiring within 10 days) and a last check 1 minute ago with 4 monitors on. Below it a table of five monitors with URL, Uptime, Certificate and Last checked columns: api.example.com down for 4 minutes with a valid certificate; blog.example.com up with a certificate that expires soon; legacy.example.com up with an invalid certificate that expired Oct 20, 2026; shop.example.com up and valid; and staging.example.com turned off. Each row that is on has Check now and Edit actions.
The Monitors page in a light Filament panel, with Uptime monitors in the navigation under Monitoring and a badge of 3. An Uptime widget shows 3 up of 4 monitored, 1 down (https://api.example.com), 2 certificate problems (invalid, or expiring within 10 days) and a last check 1 minute ago with 4 monitors on. Below it a table of five monitors with URL, Uptime, Certificate and Last checked columns: api.example.com down for 4 minutes with a valid certificate; blog.example.com up with a certificate that expires soon; legacy.example.com up with an invalid certificate that expired Oct 20, 2026; shop.example.com up and valid; and staging.example.com turned off. Each row that is on has Check now and Edit actions.

Install

Requires PHP 8.2+, Filament 4 and 5, and Laravel 12 and 13.

composer require amjadiqbal/filament-uptime-monitor

Usage

use AmjadIqbal\FilamentUptimeMonitor\UptimeMonitorPlugin;

// AdminPanelProvider
$panel->plugin(UptimeMonitorPlugin::make());

// routes/console.php: the plugin schedules nothing itself
Schedule::command('monitor:check-uptime')->everyMinute();
Schedule::command('monitor:check-certificate')->daily();

Setup

On Laravel 13, install with -W. A new Laravel 13 app ships Guzzle 8, while spatie/laravel-uptime-monitor needs Guzzle 7 (which Laravel 13 also supports), so a plain composer require fails and changes nothing; -W lets Composer move Guzzle back to 7. The plugin needs spatie/laravel-uptime-monitor 4.7 or later and PHP 8.2 or later; Filament 5 and Laravel 13 were tested from PHP 8.3. If the uptime monitor package is not set up yet, publish its config and migration and migrate. The plugin does not schedule anything, so schedule the package's own commands. It uses only Filament's components, so there are no assets to build or publish.

  1. 1 Laravel 12: composer require amjadiqbal/filament-uptime-monitor
  2. 2 Laravel 13: composer require amjadiqbal/filament-uptime-monitor -W
  3. 3 php artisan vendor:publish --provider="Spatie\UptimeMonitor\UptimeMonitorServiceProvider"
  4. 4 php artisan migrate
  5. 5 In routes/console.php, schedule monitor:check-uptime (for example every minute) and monitor:check-certificate (for example daily).
  6. 6 Add ->plugin(UptimeMonitorPlugin::make()) to the panel provider.

How checks run

The scheduled checks are the package's, not the plugin's. In Spatie's code, monitor:check-uptime checks each monitor that has uptime checks on and is due: not checked yet, down, or last checked at least its interval ago. monitor:check-certificate checks every monitor with certificate checks on. Check now calls the same check code directly for the monitors you pick, whatever their interval, so the package's config and events apply as usual.

  • The plugin adds no tables or migrations and does not change how the scheduled checks or notifications work.
  • Check now fires the package's events, so its notifications go out as for a scheduled check.
  • The package saves the result before it fires its events. If a notification channel fails (for example the default slack channel with no working webhook), the result is still saved and the panel shows the error.
  • The widget's last check is the most recent uptime check of any monitor, scheduled or by hand.

The Monitors page

Each row shows the URL, the uptime status and, for a site that is up or down, since when, the certificate status with its expiry date (or the date it expired), and when it was last checked. Hover a down status or an invalid certificate to read the failure reason. The page is sorted by URL and search matches the URL.

  • Uptime: Up, Down or Not checked yet from the package's uptime_status; Off when uptime checks are off.
  • Certificate: Valid, Invalid or Not checked yet from certificate_status; Expires soon when it is valid and expires within the package's fire_expiring_soon_event_if_certificate_expires_within_days (10 by default); Off when certificate checks are off.
  • Filters: uptime, certificate, Monitoring (on or off) and Needs attention, which shows monitors that are down or whose certificate is invalid or expires soon.
  • The navigation badge counts the same Needs attention monitors and is hidden at zero or with ->navigationBadge(false).
  • Monitors are global: the package's table has no tenant column, so in a multi-tenant panel every tenant sees the same monitors. Restrict the page with a policy or authorizeUsing().

Adding and editing

The form writes to the package's monitors table through its model, so a monitor added here is checked by the package's scheduled commands like one added with monitor:create. A new monitor's interval defaults to the package's uptime_check.run_interval_in_minutes.

  • URL: a full http:// or https:// address, stored without a trailing slash. A URL that is already monitored is refused.
  • Uptime and certificate checks can be turned on separately. Certificate checks are only allowed for https URLs.
  • HTTP method, text to look for (not with HEAD, which has no body), a request body for POST, PUT, PATCH and DELETE, and extra request headers.
  • A response checker field appears when you list your own checker classes with ->responseCheckers([...]); otherwise the checker from the package's config is used.
  • Changing the URL of an existing monitor resets its uptime and certificate status, failure reasons, last check and certificate details.

Check now

Check now runs the uptime check and, when it is on, the certificate check for one monitor, from its row or its edit page, and shows the result straight away: up or down with the reason, and the certificate expiry or why it is invalid. It is offered only for monitors that are on. To check several, select them and use Check selected now.

  • A selection of more than 20 monitors is refused as a whole; change the cap with ->maxChecksPerRequest().
  • Each user may check 30 monitors a minute by default (->checksPerMinute()). A bulk check counts every selected monitor that is on and that the user may check, including one then skipped for a private address; monitors that are off or that the user may not check are not counted. A check that would go over the limit is refused as a whole with "Too many checks. Try again in a minute."
  • The bulk result reports how many were up and down, and separately how many were skipped because they are off, because their URL points to a private address, or because the user may not check them.

Turning monitors on and off

Turn off calls the package's disable(), which stops both uptime and certificate checks, after a confirmation; the monitor's history is kept. Turn on calls enable(), which turns uptime checks on, and certificate checks too for an https URL. Both work on one monitor from the row menu or on a selection.

The status widget

The Uptime widget sits on the dashboard and above the Monitors page, and refreshes every 60 seconds. ->dashboardWidget(false) and ->listWidget(false) leave it off either place. Users who may not see the monitors do not see it.

  • Up: monitors that are up, out of the number that are on.
  • Down: the number down, with up to three of their URLs.
  • Certificate problems: certificates that are invalid or expire within the package's threshold.
  • Last check: how long ago the latest check ran. It asks "Is the scheduler running?" when monitors are on and no check has run for three times the shortest interval among monitors with uptime checks on (the package's run_interval_in_minutes when there are none), so monitors with long intervals don't set it off.

Who can do what

Out of the box, with no callback and no policy for the monitor model, every user who can open the panel can see, add, edit, check, turn on and off and delete monitors. Checks run in this order:

  • Your callback: ->authorizeUsing(fn (string $ability, ?Monitor $record, $user): bool => ...) decides alone when set. $ability is one of viewAny, view, create, update, delete, deleteAny and checkNow.
  • A policy for the monitor model (Spatie's Monitor, or your monitor_model): the plugin uses viewAny, create, update, delete and deleteAny. Turning on and off uses update. Check now uses a checkNow method when the policy has one, and update when it does not.
  • A policy method that does not exist allows the action.
  • Check now and turning on and off in bulk check every selected monitor and report the ones they skipped.
UptimeMonitorPlugin::make()
    ->authorizeUsing(fn (string $ability, ?Monitor $record, $user): bool => $user?->is_admin ?? false)
    ->navigationGroup('Monitoring')
    ->checksPerMinute(30)
    ->maxChecksPerRequest(20);

Private addresses

Check now makes your server send a request to the monitor's URL, so a panel user could use it to reach internal services. The plugin refuses such URLs unless you call ->allowPrivateHosts(). The guard covers the panel only: the package's scheduled monitor:check-uptime checks every stored monitor as it is.

  • Refused: localhost and names ending in .localhost, and any IP address outside the public range, which covers private, loopback, link-local, carrier-grade NAT (100.64.0.0/10), documentation and other reserved ranges, in IPv4 and IPv6, including IPv4 written as ::ffff:127.0.0.1.
  • A host name is looked up in DNS (A and AAAA records) and refused if any address it resolves to is private.
  • The check runs when a monitor is saved from the form, and again right before each Check now; a monitor that fails it is skipped and reported. A host that does not resolve passes this check, so a monitor whose DNS is not live yet can be saved.
  • The Check now uptime request then resolves the host once more and uses that answer: a host that does not resolve is marked down ("Could not resolve host"), one that now resolves to a private address is marked down without a request, and otherwise curl is pinned to a checked address (CURLOPT_RESOLVE, the first IPv4 address when there is one), so DNS can't switch to a private address in between.
  • During a Check now uptime check, a redirect to a private host is refused and the check fails.
  • The lookup, pinning and redirect refusal run in the plugin's own subclass of the package's request action. If you set your own actions.send_uptime_check_request in the package's config, the check before Check now still applies, but pinning and redirect refusal are up to your action.
  • The certificate check is the package's own: it opens a TLS connection to port 443 of the host and reads only the certificate. It is covered by the check before Check now, but it is not pinned.

Configuration

Everything is optional. ->resource(false) leaves the Monitors page out and ->resource(MyMonitorResource::class) swaps in your own subclass. The rest comes from the package's config/uptime-monitor.php: monitor_model is the model the page lists and edits, and the uptime_check settings and actions.send_uptime_check_request decide how Check now sends its request (timeout, headers, Guzzle options, user agent). English texts are included; php artisan vendor:publish --tag=filament-uptime-monitor-translations publishes them to translate or change.

UptimeMonitorPlugin::make()
    ->navigationGroup('Monitoring')
    ->navigationSort(10)
    ->navigationLabel('Uptime')
    ->navigationBadge(false)
    ->dashboardWidget(false)
    ->listWidget(false)
    ->responseCheckers([
        \App\Uptime\JsonHealthChecker::class => 'JSON health endpoint',
    ])
    ->allowPrivateHosts();

Credits

Uptime Monitor is built on spatie/laravel-uptime-monitor by Spatie (MIT), which stores the monitors, runs the uptime and certificate checks and sends the notifications. This plugin adds the Filament side: the page, the form, the actions, the widget and the permission and address checks. It is not affiliated with or endorsed by Spatie.

Hire me

Need this built into your app, or something custom?

I wrote Uptime Monitor. I can wire it into your Filament panel, extend it for your case, or build the feature around it. Tell me what you need and you'll get a plan and a quote, free.

Support

Found a bug or want a feature? Open an issue on GitHub. For help adding it to your own project, use the quote form above.

Need something built?

Free quote in 60 seconds