Skip to main content
Version: v2

Contributed modules

Vortex ships the contributed modules most Drupal projects need, each pre-configured and wired into the environment-aware settings and the provisioning deploy steps. This page lists every shipped module in alphabetical order: what it does, why it ships, how it's installed, and how it's configured.

It's a reference for developers and leads on a project built from Vortex. Use it to check what a module does in each environment and which variables change that.

Most modules are installed by EnableDevelopmentModulesDeployStep, a deploy step in the ys_base module. It runs on every deployment in every environment except production.

➡️ See Overview for the mechanisms that require, configure, and install these modules.

ClamAV​

ClamAV scans uploaded files for malware with the ClamAV engine before they're saved. Ships only when the ClamAV service is selected.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step, which also saves clamav as the daemon host in the module configuration.

Configuration​

settings.clamav.php selects daemon or executable mode and points the daemon at the ClamAV service, but only when DRUPAL_CLAMAV_ENABLED is set to 1. The shipped .env file sets it, with DRUPAL_CLAMAV_MODE set to daemon. Executable mode calls ClamAV's command-line scanner in /usr/bin instead of the daemon.

The override reads the following variables:

VariablePurpose
DRUPAL_CLAMAV_ENABLEDApplies the override only when set to 1
DRUPAL_CLAMAV_MODEdaemon (any case) or 0 selects daemon mode; any other value, or none, selects executable mode
CLAMAV_HOST, CLAMAV_PORTDaemon host and port, antivirus:3310 by default

Coffee​

Coffee adds a search box, opened with Alt+D, that jumps straight to any administration page as you type its name.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

No settings override.

Config Split​

Configuration Split splits configuration into sets that are imported conditionally, so each environment can carry its own configuration, such as development-only modules.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.config_split.php enables the split matching the detected environment, so each environment imports only its own set:

EnvironmentSplit
locallocal
cici
development, previewdev
stagestage
productionNone

The template ships empty config/local, config/ci, config/dev, and config/stage directories but no splits. Create a split with the matching machine name before the override has anything to enable.

Config Update​

Configuration Update Manager provides the revert and update functions that other modules build on. Provisioning installs only this base config_update module. The reports and the Drush commands that report, revert, and import configuration changes come from its config_update_ui submodule. Install that submodule when you need them.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

No settings override.

Devel​

Devel is a suite of development tools for inspecting variables, entities, and the service container while debugging.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.devel.php excludes it from the exported configuration.

Drupal Helpers​

Drupal helpers gives deploy hooks and update scripts static facades for common jobs, such as creating taxonomy trees, menu links, users, and redirects.

  • Installed: As a dependency of the ys_demo demo module, declared in ys_demo.info.yml.

Configuration​

No settings override.

➡️ See Drupal helpers for the helper facades.

Environment Indicator​

Environment Indicator shows a colored banner identifying the current environment to prevent accidental changes on the wrong site.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.environment_indicator.php names the indicator after the detected environment and colors it per environment: red for production, yellow for stage, and green for development and preview. Every other environment, local and ci included, gets a dark green banner with white text. The override also turns on the toolbar integration and the favicon marker.

Fast 404​

Fast 404 answers requests for missing files without bootstrapping Drupal. Drupal core already returns a lightweight 404 for the same file extensions, but only after a full bootstrap. On a site serving many such requests, Fast 404 saves that bootstrap.

  • Installed: Never enabled as a Drupal module. The handler runs from the settings file before the module system exists, so requiring the package is enough.

Configuration​

settings.fast_404.php applies only when the module's code is present, and calls fast404_preboot() with the following settings:

  • A request for a missing file with the txt, png, gif, jpg, jpeg, css, js, ico, swf, flv, cgi, bat, pl, dll, exe, or asp extension gets the fast 404, unless its path starts with /robots or /system/files.
  • index.php, rss.xml, cron.php, and xmlrpc.php are on the URL allowlist, which the module checks before the extensions.
  • Requests for missing image style derivatives reach Drupal, which generates each derivative on its first request. Drupal generates a derivative only for a URL with a valid itok token, so these requests can't generate arbitrary derivatives.
  • Path checking against the router and the URL aliases is off, because it queries the database before Drupal has connected to it. The redirect check that goes with the path check is off too.

Generated Content​

Generated Content generates placeholder content from plugin classes for development and testing. Plugins built on its static helpers produce the same content on every run.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step with GENERATED_CONTENT_CREATE=1, unless DRUPAL_GENERATED_CONTENT_SKIP set to 1 installs it without generating.

Configuration​

settings.generated_content.php excludes it from the exported configuration.

➡️ See Generated Content for the plugin system and the demo plugin.

Migrate Plus​

Migrate Plus extends the core Migrate API with extra source and process plugins and configuration-entity migrations. The demo migration module uses it against the second database. Ships only when the migration feature is selected. Otherwise, the installer removes the requirement.

  • Installed: As a dependency of the ys_migrate demo migration module.

Configuration​

No settings override.

➡️ See Migrations for the second database and the demo migration.

Migrate Tools​

Migrate Tools provides Drush commands and a UI to run, roll back, and monitor migrations. The MigrateContentDeployStep deploy step in ys_migrate runs its migrate:import command during provisioning. Ships only when the migration feature is selected. Otherwise, the installer removes the requirement.

  • Installed: As a dependency of the ys_migrate demo migration module.

Configuration​

No settings override.

➡️ See Migrations for the second database and the demo migration.

Navigation Extra Tools adds a Tools menu to the core Navigation module, with shortcuts that flush caches, rebuild the theme registry, run cron, and run database updates.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step, which also replaces core's toolbar with core's navigation as the administration interface.

Configuration​

No settings override.

Pathauto​

Pathauto generates URL aliases for content from configurable patterns.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

No settings override.

Redirect​

Redirect manages URL redirects and creates them when content URLs change.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

No settings override.

Redis​

Redis integrates Drupal with a Redis-compatible in-memory store for cache and lock backends. Ships only when the Redis service is selected. Locally, that service is cache, which runs Valkey.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.redis.php points the connection at the cache service, makes Redis the default cache backend, registers the module's container YAML files, and swaps the bootstrap container over. Nothing applies until the module's code is on disk and DRUPAL_REDIS_ENABLED is set to 1. The override looks for the web/modules/contrib/redis directory, so the module doesn't need to be installed yet. The variable lets a 2-stage deployment provision the service before switching the cache, and the shipped .env file sets it to 1.

The cache backend, the container YAML files, and the bootstrap container switch also need the redis PHP extension, or VORTEX_REDIS_EXTENSION_LOADED set to 1 in its place. Without either, the override sets only the connection. It reads the following variables:

VariablePurpose
DRUPAL_REDIS_ENABLEDApplies the override when set to 1 and the module's code is on disk
REDIS_HOST, REDIS_SERVICE_PORTConnection host and port, cache:6379 by default
VORTEX_REDIS_EXTENSION_LOADEDWhen set to 1, applies the cache backend, the container YAML files, and the bootstrap container switch without the redis PHP extension

Reroute Email​

Reroute Email intercepts outgoing emails and redirects them to a configurable address instead of the intended recipients. You can then test email features in non-production environments without delivering mail to real users.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.reroute_email.php excludes the module from the exported configuration and enables rerouting in every environment except local, ci, and production.

Rerouting replaces the recipient of an outgoing message with the configured address, unless that recipient matches DRUPAL_REROUTE_EMAIL_ALLOWED. With rerouting disabled, every message reaches its intended recipient. Rerouting is therefore disabled only where that delivery is either wanted or already intercepted by other means.

The following table shows where rerouting is on, and why:

EnvironmentRerouting enabledReason
LocalNoPygmy already catches outgoing mail
CINoThe mail collector stores messages instead of sending them
DevelopmentYesPrevents accidental delivery to real users
PreviewYesPrevents accidental delivery to real users
StageYesStage runs a copy of production content, so any address that survives database sanitization is a real one
ProductionNoProduction emails must reach actual recipients

Rerouting is the fall-through default, so it's also enabled in any custom environment type set through ENVIRONMENT_TYPE.

Rerouting is off in ci so that tests can assert on the address a message was sent to. With rerouting on, every message would carry the rerouting address instead of the intended one.

A site that deselects this module during installation still sends no mail from ci, because the mail collector stores messages there regardless. That site does send mail to real recipients in development, preview, stage, and custom environments.

The override reads the following variables:

VariableDefaultPurpose
DRUPAL_REROUTE_EMAIL_ADDRESSwebmaster@your-site-domain.exampleAddress to receive all rerouted emails
DRUPAL_REROUTE_EMAIL_ALLOWED*@your-site-domain.examplePattern for addresses allowed to bypass rerouting

To disable email rerouting in an environment where it would otherwise be enabled, set DRUPAL_REROUTE_EMAIL_DISABLED to 1 there. This is the supported way for a stage environment to send real mail during user acceptance testing.

Example settings.reroute_email.php
<?php

/**
* @file
* Reroute email settings.
*/

declare(strict_types=1);

use DrevOps\EnvironmentDetector\Environment;

$settings['config_exclude_modules'][] = 'reroute_email';

// Default reroute email address and allowed list.
$config['reroute_email.settings']['address'] = getenv('DRUPAL_REROUTE_EMAIL_ADDRESS') ?: 'webmaster@your-site-domain.example';
$config['reroute_email.settings']['allowed'] = getenv('DRUPAL_REROUTE_EMAIL_ALLOWED') ?: '*@your-site-domain.example';

if (in_array($settings['environment'], [
Environment::LOCAL,
Environment::CI,
Environment::PRODUCTION,
])) {
// Deliver every message to its intended recipient. Local and CI capture
// outgoing mail by other means, and production sends to real recipients.
$config['reroute_email.settings']['enable'] = FALSE;
}
else {
// Send every outgoing message to the address above instead of to its
// intended recipient, unless that recipient matches the allowed list.
$config['reroute_email.settings']['enable'] = TRUE;
}

// Allow an environment to opt out of the rerouting set above.
if (getenv('DRUPAL_REROUTE_EMAIL_DISABLED') === '1') {
// Deliver every message to its intended recipient.
$config['reroute_email.settings']['enable'] = FALSE;
}

RobotsTxt​

RobotsTxt serves robots.txt from Drupal and lets you edit it in the administration UI, which helps when the file can't live on disk, for example in multisite setups. Vortex keeps core's static robots.txt out of the webroot through the drupal-scaffold file mapping in composer.json, so the module answers every request for it.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.robotstxt.php serves a Disallow: / file outside production, so non-production environments aren't indexed.

SDC Devel​

SDC Devel provides development and validation tooling for Single Directory Components (SDC), reporting issues in component definitions and templates.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.sdc_devel.php excludes it from the exported configuration.

Search API​

Search API provides a framework for building search experiences with pluggable indexing backends. It stays required in every project.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step, together with Search API Solr, when the Solr service is selected. The ys_search module depends on it too. Without Solr, nothing installs it.

Configuration​

No settings override.

Search API Solr​

Search API Solr is a Search API backend that integrates Apache Solr. Ships only when the Solr service is selected.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step, and as a dependency of the ys_search module.

Configuration​

No settings override.

Security Kit​

Security Kit adds configurable security-hardening HTTP headers, including Content Security Policy and anti-framing protection.

  • Installed: Required only, not installed during provisioning. Enable it when the project needs it.

Configuration​

settings.seckit.php disables the Content Security Policy and the upgrade-insecure-requests header locally and in CI, where the site isn't served over HTTPS.

Shield​

Shield restricts access to your site by requiring HTTP authentication credentials.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.shield.php forces Shield on in non-production environments other than local and ci, where it's forced off. Production is left untouched, so Shield stays under UI control there.

The following table shows where Shield is on, and why:

EnvironmentShield enabledReason
LocalNoNo need for HTTP auth during local development
CINoAutomated tests must access the site freely
DevelopmentYesProtects development environments from crawlers
PreviewYesProtects preview environments from crawlers
StageYesProtects staging environments from public access
ProductionNot enforcedLeft to the site configuration: enable or disable it through the UI

The override reads the following variables:

VariableDefaultPurpose
DRUPAL_SHIELD_USERNoneHTTP authentication username, applied only when DRUPAL_SHIELD_PASS is set too
DRUPAL_SHIELD_PASSNoneHTTP authentication password, applied only when DRUPAL_SHIELD_USER is set too
DRUPAL_SHIELD_PRINTRestricted access., set in .envMessage shown in the authentication prompt. The module's own default applies when unset
DRUPAL_SHIELD_ALLOW_ACME_CHALLENGENoneSet to 1 to keep the /.well-known/acme-challenge/* path open for Let's Encrypt certificate generation

Shield stays on in development, preview, and stage even when the credentials are missing. Set DRUPAL_SHIELD_USER and DRUPAL_SHIELD_PASS in those environments, or the prompt accepts only the credentials stored in the site's configuration, if there are any.

To disable Shield in an environment where it would otherwise be enabled, set DRUPAL_SHIELD_DISABLED to 1 there. This is useful for temporary access during debugging or when an environment doesn't require protection.

Example settings.shield.php
<?php

/**
* @file
* Shield settings.
*/

declare(strict_types=1);

use DrevOps\EnvironmentDetector\Environment;

// Default Shield credentials.
//
// Shield can be enabled and disabled in production through UI.
//
// For other environments, Shield is enforced to be enabled.
// 'DRUPAL_SHIELD_USER' and 'DRUPAL_SHIELD_PASS' environment variables must
// be added in the environment or there will be no way to bypass HTTP Auth.
//
// Note that this approach is a bit different from the other settings, where
// we enable and disable features based on the presence of environment
// variables: we must not disable Shield even if the environment variables
// are not present.
//
// Enforce Shield in all non-prod environments.
if ($settings['environment'] !== Environment::PRODUCTION) {
$config['shield.settings']['shield_enable'] = TRUE;

// But bypass Shield for CI and local environments.
if ($settings['environment'] === Environment::CI || $settings['environment'] === Environment::LOCAL) {
$config['shield.settings']['shield_enable'] = FALSE;
}
}

// Set credentials, but only if the environment variables are present.
$shield_user = getenv('DRUPAL_SHIELD_USER');
$shield_pass = getenv('DRUPAL_SHIELD_PASS');
if (!empty($shield_user) && !empty($shield_pass)) {
$config['shield.settings']['credentials']['shield']['user'] = $shield_user;
$config['shield.settings']['credentials']['shield']['pass'] = $shield_pass;
}

// Allow to override the title of the shield pop-up.
$shield_print = getenv('DRUPAL_SHIELD_PRINT');
if (!empty($shield_print)) {
$config['shield.settings']['print'] = $shield_print;
}

// Allow to disable Shield completely in the environment.
if (getenv('DRUPAL_SHIELD_DISABLED') === '1') {
$config['shield.settings']['shield_enable'] = FALSE;
}

// Allow ACME challenge path for Let's Encrypt certificate generation.
if (getenv('DRUPAL_SHIELD_ALLOW_ACME_CHALLENGE') === '1') {
$config['shield.settings']['method'] = 0;
$shield_acme_path = '/.well-known/acme-challenge/*';
$shield_existing_paths = $config['shield.settings']['paths'] ?? '';
$config['shield.settings']['paths'] = str_contains($shield_existing_paths, $shield_acme_path) ? $shield_existing_paths : trim($shield_existing_paths . "\n" . $shield_acme_path);
}

Stage File Proxy​

Stage File Proxy fetches media files from a remote site on demand, so local environments don't need a full copy of the files directory.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.stage_file_proxy.php sets the origin from DRUPAL_STAGE_FILE_PROXY_ORIGIN outside production. The shipped .env file sets it to https://www.your-site-domain.example. When DRUPAL_SHIELD_USER and DRUPAL_SHIELD_PASS are both set, the override adds them to an https:// origin URL, so a shielded origin still serves files. It also turns off redirects to the origin, so the module downloads each requested file and keeps a local copy.

Storybook​

Storybook renders the custom theme's component stories through Drupal, so the component library shows the markup the site produces. Ships only when Storybook is selected during installation, which requires a custom theme.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step, which also turns on Twig development mode in the local environment.

Later in the same deployment, the BuildStorybookDeployStep deploy step builds the static component library in the local, ci, and development environments. Set DRUPAL_STORYBOOK_SKIP to 1 to skip that build.

Configuration​

settings.storybook.php excludes it from the exported configuration. In the local, ci, and development environments, it also loads services.storybook.yml, which turns on the module's development mode and lets the Storybook development server on localhost fetch story renders.

➡️ See Storybook for the component library and its commands.

Testmode​

Testmode filters the listings in registered views during automated tests, so a test sees only content with a test title prefix such as [TEST].

  • Installed: As a dependency of the ys_demo demo module, declared in ys_demo.info.yml.

Configuration​

settings.testmode.php excludes it from the exported configuration.

➡️ See Testmode for the configuration and the Behat integration.

XML Sitemap​

XML sitemap generates a multilingual XML sitemap to help search engines index the site.

  • Installed: By the EnableDevelopmentModulesDeployStep deploy step.

Configuration​

settings.xmlsitemap.php stops cron regeneration and search engine submission outside production, so non-production environments are never advertised.