Settings
Drupal site configuration — including database connections, file paths, and
environment-specific behavior — is controlled through the settings.php
and
services.yml
files. This section explains how Vortex structures and
extends these files to support consistent setup across environments.
Vortex ships with its own streamlined version of
the settings.php
and
services.yml
files.
It provides logic to detect the current environment (such as local, CI, or production) and apply settings conditionally. You can also define configuration overrides for individual modules if needed.
The default Drupal Scaffold's default.settings.php
and default.services.yml
files are also provided if you choose to use them instead.
Approach
Managing Drupal settings across multiple environments — such as local, CI, development, staging, and production — often requires conditional configuration. Different environments may need to enable or disable modules, change performance settings, use different APIs, or point to different services.
The challenge is that Drupal doesn’t offer a standard way to manage these environment-specific differences. Its configuration system is not designed to handle conditional logic, such as applying different settings based on runtime environment, or retrieving values from environment variables.
Modules like config_split
can help by allowing you to maintain separate
configuration sets per environment, but they are limited: they don’t support
environment-based conditions inside the configuration YAML files, cannot access
environment variables directly, and are not suitable when you need dynamic logic
(e.g. setting values based on external service URLs).
Vortex does support config_split
as part of its standard tooling, and it’s
ideal for use cases where declarative configuration is sufficient — for example,
enabling a module in staging but not production. However, when settings require
conditional logic or need to pull values from the environment, config_split
does not suffice. In addition, it is not possible to automatically test which
settings are applied in a specific environment.
Vortex addresses this problem with a clear and maintainable approach:
- The environment type is detected based on the environment where the site is running. This detection step is isolated and does not apply any configuration overrides.
- Configuration overrides are defined in per-module override files, with conditions applied based on the detected environment type.
This structure offers several benefits:
- It keeps environment detection separate from configuration logic.
- It makes it easy to see how a module behaves in a specific environment — all in one place.
- If a module is no longer needed, its override file can be safely removed
without modifying the
settings.php
file. - It prevents environment-specific settings from leaking into unrelated parts of the configuration.
Guidelines
When working with settings, follow these guidelines to ensure clarity, consistency, and maintainability:
-
Do not modify
settings.php
directly.
Use environment variables for general settings or per-module override files for any custom or environment-aware configuration. -
Keep all overrides isolated by module.
Each file should encapsulate logic for a single module only. If a module is removed, its override file should be removable without affecting unrelated settings. -
Use environment variables for configuration that changes by environment.
Prefix all such variables withDRUPAL_
(e.g.DRUPAL_MY_SETTING
) to easily distinguish them from other environment variables.
Always define a default hardcoded value for each environment variable. -
Use conditions based on environment type within per-module override files.
This allows for environment-specific configuration without cluttering the mainsettings.php
file.
Use the$settings['environment']
variable to check the current environment type.
Example of the Environment indicator
module settings file
<?php
/**
* @file
* Environment indicator settings.
*/
declare(strict_types=1);
$config['environment_indicator.indicator']['name'] = $settings['environment'];
$config['environment_indicator.indicator']['bg_color'] = '#006600';
$config['environment_indicator.indicator']['fg_color'] = '#ffffff';
$config['environment_indicator.settings']['toolbar_integration'] = [TRUE];
$config['environment_indicator.settings']['favicon'] = TRUE;
switch ($settings['environment']) {
case ENVIRONMENT_PROD:
$config['environment_indicator.indicator']['bg_color'] = '#ef5350';
$config['environment_indicator.indicator']['fg_color'] = '#000000';
break;
case ENVIRONMENT_STAGE:
$config['environment_indicator.indicator']['bg_color'] = '#fff176';
$config['environment_indicator.indicator']['fg_color'] = '#000000';
break;
case ENVIRONMENT_DEV:
$config['environment_indicator.indicator']['bg_color'] = '#4caf50';
$config['environment_indicator.indicator']['fg_color'] = '#000000';
break;
}
Settings file structure
The settings.php
file is organized into the following sections:
Click here to see the contents of the settings.php
file
<?php
/**
* @file
* Drupal site-specific configuration file.
*
* Copy `default.settings.local.php` and `default.services.local.yml` to
* `settings.local.php` and `services.local.yml` respectively to
* enable local overrides.
*
* It’s recommended to leave this file unchanged and manage configuration
* through environment variables and module-specific settings files instead.
* This allows for better portability and easier management of settings across
* environments.
* @see https://www.vortextemplate.com/docs/drupal/settings
*
* phpcs:disable Drupal.Commenting.InlineComment.NoSpaceBefore
* phpcs:disable Drupal.Commenting.InlineComment.SpacingAfter
* phpcs:disable DrupalPractice.Commenting.CommentEmptyLine.SpacingAfter
* phpcs:disable DrupalPractice.CodeAnalysis.VariableAnalysis.UnusedVariable
*/
declare(strict_types=1);
////////////////////////////////////////////////////////////////////////////////
/// DATABASE ///
////////////////////////////////////////////////////////////////////////////////
// @see https://www.vortextemplate.com/docs/drupal/settings#database
$databases = [
'default' =>
[
'default' =>
[
'database' => getenv('DATABASE_NAME') ?: getenv('DATABASE_DATABASE') ?: getenv('MARIADB_DATABASE') ?: 'drupal',
'username' => getenv('DATABASE_USERNAME') ?: getenv('MARIADB_USERNAME') ?: 'drupal',
'password' => getenv('DATABASE_PASSWORD') ?: getenv('MARIADB_PASSWORD') ?: 'drupal',
'host' => getenv('DATABASE_HOST') ?: getenv('MARIADB_HOST') ?: 'localhost',
'port' => getenv('DATABASE_PORT') ?: getenv('MARIADB_PORT') ?: '3306',
'charset' => getenv('DATABASE_CHARSET') ?: getenv('MARIADB_CHARSET') ?: getenv('MYSQL_CHARSET') ?: 'utf8mb4',
'collation' => getenv('DATABASE_COLLATION') ?: getenv('MARIADB_COLLATION') ?: getenv('MYSQL_COLLATION') ?: 'utf8mb4_general_ci',
'prefix' => '',
'driver' => 'mysql',
],
],
];
////////////////////////////////////////////////////////////////////////////////
/// GENERAL ///
////////////////////////////////////////////////////////////////////////////////
// @see https://www.vortextemplate.com/docs/drupal/settings#general
$app_root = $app_root ?? DRUPAL_ROOT;
$site_path = $site_path ?? 'sites/default';
$contrib_path = $app_root . '/' . (is_dir($app_root . '/modules/contrib') ? 'modules/contrib' : 'modules');
// Public files directory relative to the Drupal root.
$settings['file_public_path'] = getenv('DRUPAL_PUBLIC_FILES') ?: 'sites/default/files';
// Private files directory relative to the Drupal root.
$settings['file_private_path'] = getenv('DRUPAL_PRIVATE_FILES') ?: 'sites/default/files/private';
// Temporary file directory.
$settings['file_temp_path'] = getenv('DRUPAL_TEMPORARY_FILES') ?: getenv('TMP') ?: '/tmp';
// Location of the site configuration files relative to the Drupal root. If not
// set, the default location is inside a randomly-named directory in the public
// files path.
if (!empty(getenv('DRUPAL_CONFIG_PATH'))) {
$settings['config_sync_directory'] = getenv('DRUPAL_CONFIG_PATH');
}
// Load services definition file.
$settings['container_yamls'][] = $app_root . '/' . $site_path . '/services.yml';
// Use DRUPAL_HASH_SALT or the database host name for salt.
$settings['hash_salt'] = getenv('DRUPAL_HASH_SALT') ?: hash('sha256', $databases['default']['default']['host']);
// Timezone settings.
ini_set('date.timezone', getenv('DRUPAL_TIMEZONE') ?: getenv('TZ') ?: 'UTC');
date_default_timezone_set(getenv('DRUPAL_TIMEZONE') ?: getenv('TZ') ?: 'UTC');
// Maintenance theme.
$settings['maintenance_theme'] = getenv('DRUPAL_MAINTENANCE_THEME') ?: getenv('DRUPAL_THEME') ?: 'claro';
// Trusted Host Patterns.
// See https://www.drupal.org/node/2410395 for more information on how to
// populate this array.
// Settings for specific environments (including a local container-based
// environment) are populated within provider-specific
// `includes/providers/settings.<provider>.php` files.
// @see https://www.vortextemplate.com/docs/drupal/settings#per-module-overrides
$settings['trusted_host_patterns'] = [
'^localhost$',
];
// Modules excluded from config export.
// Populate this array in the `includes/modules/settings.<module>.php` file.
$settings['config_exclude_modules'] = [];
// The default list of directories that will be ignored by Drupal's file API.
$settings['file_scan_ignore_directories'] = [
'node_modules',
'bower_components',
];
// The default number of entities to update in a batch process.
$settings['entity_update_batch_size'] = 50;
////////////////////////////////////////////////////////////////////////////////
/// ENVIRONMENT TYPE DETECTION ///
////////////////////////////////////////////////////////////////////////////////
// @see https://www.vortextemplate.com/docs/drupal/settings#environment-type-detection
// Use these constants anywhere in code to alter behavior for a specific
// environment.
// @codeCoverageIgnoreStart
if (!defined('ENVIRONMENT_LOCAL')) {
define('ENVIRONMENT_LOCAL', 'local');
}
if (!defined('ENVIRONMENT_CI')) {
define('ENVIRONMENT_CI', 'ci');
}
if (!defined('ENVIRONMENT_DEV')) {
define('ENVIRONMENT_DEV', 'dev');
}
if (!defined('ENVIRONMENT_STAGE')) {
define('ENVIRONMENT_STAGE', 'stage');
}
if (!defined('ENVIRONMENT_PROD')) {
define('ENVIRONMENT_PROD', 'prod');
}
// @codeCoverageIgnoreEnd
// Default environment type is 'local'.
$settings['environment'] = ENVIRONMENT_LOCAL;
// Load provider-specific environment detection settings.
if (file_exists($app_root . '/' . $site_path . '/includes/providers')) {
$files = glob($app_root . '/' . $site_path . '/includes/providers/settings.*.php');
if ($files) {
foreach ($files as $filename) {
require $filename;
}
}
}
// Allow to override an environment type using the DRUPAL_ENVIRONMENT variable.
if (!empty(getenv('DRUPAL_ENVIRONMENT'))) {
$settings['environment'] = getenv('DRUPAL_ENVIRONMENT');
}
////////////////////////////////////////////////////////////////////////////////
/// PER-MODULE OVERRIDES ///
////////////////////////////////////////////////////////////////////////////////
// @see https://www.vortextemplate.com/docs/drupal/settings#per-module-overrides
if (file_exists($app_root . '/' . $site_path . '/includes/modules')) {
$files = glob($app_root . '/' . $site_path . '/includes/modules/settings.*.php');
if ($files) {
foreach ($files as $filename) {
require $filename;
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// LOCAL OVERRIDE ///
////////////////////////////////////////////////////////////////////////////////
// @see https://www.vortextemplate.com/docs/drupal/settings#local-overrides
// Load local override configuration, if available.
//
// Copy `default.settings.local.php` and `default.services.local.yml` to
// `settings.local.php` and `services.local.yml` respectively to enable local
// overrides.
//
// `services.local.yml` is loaded from within `settings.local.php`.
//
// Keep this code block at the end of this file to take full effect.
// @codeCoverageIgnoreStart
if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
require $app_root . '/' . $site_path . '/settings.local.php';
}
// @codeCoverageIgnoreEnd
Database
Database configuration is managed through environment variables with sensible defaults, offering flexibility across hosting environments while keeping the setup consistent.
To support a variety of hosting providers and container platforms, multiple environment variable names are accepted for each setting:
Variable | Alternative Variables | Default | Purpose |
---|---|---|---|
DATABASE_NAME | DATABASE_DATABASE , MARIADB_DATABASE | drupal | Database name |
DATABASE_USERNAME | MARIADB_USERNAME | drupal | Database username |
DATABASE_PASSWORD | MARIADB_PASSWORD | drupal | Database password |
DATABASE_HOST | MARIADB_HOST | localhost | Database host |
DATABASE_PORT | MARIADB_PORT | 3306 | Database port |
DATABASE_CHARSET | MARIADB_CHARSET , MYSQL_CHARSET | utf8mb4 | Character set |
DATABASE_COLLATION | MARIADB_COLLATION , MYSQL_COLLATION | utf8mb4_general_ci | Collation |
These variables normally should not be modified unless you are using a custom database setup or a different hosting provider that requires specific configuration. The defaults are designed to work with most common setups, including local development environments and popular hosting providers.
General
This section configures generic site settings such as file paths, security patterns, performance optimizations, and essential directories. These settings are identical across all environment types.
The following environment variables can be used to customize general settings:
Variable | Alternative Variables | Default | Purpose |
---|---|---|---|
DRUPAL_CONFIG_PATH | ../config/default | Location of configuration sync directory | |
DRUPAL_PUBLIC_FILES | sites/default/files | Public files directory path | |
DRUPAL_PRIVATE_FILES | sites/default/files/private | Private files directory path | |
DRUPAL_TEMPORARY_FILES | /tmp | Temporary files directory path | |
DRUPAL_HASH_SALT | Generated from database host | Cryptographic salt for security | |
DRUPAL_TIMEZONE | TZ | UTC | Site timezone |
DRUPAL_MAINTENANCE_THEME | DRUPAL_THEME | claro | Theme used during maintenance mode |
DRUPAL_CACHE_PAGE_MAX_AGE | 900 | Page cache expiration time (seconds) |
Environment type detection
Vortex defines an environment type to represent the context in which the Drupal site is running — such as local, CI, development, staging, or production. This concept allows the system to conditionally adjust settings and behaviors depending on the runtime environment.
The environment type is detected automatically based on known hosting provider indicators or predefined environment variables. Detection logic is intentionally isolated from configuration logic — it identifies the context but does not apply any overrides directly.
Once detected, the environment type is stored in the $settings['environment']
value, which can be used by modules, settings overrides, and shell scripts to
drive environment-specific behavior.
Environment type constants
Vortex defines the following constants to represent supported environments:
ENVIRONMENT_LOCAL
ENVIRONMENT_CI
ENVIRONMENT_DEV
ENVIRONMENT_STAGE
ENVIRONMENT_PROD
These constants are used consistently across settings files and scripts to determine conditional behavior.
Detection mechanism
The detection process uses indicators provided by known cloud hosting platforms. Logic
for supported providers is stored in the includes/providers
directory.
To add support for a custom platform, simply create a settings.[provider].php
file in that directory with the relevant detection logic.
- If a provider is detected, the default environment type is set to
ENVIRONMENT_DEV
. - Additional provider-specific conditions can elevate this to
ENVIRONMENT_STAGE
orENVIRONMENT_PROD
. - If no provider is detected, the environment type defaults to
ENVIRONMENT_LOCAL
.
It is important to note that this detection logic is only responsible for identifying the environment type. It does not apply any configuration changes. Those are handled separately in per-module override files, making the setup modular and independent of the cloud hosting platforms.
Overriding environment type
You can override the detected environment type by setting the
DRUPAL_ENVIRONMENT
environment variable.
This is useful when:
- Testing environment-specific behavior locally.
- Working around gaps in the detection logic.
- Forcing a known environment type for debugging.
For example, add DRUPAL_ENVIRONMENT=ci
to your .env.local
file to simulate
the CI environment locally.
Per-module overrides
This section automatically includes module-specific settings from files in the
includes/modules
directory. Each file follows the naming pattern
settings.[module].php
and contains configuration overrides for a specific
Drupal module.
Vortex ships with pre-configured settings for several popular contributed modules, each isolated in its own file for easy maintenance and removal.
Creating custom module settings
To add settings for a new module, create a file following the naming pattern:
web/sites/default/includes/modules/settings.[module_name].php
Each settings file should:
- Use environment type constants (
ENVIRONMENT_LOCAL
,ENVIRONMENT_PROD
, etc.) for conditional logic - Leverage environment variables for configuration values
- Provide sensible defaults when environment variables are not set
- Be self-contained and removable without affecting other modules
Example of the Environment indicator
module settings file
<?php
/**
* @file
* Environment indicator settings.
*/
declare(strict_types=1);
$config['environment_indicator.indicator']['name'] = $settings['environment'];
$config['environment_indicator.indicator']['bg_color'] = '#006600';
$config['environment_indicator.indicator']['fg_color'] = '#ffffff';
$config['environment_indicator.settings']['toolbar_integration'] = [TRUE];
$config['environment_indicator.settings']['favicon'] = TRUE;
switch ($settings['environment']) {
case ENVIRONMENT_PROD:
$config['environment_indicator.indicator']['bg_color'] = '#ef5350';
$config['environment_indicator.indicator']['fg_color'] = '#000000';
break;
case ENVIRONMENT_STAGE:
$config['environment_indicator.indicator']['bg_color'] = '#fff176';
$config['environment_indicator.indicator']['fg_color'] = '#000000';
break;
case ENVIRONMENT_DEV:
$config['environment_indicator.indicator']['bg_color'] = '#4caf50';
$config['environment_indicator.indicator']['fg_color'] = '#000000';
break;
}
Local overrides
At the end of the settings.php
, there is an option to include additional local
settings. This allows you to override some settings for the local
environment without affecting the main configuration. You can
copy default.settings.local.php
and default.services.local.yml
to settings.local.php
and services.local.yml
, respectively, to utilize this
functionality.
Click here to see the contents of the default.settings.local.php
file
<?php
/**
* @file
* Settings file for local environment.
*/
declare(strict_types=1);
if (file_exists($app_root . '/' . $site_path . '/services.local.yml')) {
$settings['container_yamls'][] = $app_root . '/' . $site_path . '/services.local.yml';
}
// Show all error messages on the site.
$config['system.logging']['error_level'] = 'all';
// Disable caching.
$config['system.performance']['cache']['page']['max_age'] = 0;
$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['extension_discovery_scan_tests'] = FALSE;
// Disable CSS files aggregation.
$config['system.performance']['css']['preprocess'] = FALSE;
// Disable JavaScript files aggregation.
$config['system.performance']['js']['preprocess'] = FALSE;
// Hide admin toolbar. Useful for themeing while logged in as admin.
// $settings['hide_admin_toolbar'] = TRUE;
Click here to see the contents of the default.services.local.yml
file
parameters:
http.response.debug_cacheability_headers: true
# Disable twig debugging and auto reload, plus enable twig caching.
twig.config:
debug: true
auto_reload: null
# Twig cache allows Xdebug to work with .twig files.
cache: true
services:
cache.backend.null:
class: Drupal\Core\Cache\NullBackendFactory
Testing settings with unit tests
Vortex includes a set of unit tests to verify that settings are applied correctly for each detected environment type.
These tests are intended to be maintained within your project, helping you ensure that environment-driven configuration — including both environment types and environment variables — behaves as expected.
To run unit tests for settings:
vendor/bin/phpunit --group=drupal_settings
You may simply remove these tests if you do not want to maintain them.