Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Down command creates files when using cache driver for maintenance mode #53278

Open
JaZo opened this issue Oct 23, 2024 · 7 comments
Open

Down command creates files when using cache driver for maintenance mode #53278

JaZo opened this issue Oct 23, 2024 · 7 comments

Comments

@JaZo
Copy link
Contributor

JaZo commented Oct 23, 2024

Laravel Version

11.23.5

PHP Version

8.2.24

Database Driver & Version

No response

Description

When you're using the cache based maintenance mode, Laravel still tries to create the framework/maintenance.php file. However, this file does nothing when there's no down-file, which is the case when you're using the cache driver, so basically it is useless.

Example of when this is an issue:

  1. When running a multi server environment, only the server where the down command is ran, will have the maintenance file and the others don't.
  2. When running on a read-only filesystem, the down command will error as the file can't be created.

In both these situations the cache driver should suffice, but currently it has this issue.

N.B. I proposed a solution in #53228, but that wasn't accepted.

Steps To Reproduce

  1. Make sure your cache store isn't file based;
  2. Set the maintenance mode driver to cache;
  3. Make the storage directory read-only;
  4. Run php artisan down;
  5. See that the command fails because it can't create the maintenance file.
@ismaildasci
Copy link

Hey! 👋

You're right—Laravel’s php artisan down command creates the framework/maintenance.php file even in cache-based maintenance mode. This file isn’t really necessary if you’re relying on the cache driver for maintenance status.
Possible Workaround

One option is to create a custom command to enable maintenance mode using only the cache without creating maintenance.php. Here’s an example:

php

use Illuminate\Support\Facades\Cache;
use Illuminate\Console\Command;

class CustomDownCommand extends Command
{
protected $signature = 'custom:down';
protected $description = 'Put the app in maintenance mode (cache-based only)';

public function handle()
{
    Cache::put('maintenance_mode', true, now()->addHours(24)); // 24-hour maintenance mode
    $this->info('Maintenance mode enabled without file.');
}

}

This way, only the cache is used, and maintenance.php won’t be created. Hope this helps! 😊

@devriazul
Copy link

Thank you for raising this issue! I understand the challenges faced, particularly in multi-server environments or read-only filesystems, where creating unnecessary files can disrupt workflows.

To address this, here are a few thoughts:

Workaround:
A custom command like the one suggested by @ismaildasci is a great temporary solution. For example:

`use Illuminate\Support\Facades\Cache;
use Illuminate\Console\Command;

class CustomDownCommand extends Command
{
protected $signature = 'custom:down';
protected $description = 'Put the app in maintenance mode (cache-based only)';

public function handle()
{
    Cache::put('maintenance_mode', true, now()->addHours(24)); // 24-hour maintenance mode
    $this->info('Maintenance mode enabled without file.');
}

}
`
This ensures maintenance mode is activated using the cache driver without attempting to create the maintenance.php file.

Proposal for Core Behavior:
Laravel could check the maintenance mode driver and skip creating the framework/maintenance.php file entirely if the driver is set to cache. This change would maintain backward compatibility while streamlining behavior for cache-based setups.

Documentation:
If the core behavior remains unchanged, it would be helpful to update the documentation or migration guides to note this behavior and provide recommendations for multi-server or read-only environments.

I’d be happy to assist with refining this idea or contributing a PR for the documentation. Let me know how I can help! 😊

@mhshagor
Copy link

mhshagor commented Feb 6, 2025

It looks like you're facing an issue with Laravel's maintenance mode when using the cache driver. The problem arises because the php artisan down command attempts to create a framework/maintenance.php file, which is not necessary when the cache driver is used, especially in multi-server environments or when the storage directory is read-only.

To address this, you could consider the following approaches:

  1. Modify the down Command: You can extend the down command in Laravel to check if the cache driver is being used and skip the creation of the maintenance.php file if it is. This would involve overriding the default behavior of the command in your application.
  2. Custom Middleware: Implement a custom middleware that checks for maintenance mode and handles the request accordingly without relying on the maintenance.php file.
  3. Environment Configuration: Ensure that your environment configuration allows for proper handling of maintenance mode without needing to write to the filesystem.

@pandiselvamm
Copy link
Contributor

Hi @JaZo,

Please update APP_MAINTENANCE_DRIVER to cache and APP_MAINTENANCE_STORE to database. This will allow us to manage Maintenance Mode across multiple servers effectively.

@ismaildasci @devriazul @mhshagor @crynobone please check this out.

@JaZo
Copy link
Contributor Author

JaZo commented Feb 21, 2025

Thanks all for the responses! Sure I can create my own command to "fix" this, but in my opinion it should be fixed in the framework itself.

@pandiselvamm, using the cache driver for maintenance mode works fine, the problem is that it creates the framework/maintenance.php file, which isn't synced to other servers in a multi-server setup. See the issue description for more details.

@ollieread
Copy link
Contributor

ollieread commented Feb 23, 2025

Laravel Version

11.23.5

PHP Version

8.2.24

Database Driver & Version

No response

Description

When you're using the cache based maintenance mode, Laravel still tries to create the framework/maintenance.php file. However, this file does nothing when there's no down-file, which is the case when you're using the cache driver, so basically it is useless.

Example of when this is an issue:

  1. When running a multi server environment, only the server where the down command is ran, will have the maintenance file and the others don't.
  2. When running on a read-only filesystem, the down command will error as the file can't be created.

In both these situations the cache driver should suffice, but currently it has this issue.

N.B. I proposed a solution in #53228, but that wasn't accepted.

Steps To Reproduce

  1. Make sure your cache store isn't file based;
  2. Set the maintenance mode driver to cache;
  3. Make the storage directory read-only;
  4. Run php artisan down;
  5. See that the command fails because it can't create the maintenance file.

@JaZo I've no idea why this is marked as need-more-info, or why it's attracted so many AI responses.

@crynobone when you run php artisan down, the down command creates the file, even though it's not used if you aren't using the file driver.

file_put_contents(
storage_path('framework/maintenance.php'),
file_get_contents(__DIR__.'/stubs/maintenance-mode.stub')
);

The php artisan up command even wraps the removal of this file in a presence check.

if (is_file(storage_path('framework/maintenance.php'))) {
unlink(storage_path('framework/maintenance.php'));
}

When you use the file driver, the file framework/down is created, but when you're using cache it is not. But, the very first bit of code in the framework/maintenance.php file ignores the rest of the file if framework/down doesn't exist.

<?php
// Check if the application is in maintenance mode...
if (! file_exists($down = __DIR__.'/down')) {
return;
}

Ideally, this file shouldn't be created for anything but the file driver.

@ollieread
Copy link
Contributor

@JaZo if you want a quick fix, you can do this in a service provider boot method.

Event::listen(Illuminate\Foundation\Events\MaintenanceModeEnabled::class, function () {
    if (is_file(storage_path('framework/maintenance.php'))) {
        unlink(storage_path('framework/maintenance.php'));
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants
@crynobone @ollieread @JaZo @devriazul @mhshagor @pandiselvamm @ismaildasci and others