Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sentinel Laravel Package

laravel/sentinel

Laravel Sentinel adds a lightweight, configurable guard layer to your Laravel app. Simple to install and expressive to use, it helps you monitor and protect key parts of your project, integrating cleanly with Laravel's config and service container without extra boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Install, then pin — don't float.

composer require laravel/sentinel

The entire release history is v1.0.1 and v1.1.0, and between them the changelog contains four PRs: two CI/test-workflow typos, a Laravel 13 support bump, and a fix for "blocking [a] docker container when accessed from local machine." That is not enough surface area to justify a caret constraint in production. Pin "laravel/sentinel": "1.1.*" and treat 1.x as pre-stable until you've read the source yourself.

Read these three things before writing a line of code.

  1. composer.json — the illuminate/* constraints tell you whether Laravel 13 is a floor, a ceiling, or the only supported target. If you're on 10/11/12, this may not install at all. Check before you plan work around it.
  2. src/ — locate the service provider, the publishable config file (if one exists), the check contract/interface, and the notification channel wiring. Those four things are the package's real API, regardless of what the description claims.
  3. php artisan list — confirm the actual command name(s) it registers. Do not assume sentinel:check or similar from the README-style description; this package has no README in the supplied material.

Resolve the scope question first, because the description and the changelog disagree. The package blurb promises health checks for database, cache, storage, queues, and custom services, audit logging, notification-channel alerting, and access-control hooks. The changelog evidences almost none of it, and the one described behavior — Docker container networking when accessed from localhost — is a signature of dev-environment tooling, not production monitoring. There is also a persistent name collision with cartalyst/sentinel, the historic auth/RBAC library. Anything you write here is an uptime/health concern, not authentication. Confirm which one you actually installed.

Publish and inspect config, if there is any.

php artisan vendor:publish --provider="Laravel\Sentinel\SentinelServiceProvider"

Adjust the namespace to whatever the provider is actually called once you've found it in src/. If nothing publishes, the package is likely convention-driven and you'll wire it through code rather than config — check the provider's register()/boot() for the real extension points.

First use case: one check, run by hand, no schedule, no notifications. Point it at a known-good database, run the command, confirm a pass. Then break it deliberately — bogus host in the config, stop Redis, revoke storage credentials — and confirm you get a failed result rather than an exception, a hang, or a silent success. A health checker that can't fail loudly is worse than no health checker at all, and with zero public dependents you are the first person to test this path.

Implementation Patterns

Split cheap liveness from expensive diagnostics. Cheap checks — DB SELECT 1, cache ping, app boot — run every minute. Expensive checks — storage write/read/delete round-trip, queue depth, third-party API reachability — run every 5–15 minutes. Register them as two separate scheduled commands rather than one, so a slow storage probe can't delay your liveness signal.

Schedule via the framework, not the package. Wire it in routes/console.php (or bootstrap/app.php on newer skeletons):

use Illuminate\Support\Facades\Schedule;

Schedule::command('sentinel:check --group=liveness')
    ->everyMinute()
    ->withoutOverlapping()
    ->runInBackground();

Schedule::command('sentinel:check --group=diagnostics')
    ->everyFiveMinutes()
    ->withoutOverlapping();

withoutOverlapping() matters here: if a check hangs on a dead dependency, you want skipped runs, not a pileup of blocked workers. runInBackground() keeps a slow check off the scheduler's critical path.

Write custom checks as read-only, idempotent, and hard-timed-out. Implement whatever check contract the package exposes (find it in src/Contracts or equivalent), resolve dependencies through the container, and wrap every network call in an explicit timeout. Never write to production tables to prove writability; use a dedicated scratch prefix and clean up after yourself. Keep these classes in app/Support/Health/ so a vendor update can't clobber them and so they're trivially portable if you swap the package out later.

namespace App\Support\Health;

class BillingApiReachable implements Check
{
    public function __construct(private Client $http) {}

    public function run(): Result
    {
        try {
            $response = $this->http->timeout(3)->get(config('services.billing.url') . '/ping');
            return $response->successful() ? Result::pass('billing-api') : Result::fail('billing-api', $response->status());
        } catch (ConnectionException $e) {
            return Result::fail('billing-api', $e->getMessage());
        }
    }
}

Route alerts to infrastructure you already own. Mail, Slack webhooks, or a custom channel through Laravel's notification system. The value of the package is that checks and routing live in one place; the risk is that a bespoke alerting path becomes another thing to page-debug. Reuse your existing notifications channel config, and send to an on-call channel rather than an individual.

Gate noisy environments. Local and CI should run checks without alerting: ->when(fn () => app()->isProduction()) on the scheduled entries, or an env-driven enabled flag. A failing health check firing Slack messages from every developer's sail up will get the package ripped out within a week.

Complement, don't replace, your external prober. If you already pay for an uptime service or use Forge/Envoyer health hooks, keep it. Point the external prober at /up (Laravel's built-in endpoint) and use Sentinel for the internal dependency checks the outside world can't see — queue depth, cache reachability, storage writability. That split plays to its actual strengths.

Test checks in isolation, not through the command. Instantiate each check class in a feature test, fake the underlying dependency (Http fake, a broken DB connection, a read-only filesystem), and assert the result object. Testing through the artisan command adds a layer you can't control and hides which check produced which outcome. If the package ships assertion helpers or a fake, use them; if not, keep your Result-shaped return values simple enough to assert against directly.

Persist outcomes somewhere you control. There is no evidence in the changelog of time-series storage, retention, or a dashboard. If you want history — "how often did the queue check fail last month?" — log structured results to your existing log stack or a table you own, and treat the package as the runner, not the record.

Gotchas and Tips

In-app monitoring goes silent exactly when you need it. Sentinel runs inside the application it monitors. If PHP-FPM is down, the container is OOM-killed, or the scheduler isn't running, no check runs and no alert fires. You will discover the outage from users. Pair it with an external prober hitting /up from outside your infrastructure — that is the non-negotiable complement, not a nice-to-have.

Alert delivery through the queue can deadlock with the failure it's reporting. If notifications are queued and your queue is the thing that just failed, the alert never leaves. Either use sync for health notifications, or explicitly configure a separate queue/connection for alerting that doesn't share fate with the checked dependency.

Verify a failing check actually notifies, end to end, before you trust it. The single most important spike question: does a failing check deliver a Slack/mail message, or does it only print pass/fail to stdout? The changelog does not evidence notification delivery. Run the negative path in staging, confirm the message lands in the channel, then close the loop.

Zero dependents means you're the first serious adopter. Every edge case is yours, the Laravel 14 upgrade path is yours, and the first bug report is yours to write. That's tractable — it's a leaf dependency, removal is a composer remove plus deleting your app/Support/Health/ classes — but name an owner and an upgrade watcher rather than assuming maintenance happens.

The Docker local-access fix hints at binding/host behaviour to watch. v1.1.0's only behavior change was "avoid blocking [a] docker container when accessed from local machine." If your app runs behind Sail, Docker Compose, or a load balancer with host-header rewriting, check that check execution doesn't inherit that same blocking path in production. Test from inside the container and from the host.

Run php artisan config:cache before trusting any published config. A published config file with closures, env-dependent arrays, or non-cacheable values will break deploy pipelines in ways that never show up locally. Cache config in CI early.

The changelog tells you what to expect from composer update. Two patch releases, both housekeeping. That is a good sign for API stability and a bad sign for maturity — there's no evidence anyone has stress-tested this against real dependency failures. Read src/ before you build a custom check contract on top of it, because a 1.x minor could still move interfaces.

Extension points are the whole value proposition — inventory them explicitly. Before adopting, write down: the check contract, the notification channel contract, the config schema, and the command signature. If any of those four is missing or requires forking, the package is a liability rather than a convenience, and ~150 lines of hand-rolled Artisan commands plus an existing health endpoint becomes the better answer.

Don't let the name reintroduce the auth reading. laravel/sentinel is not cartalyst/sentinel. If a teammate proposes it for guards, roles, or access control based on the description's "access control hooks" line, stop them — use Fortify, Sanctum/Passport, or your IdP. Scope creep from a name collision is the most expensive failure mode here, and it costs nothing to prevent.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo
bernskioldmedia/laravel-harvest
bernskiold/laravel-data-scrubber
bernskiold/laravel-currency-converter
bernskiold/laravel-campaign-monitor
bernskioldmedia/laravel-autotranslate
siberfx/telegram-bot
roy-sandip/laravel-view-extended
gregsphotography/site-builder-core
roy-sandip/laravel-view
anodyne/blade-fluentui-icons
webx-ui/module-catalog-collections