Quick Start
Enable Lockout
Add to your .env file:
1APP_READ_ONLY=true
By default, only pages accessed with GET requests will be allowed. All other request types (POST, PUT, PATCH, DELETE) will be blocked with a 401 Unauthorized response.
Disable Lockout
1APP_READ_ONLY=false
Or use the Artisan command:
1php artisan lockout:disable
Basic Configuration
Allow Login During Lockout
To allow users to log in and view secure areas (but still only allow GET requests after login):
1APP_READ_ONLY_LOGIN=true
You can customize your login/logout paths in the configuration file if they differ from Laravel defaults.
Locking Specific GET Pages
Block access to specific pages even for GET requests:
1'pages' => [2 'register',3 'subscribe',4 'admin/settings',5],
Whitelisting Specific Routes
Allow specific routes to bypass lockout:
1'whitelist' => [2 'post' => 'password/confirm',3 'put' => 'profile/update',4],
Advanced Features
IP Whitelist/Blacklist
IP Whitelist
Allow specific IP addresses to bypass lockout completely:
IPv4 and IPv6 addresses and CIDR ranges are supported. Malformed CIDR masks are ignored.
Via .env:
1LOCKOUT_IP_WHITELIST=127.0.0.1,192.168.1.100
Via Config:
1'ip_whitelist_array' => [2 '127.0.0.1',3 '192.168.1.0/24', // CIDR notation supported4 '10.0.0.0/8',5],
IP Blacklist
Block specific IP addresses even when lockout is disabled:
Via .env:
1LOCKOUT_IP_BLACKLIST=192.168.1.50
Via Config:
1'ip_blacklist_array' => [2 '192.168.1.50',3 '10.0.0.100/24',4],
Role-Based Exceptions
Allow users with specific roles to bypass lockout:
1'allowed_roles' => [2 'admin',3 'super-admin',4 'maintenance',5],
The package supports:
- Laravel Bouncer
- Spatie Permission
- Simple role attributes (
$user->role) - Roles relationships
Custom Response Types
View Response
Show a custom maintenance page:
1'response_type' => 'view',2'response_view' => 'lockout::maintenance',3'response_message' => 'We are currently performing maintenance.',4'response_code' => 503,
Publish the view to customize:
1php artisan vendor:publish --tag=lockout-views
JSON Response
Return JSON for API requests:
1'response_type' => 'json',2'response_code' => 503,
API-Specific Handling
Automatically detect and handle API requests differently:
1'api_enabled' => true,2'api_response_type' => 'json',3'api_response_message' => [4 'message' => 'Application is in maintenance mode.',5 'status' => 'maintenance',6],
Route Patterns and Names
Route Patterns
Whitelist routes by pattern:
* matches any path characters. Other characters, including dots, are matched literally.
1'route_patterns' => [2 'api/*', // All API routes3 'health', // Health check4 'admin/*', // All admin routes5],
Route Names
Whitelist routes by name:
Names are matched against the route for the current request, including when Lockout runs as global middleware.
1'route_names' => [2 'health.check',3 'api.status',4 'admin.dashboard',5],
Health Check Endpoint
A health check endpoint is automatically registered at /health (configurable):
1GET /health
Response:
1{2 "status": "ok",3 "timestamp": "2025-01-15T10:30:00Z",4 "lockout_enabled": true5}
Disable or customize:
1'health_check_enabled' => true,2'health_check_path' => 'health',
Cache Integration
Improve performance by caching lockout status:
1'cache_enabled' => true,2'cache_key' => 'lockout.status',3'cache_ttl' => 60, // seconds
Disable caching:
1'cache_enabled' => false,
Clear cache manually:
1php artisan cache:clear
Or when enabling/disabling:
The enable and disable commands automatically clear the lockout status cache. --clear-cache remains accepted for existing scripts.
1php artisan lockout:enable --clear-cache2php artisan lockout:disable --clear-cache
Event System
The package fires events that you can listen to:
Available Events
Rappasoft\Lockout\Events\LockoutEnabled- Fired when lockout is enabledRappasoft\Lockout\Events\LockoutDisabled- Fired when lockout is disabledRappasoft\Lockout\Events\RequestBlocked- Fired when a request is blocked
Example Listener
1use Rappasoft\Lockout\Events\RequestBlocked; 2use Illuminate\Support\Facades\Log; 3 4class LogBlockedRequests 5{ 6 public function handle(RequestBlocked $event) 7 { 8 Log::warning('Request blocked', [ 9 'path' => $event->request->path(),10 'method' => $event->request->method(),11 'ip' => $event->request->ip(),12 'reason' => $event->reason,13 ]);14 }15}
Register in EventServiceProvider:
1protected $listen = [2 RequestBlocked::class => [3 LogBlockedRequests::class,4 ],5];
Disable events:
1'fire_events' => false,
Artisan Commands
These commands update the application's active environment file, preserve its file permissions, and clear any cached Laravel configuration. They fail if the environment file is missing or cannot be updated. Run php artisan config:cache afterwards if your deployment uses cached configuration, and restart long-running workers or Octane processes so they reload the setting. If your deployment supplies APP_READ_ONLY through external environment variables, update that setting through your deployment instead.
Enable Lockout
1php artisan lockout:enable
Options:
--clear-cache- Accepted for existing scripts; the lockout cache is always cleared
Disable Lockout
1php artisan lockout:disable
Options:
--clear-cache- Accepted for existing scripts; the lockout cache is always cleared
Check Status
1php artisan lockout:status
Output:
1Lockout Status: 2───────────────── 3Enabled: Yes 4Cached: Yes 5 6Configuration: 7 Allow Login: Yes 8 Locked Types: post, put, patch, delete 9 Response Type: abort10 Health Check: Yes11 Cache Enabled: Yes
Blade Directive
Conditionally render content based on lockout status:
1@readonly2 <div class="alert alert-warning">3 Application is currently in read-only mode.4 </div>5@else6 <div class="alert alert-info">7 Application is fully operational.8 </div>9@endreadonly
Best Practices
-
Use IP Whitelist for Maintenance: Whitelist your IP before enabling lockout to ensure you can still access the application.
-
Use Health Check for Monitoring: Configure your monitoring tools to check the
/healthendpoint. -
Enable Caching in Production: Improve performance by enabling cache for lockout status.
-
Use Events for Logging: Listen to
RequestBlockedevents to track blocked requests. -
Customize Response for Better UX: Use view responses for web requests and JSON for API requests.
-
Test Before Production: Always test lockout in a staging environment first.