Magento 2's Hidden Cache Demands: Unraveling Unnecessary File Permissions with Redis

Magento 2's Hidden Cache Demands: Unraveling Unnecessary File Permissions with Redis

Deploying and managing a robust Magento 2 store often involves optimizing performance with external caching solutions like Redis. However, a recent GitHub issue (#41157) has brought to light a perplexing behavior in Magento 2.4.6 through 2.4.8-p* (and even 2.4-develop): the platform insists on creating and requiring write access to var/cache and var/page_cache directories, even when all cache backends are explicitly configured to use Redis.

The Deployment Headache for Redis Users

This issue primarily impacts Magento 2 deployments that leverage Redis for all cache frontends and sessions, especially in environments with strict file permissions. Consider a common setup: a 'deploy user' handles CLI commands (like setup:upgrade, di:compile) and a separate 'www-data' user runs PHP-FPM, with the document root expected to be largely read-only for PHP-FPM outside of specific directories like var/log or pub/media.

The issue arises even with a configuration like this in app/etc/env.php, explicitly setting Redis for all cache backends:


'cache' => [
    'frontend' => [
        'default' => [
            'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
            'backend_options' => ['server' => 'redis', 'database' => 0, 'port' => 6379],
        ],
        'page_cache' => [
            'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
            'backend_options' => ['server' => 'redis', 'database' => 1, 'port' => 6379],
        ],
    ],
],
'session' => ['save' => 'redis', ...],
'http_cache_hosts' => [...], // Varnish as FPC

Under these conditions, the problem manifests in several critical ways:

  • Unnecessary Directory Creation: During deployment commands, var/cache and var/page_cache are created (empty) by the deploy user.
  • Silent HTTP 500 Errors: When PHP-FPM (as 'www-data') attempts to serve the storefront, it fails to write into these *unused* directories. Crucially, this results in an HTTP 500 error with no entries in var/log/exception.log, making diagnosis extremely difficult. The failure occurs early, during cache frontend instantiation, before the logger is available.
  • Setup Command Failures: Commands like bin/magento setup:upgrade report missing write permissions for var if any of these unused subdirectories (including var/tmp) are not writable.

The Temporary Fix: A Permission Workaround

Until an official fix is released, the community has resorted to a workaround: pre-creating var/cache, var/page_cache, and var/tmp with the appropriate group (e.g., www-data) and granting group write permissions (g+ws) *before* any Magento command runs. This grants write access to directories that ultimately hold no data, simply to satisfy Magento's unexpected demands.

Diving Deep: The Root Cause Analysis

The issue's author, lbajsarowicz, provided an exceptionally detailed root cause analysis, pinpointing four key areas in Magento's codebase:

  1. Hardcoded cache_dir for page_cache: Magento's app/etc/di.xml hardcodes a cache_dir for the page_cache frontend. Due to how Magento\Framework\App\Cache\Frontend\Pool::_getCacheSettings() merges configuration (using array_replace_recursive()), this cache_dir setting persists even when Redis is configured as the backend.
  2. Unconditional Directory Creation in Frontend Factory: The Magento\Framework\App\Cache\Frontend\Factory::create() method resolves and creates cache_dir for backend_options and slow_backend_options unconditionally at the start of the method, *before* the actual backend class is determined. This means the directory is created regardless of whether a file-based backend is truly needed.
  3. var/cache Cleanup and Re-creation: Deployment commands like cleanGeneratedFiles() and DiCompileCommand include DirectoryList::CACHE in their cleanup lists and trigger cache:flush without checking the configured backend. This results in var/cache being removed and re-created with the ownership of the user running the command.
  4. Overly Strict Permission Gate: Magento\Framework\Setup\FilePermissions::checkRecursiveDirectories() recursively checks all var/* subdirectories for writability (excluding only var/session and generated code paths). This means even unused cache directories become a hard gate for setup:upgrade.

Towards a Permanent Solution

The good news is that the community is actively working on a resolution. The issue's author has already submitted two potential pull requests for maintainer consideration:

  • PR #41158: A minimal approach where the factory only resolves cache_dir to a path, with the filesystem adapter creating the directory only on first use.
  • PR #41159: An explicit approach where the factory creates cache_dir only when the backend is confirmed to be file-based.

This issue, classified as S1 (affecting critical functionality and forcing workarounds), highlights a crucial area for improvement in Magento 2's core architecture regarding cache management and deployment flexibility. Developers and merchants running Redis-based Magento 2 stores should monitor these developments closely for an official resolution that will streamline their deployment pipelines and eliminate these frustrating permission-related roadblocks.

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools