Installation:
composer require lexik/maintenance-bundle
Add to config/bundles.php:
return [
// ...
Lexik\Bundle\MaintenanceBundle\LexikMaintenanceBundle::class => ['all' => true],
];
Configuration: Publish the default config:
php bin/console lexik:maintenance:config:dump
Edit config/packages/lexik_maintenance.yaml to define:
mode (e.g., file, memcache, or database).allowed_ips (e.g., ['127.0.0.1', '192.168.1.0/24']).error_template (optional).First Use Case: Enable maintenance mode:
php bin/console lexik:maintenance:enable
Disable it:
php bin/console lexik:maintenance:disable
Verify with curl -I http://your-site.com (should return 503).
Deployment Workflow:
php bin/console lexik:maintenance:enable --env=prod
php bin/console lexik:maintenance:disable --env=prod
IP Whitelisting:
# config/packages/lexik_maintenance.yaml
lexik_maintenance:
allowed_ips: ['192.168.1.100', '203.0.113.5']
Custom Error Pages:
templates/lexik_maintenance/error.html.twig.config/packages/lexik_maintenance.yaml:
lexik_maintenance:
error_template: 'custom_error_page'
error_template_data:
title: 'Under Maintenance'
message: 'We’ll be back soon!'
Database-Backed Mode:
config/packages/lexik_maintenance.yaml:
lexik_maintenance:
mode: database
database_table: maintenance_mode
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Environment-Specific Configs:
dev/prod by leveraging Symfony’s environment variables:
# config/packages/lexik_maintenance.yaml
when@prod:
lexik_maintenance:
mode: file
file_path: '%kernel.project_dir%/var/maintenance.lock'
Integration with CI/CD:
# .github/workflows/deploy.yml
- name: Enable Maintenance Mode
run: php bin/console lexik:maintenance:enable --env=prod
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Caching Issues:
memcache mode, ensure the cache server is running and accessible.php bin/console cache:clear
File Permissions:
file mode, ensure the lock file (e.g., var/maintenance.lock) is writable:
chmod 644 var/maintenance.lock
Database Mode Quirks:
maintenance_mode table doesn’t exist, the bundle won’t work. Run migrations manually if needed.IP Whitelisting Edge Cases:
192.168.1.0/24) may not work as expected if the bundle isn’t updated. Test thoroughly.127.0.0.1) is often auto-whitelisted, but verify in logs if access is denied.Symfony 5+ Compatibility:
symfony/http-kernel).Debugging:
php bin/console lexik:maintenance:debug
php bin/console lexik:maintenance:enable -v
Custom Commands: Extend the bundle by creating a custom command to toggle maintenance mode with additional logic:
// src/Command/ToggleMaintenanceCommand.php
namespace App\Command;
use Lexik\Bundle\MaintenanceBundle\Command\EnableCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ToggleMaintenanceCommand extends EnableCommand {
protected function execute(InputInterface $input, OutputInterface $output) {
// Add pre/post logic (e.g., send Slack notifications)
parent::execute($input, $output);
}
}
Environment Variables: Dynamically enable/disable maintenance via environment variables:
# .env
MAINTENANCE_MODE=true
// src/Command/EnableCommand.php (override)
if (!$this->getContainer()->getParameter('kernel.environment') === 'prod' ||
!$this->getInput()->getOption('force')) {
throw new \RuntimeException('Maintenance mode can only be enabled in production.');
}
Logging Maintenance Events: Log enable/disable actions to track downtime:
# config/packages/monolog.yaml
handlers:
maintenance:
type: stream
path: "%kernel.logs_dir%/maintenance.log"
level: info
// In a custom command
$this->getContainer()->get('logger')->info('Maintenance mode enabled by ' . $this->getUser());
Testing Maintenance Mode: Use PHPUnit to test maintenance behavior:
// tests/Functional/MaintenanceTest.php
public function testMaintenanceMode() {
$client = static::createClient();
$client->disableMaintenanceMode(); // Custom helper
$client->request('GET', '/');
$this->assertEquals(503, $client->getResponse()->getStatusCode());
}
Fallback for Shared Hosting:
If no memcache/database is available, use file mode with a fallback path:
lexik_maintenance:
mode: file
file_path: '%kernel.project_dir%/var/maintenance.lock'
# Fallback if 'var' is not writable
fallback_file_path: '/tmp/maintenance.lock'
Security Note: Avoid exposing the maintenance toggle endpoint in production. Restrict access to the CLI commands via:
# config/packages/security.yaml
access_control:
- { path: ^/bin/console, roles: ROLE_ADMIN }
How can I help you explore Laravel packages today?