Skip to content

Remove setup/ directory dependency from production artifacts #40695

@lbajsarowicz

Description

@lbajsarowicz

Problem Statement

The setup/ directory is a standalone Laminas (Zend) MVC application that was originally built for the web-based Setup Wizard. The web installer has been officially deprecated (classes annotated with @deprecated, blocked by default in nginx.conf.sample), yet the entire setup/ directory remains a hard runtime dependency for every bin/magento invocation.

Current state

  1. Magento\Framework\Console\Cli unconditionally requires setup/config/application.config.php and bootstraps a Laminas ServiceManager on every CLI call — even for cache:flush or indexer:reindex.

  2. app/etc/di.xml maps core Framework interfaces to Magento\Setup\* implementations:

    <preference for="Magento\Framework\Setup\SchemaSetupInterface" type="Magento\Setup\Module\Setup" />
    <preference for="Magento\Framework\Setup\ModuleDataSetupInterface" type="Magento\Setup\Module\DataSetup" />
  3. app/code/Magento/Backend extends Magento\Setup\Console\Command\AbstractSetupCommand for maintenance commands.

  4. The composer.json PSR-4 autoload and registration_globlist.php both reference setup/.

This means removing setup/ from a production artifact breaks bin/magento entirely — even though a deployed production store never needs the installer, DI compiler, or static content deployer at runtime.

What's dead but still shipped

Component Files Status
Web installer entry point (setup/index.php) 1 Deprecated, blocked in nginx
Laminas views & templates (setup/view/) ~10 Deprecated, unused
Static assets (setup/pub/) ~15 Deprecated, unused
Web controllers (setup/src/.../Controller/) ~5 Deprecated
Laminas MVC bootstrap listeners ~3 Annotated @deprecated
Performance toolkit fixtures ~20 Dev-only
DI Compiler (Module/Di/) ~50 Build-time only
I18n tools (Module/I18n/) ~30 Build-time only
Dependency analysis (Module/Dependency/) ~40 Dev-time only

~170+ files that serve no purpose in production are required to be deployed.

Security concern

Shipping setup/ in production artifacts encourages (or requires) exposing the directory on web servers. Even with deny all in nginx, misconfigured servers can leak:

  • Magento version information via setup/view/ templates
  • Internal directory structure
  • The setup entry point itself (historically a common attack vector)

The safest file is the one that doesn't exist on the server.

Expected State

Short-term (non-breaking)

  1. Make Cli.php setup-tolerant — Load setup/config/application.config.php conditionally with a class_exists() / file_exists() guard. If setup/ is absent, skip SetupCommandLoader registration. Non-setup commands (cache:*, indexer:*, cron:*) should work without setup/.

  2. Move runtime DI implementations to FrameworkMagento\Setup\Module\Setup and Magento\Setup\Module\DataSetup contain minimal logic on top of Magento\Framework\Module\Setup. Move them into lib/internal/Magento/Framework/Setup/ and update di.xml preferences. These are the only two classes needed at runtime.

  3. Move AbstractSetupCommand to Framework — Backend's maintenance commands should not depend on the Magento\Setup namespace.

After these 3 changes, setup/ can be safely excluded from production deploys while keeping bin/magento fully functional for operational commands.

Long-term (next major version)

  1. Relocate CLI commands to proper Magento modules — Register setup:* commands via di.xml like every other command, eliminating the Laminas ServiceManager bootstrap entirely.

  2. Remove the dead web installer code — Delete deprecated controllers, views, pub assets, Laminas MVC listeners.

  3. Extract build-time tools into separate packages — DI compiler, I18n tools, dependency analysis as magento/setup-tools or similar.

Impact

  • Performance: Every bin/magento call bootstraps Laminas ServiceManager unnecessarily
  • Security: Reduced attack surface by not shipping installer code to production
  • DevOps: Smaller, cleaner production artifacts; no need to maintain nginx rules for a dead feature
  • Architecture: Removes the last Laminas MVC dependency from the runtime path

⭐ Support my work

Do you like the fix? Remember to react with "👍🏻" to get it merged faster,
Then Sponsor me on Github so I can spend more time on fixing issues like this one.

Learn more at https://github.com/sponsors/lbajsarowicz

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions