Queopius Sentinel is a production-ready Laravel package for HTTP security hardening with great DX:
- Security headers (HSTS, CSP, Referrer-Policy, and more)
- HTTPS enforcement middleware
- Optional dashboard UI for audit/inspection
- Dashboard metrics with CSP-safe native charts and hardening plan
- Optional CSP reports endpoint + storage
- Security audit, endpoint scan, and report pruning commands
- Publishable views for full UI customization
- Safe-by-default with preset support
- Progressive rollout path (CSP report-only first)
- Works as reusable package and monorepo local package
- Built for Laravel 11, 12, and 13
Queopius Sentinel follows SemVer for package versions.
MAJOR: breaking changesMINOR: new features, backward compatiblePATCH: fixes and internal improvements
| Sentinel version | Laravel | PHP | Status |
|---|---|---|---|
2.x |
11.x, 12.x |
8.2, 8.3, 8.4 |
Active |
2.x |
13.x |
8.3, 8.4 |
Active |
Composer constraints (current):
illuminate/*:^11.0|^12.0|^13.0php:^8.2
Laravel 13 requires PHP ^8.3, so PHP 8.2 support applies to Laravel 11 and 12 only.
- Only actively maintained major versions receive fixes/features.
- Security fixes are prioritized for the latest maintained major.
- When a Laravel major reaches end-of-life, support can be dropped in the next Sentinel major.
- Use a stable constraint in host apps:
composer require queopius/sentinel:^2.0 - Read release notes before any major upgrade (
1.x->2.x). - Run:
php artisan sentinel:auditafter upgrades to validate effective runtime security.
- Install package:
composer require queopius/sentinel- Run installer:
php artisan sentinel:install --with-views- Migrate (for CSP reports table):
php artisan migrate-
Add middleware aliases/global as needed (see below).
-
Run audit:
php artisan sentinel:auditphp artisan vendor:publish --tag=sentinel-config
php artisan vendor:publish --tag=sentinel-views
php artisan vendor:publish --tag=sentinel-migrationsAdd aliases/global middleware in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'sentinel.headers' => \Queopius\Sentinel\Http\Middleware\AddSecurityHeaders::class,
'sentinel.https' => \Queopius\Sentinel\Http\Middleware\EnforceHttps::class,
]);
// Optional global
$middleware->append(\Queopius\Sentinel\Http\Middleware\EnforceHttps::class);
$middleware->append(\Queopius\Sentinel\Http\Middleware\AddSecurityHeaders::class);
})Config file: config/sentinel.php
Key areas:
preset: baseline config (web_compatible,api_strict)headers.*: security headers setuphttps.*: redirect + force schemeui.*: optional dashboardcsp_reports.*: endpoint + DB storageaudit.*: warnings and probe behaviorhealth_endpoint.*: optional JSON endpoint
Enable in config:
'ui' => [
'enabled' => true,
'path' => 'sentinel',
'middleware' => ['web', 'auth'],
'require_ability' => 'viewSentinelDashboard',
'theme' => 'light', // light|dark|auto
]Then open /sentinel.
- Keep
ui.middlewarewithauth(default in package). - Set
ui.require_abilityand define the Gate in your app:
Gate::define('viewSentinelDashboard', fn ($user) => $user->hasRole('super_admin'));With Spatie Permission you can map it to a permission:
Gate::define('viewSentinelDashboard', fn ($user) => $user->can('sentinel.view'));Dashboard endpoint scan extras:
- Dynamic paths filter via
scan_pathsquery/form - Export scan results:
/sentinel?export=endpoints&format=json/sentinel?export=endpoints&format=csv
Enable:
'csp_reports' => [
'enabled' => true,
'route_path' => 'sentinel/csp-reports',
'store_database' => true,
]Use report-only initially, inspect reports, then enforce.
php artisan sentinel:install [--with-views] [--force]php artisan sentinel:audit [--format=table|json|csv]php artisan sentinel:scan [--json] [--paths=/,/login,/api]php artisan sentinel:prune-reports [--days=30]
- Start with preset
web_compatible - Keep CSP in
report_only - Observe dashboard + reports
- Tighten CSP directives and remove
unsafe-inline - Enable HTTPS redirect and HSTS in production
If app is behind Cloudflare / ALB / Nginx proxy, ensure Laravel trusted proxies are correctly configured so Request::isSecure() is reliable.
For monorepo host apps:
./scripts/generate-local-https-cert.sh
./vendor/bin/sail up -d --buildSet in host .env:
APP_URL=https://your-app.test:8443Then run:
./vendor/bin/sail artisan optimize:clearOpen:
https://your-app.test:8443https://your-app.test:8443/sentinel
Full trust instructions are in docs/guides/local-https.md.
Views namespace: sentinel.
You can override UI templates by publishing views:
php artisan vendor:publish --tag=sentinel-viewsOutput path: resources/views/vendor/sentinel
Host app composer.json:
{
"repositories": [
{
"type": "path",
"url": "packages/queopius/sentinel",
"options": {
"symlink": true
}
}
],
"require": {
"queopius/sentinel": "^2.0"
}
}Then:
composer require queopius/sentinel:^2.0
php artisan sentinel:install --with-views
php artisan migrate
php artisan sentinel:audit
php artisan sentinel:scanInside package directory:
composer install
vendor/bin/phpunit
vendor/bin/pint --test
vendor/bin/phpstan analyseSee docs/ for architecture, config reference, CSP reporting, dashboard and roadmap.
Release-hardening checklist: docs/production-readiness.md.
- Contribution guide:
CONTRIBUTING.md - Security policy:
SECURITY.md - Release + Packagist automation:
docs/guides/release-and-packagist.md
- Code: MIT (see
LICENSE). - Documentation and guides: Creative Commons Attribution 4.0 International (CC BY 4.0).
This package includes:
.readthedocs.yamlmkdocs.ymldocs/requirements.txt
Local docs preview:
cd packages/queopius/sentinel
python3 -m venv .venv
source .venv/bin/activate
pip install -r docs/requirements.txt
mkdocs serveLocal strict build:
mkdocs build --strictGitHub Actions docs workflow:
- validates docs on PR/push via
mkdocs build --strict - optional Read the Docs trigger on push to
main
Required repository secrets for RTD trigger:
RTD_TOKEN: Read the Docs API tokenRTD_PROJECT: Read the Docs project slug (example:queopiussentinel)
- Logo placeholder path in this README:
.github/assets/logo-queopius-sentinel.png
- If repository owner/name changes, update badge URLs accordingly.
- If Read the Docs project slug changes, update:
https://readthedocs.org/projects/<slug>/badge/?version=latest
