flagbit/shopware-maintenance
A Shopware plugin for managing maintenance mode with configurable templates, IP allowlisting, and easy toggling. Take your store offline for updates or emergencies while keeping trusted users and staff access.
This is a Shopware 6 plugin, not a framework-agnostic library. You get the most value by treating it as part of your deployment toolchain rather than as application code.
Minimal install path
composer require flagbit/shopware-maintenance
bin/console plugin:refresh
bin/console plugin:install --activate <technical-name> # name is printed by plugin:refresh
bin/console cache:clear
bin/console assets:install
bin/console theme:compile
If the plugin ships Administration assets, also run the admin build (bin/console administration:build or your normal shopware-cli/webpack pipeline). In production, never skip assets:install and theme:compile; a maintenance page with missing CSS is worse than no maintenance page.
Where to look first
README.md in the repo for the configuration keys and console command names (they are plugin-specific; confirm with bin/console list | grep -i maintenance rather than guessing).CLAUDE.md in the repo root — added in v4.0.0 — which documents the plugin's structure and conventions for AI coding assistants. It doubles as a fast orientation file for humans, and is the file to update if you fork or extend the plugin.src/Resources/config/ and src/Resources/views/ to see which services and Twig templates you can override.composer.json of the plugin for the supported Shopware/PHP constraint before you upgrade — see the gotchas on v4.0.0.First use case
Enable maintenance during a deploy, keep your office/VPN IP whitelisted, run smoke tests against the real storefront, then disable. That single loop — toggle, verify as an allowed client, toggle back — is the core of daily use. Do not start by customizing the template; start by proving the bypass works from your machine and from CI.
Wrap the toggle in your release script so it is deterministic and always paired:
# before migrations / theme compile
bin/console <maintenance-enable-command>
# ... deploy steps ...
# after cache warmup and smoke tests
bin/console <maintenance-disable-command>
Use a trap/finally block so a failed deploy does not leave the shop in maintenance indefinitely. Pair the enable step with an alert, because a stuck maintenance flag is a revenue incident.
v4.0.0 is a major bump, so treat it as a migration rather than a routine composer update. In a staging clone:
composer require flagbit/shopware-maintenance:^4.0 --with-dependencies
bin/console plugin:refresh
bin/console plugin:update <technical-name> # not plugin:install — state already exists
bin/console database:migrate --all <technical-name>
bin/console cache:clear
bin/console assets:install && bin/console theme:compile
Then exercise the full toggle loop (enable → bypassed request → disable) and re-check that any template override of yours still resolves. Because the release notes only mention a New Relic fix and a docs addition, the major bump most likely reflects a platform/constraint change (Shopware or PHP) rather than a rewritten feature set — but verify the constraint in the plugin's composer.json instead of assuming, and only then roll it to production.
Configure the whitelist with your office egress IP and CI runner IPs. This lets you exercise the real storefront (routing, theme, checkout) while customers see the maintenance page. For teams behind changing egress IPs, prefer a shared VPN exit or a header/cookie-based bypass over maintaining a long IP list.
If the plugin supports a secret token/query parameter, use it only from automated smoke tests and only over HTTPS. Keep the token in your secret manager, inject it as an environment variable in CI, and rotate it after major releases. Never put it in a bookmark or documentation page that ends up in a referrer header.
curl -sS -o /dev/null -w '%{http_code}\n' \
"https://shop.example.com/?<bypass-param>=${MAINTENANCE_TOKEN}"
Assert on the status code (expect 200 for a bypassed client, 503 for everyone else) rather than on HTML content.
For staged launches or storefront-only incidents, scope maintenance to a single sales channel where the plugin allows it. This is the pattern for "new B2B storefront is not ready, but the existing EU storefront must stay live." Test the scoping explicitly: the admin API and other channels should remain unaffected.
Find the template the plugin renders:
find vendor/flagbit -name '*.twig' | grep -i maint
Override it by mirroring the path inside your own theme or plugin's Resources/views/storefront/..., rather than editing vendor/. Keep the page static and dependency-light — no cart, no customer session, no API calls. Put support contact details and an expected end time in plugin config text fields so non-developers can update them.
Make your uptime monitor treat the maintenance response as a known state, not an outage. Check for the specific status code and a marker in the response (a header or a stable HTML element) so you can distinguish "intentional maintenance" from "PHP fatal error returning 503." Alert on unexpected 503s; do not page on planned maintenance.
If you run New Relic, note that v4.0.0 fixes a crash during plugin sync. Re-verify your APM integration on staging after the upgrade: run plugin:refresh/plugin:update with the agent enabled and confirm the Administration plugin list still loads, since a broken sync surfaces as an unusable extension manager rather than as a maintenance-mode bug.
Maintenance mode is an HTTP-storefront concern. Before a deploy that includes migrations, stop or drain messenger:consume workers and any cron runners, then restart them after. Otherwise consumers keep writing against half-migrated schemas while the storefront politely shows a maintenance page.
TRUSTED_PROXIES / shopware.trusted_proxies correctly, or your whitelist will either match everyone or no one. Verify with a temporary debug log of the resolved client IP before trusting the whitelist.503 Service Unavailable with Retry-After, not a 200 page. A 200 maintenance page gets indexed and confuses monitoring. Check with curl -I rather than a browser.composer require alone is not enough. Missing plugin:refresh/install/update, missing migrations, or an unbuilt theme is the most common "plugin does nothing" cause. Check var/log/ and the plugin state in the database if activation silently fails.CLAUDE.md addition). That does not tell you what broke compatibility. Read the diff between v3.0.0...v4.0.0 and the plugin's composer.json constraints before upgrading; if you cannot determine the breaking change, stay on the pinned v3 line until you can test in staging.Referer headers. Prefer IP-based bypass where possible, restrict token usage to CI, and rotate after exposure.composer.json, test it against each Shopware minor upgrade, and keep a documented fallback: Shopware's built-in maintenance facility or a reverse-proxy-level 503. Do not let it become an unowned single point of failure for releases.curl -I from an allowed and a disallowed IP; inspect the plugin's system_config values; run bin/console debug:container | grep -i maint to find the checker service and any events; disable other request-modifying plugins to isolate conflicts.CLAUDE.md is a starting map rather than an API contract. Re-verify both after any major upgrade.How can I help you explore Laravel packages today?