taecontrol/moonguard
MoonGuard is a Laravel package for simple, flexible role and permission management. Define roles and abilities, assign them to users, and protect routes and resources with a clean interface and minimal configuration. It keeps authorization logic organized and easy to maintain.
MoonGuard is a security-monitoring companion for Laravel apps: it records suspicious/inbound attempts (failed auth, 404/403 probes, blocked requests), surfaces them in a Livewire dashboard, and pushes alerts to Telegram/email. It is not a WAF — treat it as detection + notification, not prevention.
Minimal path:
composer require taecontrol/moonguardphp artisan moonguard:install — this publishes config/moonguard.php, publishes/runs migrations, and registers the dashboard route scaffolding.php artisan migrate. In production, review the migrations first; you are adding tables to an existing database, not a fresh one.config/moonguard.php (Telegram bot token + chat id, and/or mail recipient). Without a channel configured the package is effectively a silent logger.First real use case: turn it on in a staging environment, hit a handful of non-existent routes to generate 404 attempts, and confirm both (a) rows appear in the dashboard and (b) the alert arrives in Telegram. That validates the whole chain — ingestion, storage, notification — in ten minutes.
Laravel 11 note (v1.2.3): this release bumps the dependency constraints for Laravel 11. If you were holding the package back on Laravel 10 because of a composer conflict, that's now unblocked. If you are already on an older MoonGuard with an existing published config and migrations, re-publish carefully (see Gotchas) — do not blindly overwrite.
Middleware-first ingestion. Register the package's request-recording middleware in the web group (or a global stack) so every request is eligible for inspection. Day-to-day, the useful pattern is to scope it: apply the middleware everywhere, but tune the thresholds in config (which status codes count as an attempt, whether to ignore known bot User-Agents, which paths to exclude). Otherwise your own healthchecks and asset 404s generate noise that trains you to ignore alerts.
Alert routing per environment. Point Telegram at a dedicated security channel and mail at an on-call alias, and make the config environment-aware (MOONGUARD_TELEGRAM_* env vars in production, LOG driver locally). A package that notifies on every probe in local dev becomes background noise fast.
Pair it with your auth events. MoonGuard's attempt records are most valuable when correlated with Illuminate\Auth\Events\Failed and rate-limiter hits. A practical pattern: keep MoonGuard as the raw signal capture, and add a small listener that escalates to an incident channel when the same IP produces N attempts across both sources within a window.
Dashboard as a triage queue, not a firewall console. The realistic workflow is a daily/weekly review: filter by IP and time range, block the offending IP at your edge (Cloudflare/nginx/RateLimiter), and mark the issue handled. Build that habit rather than wiring automated blocking into the package — MoonGuard's data is retrospective.
Scheduled housekeeping. Attempt tables grow monotonically. Add a scheduled command (or a model prune) to delete records older than 30–90 days; retention policy is your decision, not the package's default.
Integration tips. Keep the package's migrations separate from your app's in version control expectations — if you squash your app migrations, the package tables still need to exist. And export/forward alerts to your existing observability stack (Slack webhook, Sentry breadcrumb) rather than asking the team to watch a second dashboard.
vendor:publish --force will overwrite tuned config/moonguard.php. Diff first: php artisan vendor:publish --tag=moonguard-config into a temp path, or copy values by hand. Same for published migrations — never re-run a publish that would collide with an existing table.composer update still fails, check for a conflicting package pinning the old framework constraints rather than assuming MoonGuard is at fault; composer why-not taecontrol/moonguard isolates it quickly.-100 prefix for channels), and whether the notifiable condition in config filters the severity out. Failures here are often swallowed — run with LOG_LEVEL=debug and inspect laravel.log for driver exceptions.sync driver for low-volume security alerting, or monitor queue depth — silence should not be indistinguishable from "no attacks".follow-redirects-style dependency bumps. The dependabot commit in this release is a dev-tooling change with no runtime impact for your app; don't add it to your changelog or regression checklist. Focus upgrade testing on the Laravel 11 framework jump: middleware registration (Laravel 11 changed the bootstrap/app.php model), exception handling, and the dashboard route registration under the new skeleton.Upgrade verdict for v1.2.3: low-risk, additive compatibility release. Run it as part of your Laravel 11 migration rather than as a standalone change, and re-verify the notification path and dashboard authorization after the framework jump — those are the two things most likely to break quietly.
How can I help you explore Laravel packages today?