syriable/maintenance-guard
Maintenance Guard adds a flexible maintenance-mode layer to Laravel apps, letting you gate requests behind custom checks, whitelist routes or IPs, and return friendly responses while work is in progress. Easy to configure and toggle.
syriable/maintenance-guard 1.0.0 is a brand-new package (first public release), so treat it as an early-adopter dependency: the surface area is small, but there is no long tail of community usage to lean on yet.
Minimal setup:
composer require syriable/maintenance-guard
php artisan vendor:publish --tag=maintenance-guard-config
Then read, in this order:
config/maintenance-guard.php — this is where the package's whole behaviour is expressed (who is allowed through while php artisan down is active). Everything else is plumbing.README.md — for the exact middleware alias / service-provider registration expectations in 1.0.0.src/ — it's a small package at this point; skimming the guard class will take five minutes and save you an afternoon of guessing.First real use case: you run php artisan down for a deploy, and you want your team, your uptime monitor, and your staging smoke tests to keep hitting the app while everyone else sees the maintenance page. Wire the guard so a known set of IPs / a header / a query token bypasses the 503, verify with curl -I, and only then roll it into your deploy script.
Because this is a 1.0.0 with a single contributor, pin the version ("syriable/maintenance-guard": "^1.0") and plan to re-read the config on each minor bump.
Environment-driven allowlists. Keep the bypass list in config, sourced from env, so local/staging/production differ without code changes:
// config/maintenance-guard.php
'allowed_ips' => array_filter(explode(',', env('MAINTENANCE_ALLOWED_IPS', ''))),
Then MAINTENANCE_ALLOWED_IPS=203.0.113.10,198.51.100.0/24 in the deploy environment. Prefer CIDR support if the package provides it; otherwise list individual addresses and be explicit about the limitation in your runbook.
Secret-token bypass for CI and smoke tests. A query string or header token lets automated checks pass through without hardcoding office IPs:
curl -s -o /dev/null -w "%{http_code}" \
-H "X-Maintenance-Token: $TOKEN" https://example.com/
# expect 200, not 503
Generate the token per environment, never commit it, and rotate it after an incident.
Keep the guard out of the public surface. Register the middleware on the web and api groups (or globally) rather than per-route — a bypass that only applies to / is a footgun during an incident. If the package ships a middleware alias, prefer group assignment in bootstrap/app.php (Laravel 11+) or Kernel.php (Laravel 10 and below).
Pair it with a predictable deploy sequence. The pattern that actually pays off day to day:
php artisan down --render="errors::503" --retry=60
# deploy / migrate
php artisan up
The guard makes down survivable for humans; --retry makes it survivable for browsers. Use both.
Cache and queue awareness. Maintenance mode does not stop queue workers. Decide explicitly whether jobs should keep running during the window — run php artisan queue:pause / drain, or scope the maintenance window to web traffic only. Write this down; it's the most common source of "we were down but emails still went out" surprises.
Scheduled-window integration. If you gate deploys behind a scheduled task, wrap the down/up calls in a command with a finally block so a failed deploy never leaves the app stuck in maintenance:
try {
Artisan::call('down');
// deploy steps
} finally {
Artisan::call('up');
}
$request->ip() returns the proxy address unless TrustProxies is configured. You will either lock everyone out or let everyone in. Verify with $request->ip() logged during the maintenance window before you rely on it.php artisan down returns 503, not 200. Uptime monitors and health checks configured for 2xx will page you. Either let the monitor through the guard or teach it that 503-with-Retry-After is the expected state during a window.config/maintenance-guard.php in production, run php artisan config:cache — otherwise you'll debug a change that silently isn't applied.finally-based up (above) and know the manual escape hatch: php artisan up on the box. Some setups also need the storage/framework/down file removed if up was interrupted.down is active. This is cheap and catches config drift immediately.How can I help you explore Laravel packages today?