Configuring Craft
Craft can be configured to work in a way that makes sense for you, your team, and your infrastructure.
Broadly, configuration refers to how Craft will behave in a particular environment. Most applications will only require database connection information to work, but as you get familiar with more of Craft’s features, install plugins, or start using additional services, you may need to provide additional config.
We’ll start by looking at how Craft builds its config in a context-aware way, then get into some specific options. Keep in mind that—unlike most aspects of a Craft project—this will require some basic PHP knowledge.
Project config is a discrete concept, but was designed to integrate with the core config system. We’ll look at some examples in just a moment.
# Where Configuration Happens
# Config Files
The most common way to customize your Craft project is by editing files in the config/
folder. These files act as a canonical map of what customizations you’ve made to a project, and as a bridge between specific settings and environment variables.
Concern | File(s) | Description |
---|---|---|
General Configuration | general.php | Global options that can affect the front-end, control panel, debugging, etc. |
Database Settings | db.php | Connection settings for your database. |
Custom Options | custom.php | Arbitrary key-value storage for your own options. |
Routing | routes.php | Custom HTTP routes. |
Application Configuration | app.php , app.web.php , app.console.php | Overrides for the root application and any of its Components (opens new window). |
Plugin Settings | {plugin-handle}.php , or other custom files | Consult the plugin’s documentation for specifics. |
Advanced | Specific library options and/or behaviors that may be exposed in a non-standard way. |
You may find other files in the config/
folder, like license.key
or the project/
folder. Craft (and many plugins) will ask you to place config-adjacent files here, even if they don’t work in a consistent way.
Sensitive credentials like your database’s password should be kept out of tracked files—but instead of ignoring config files outright, let’s take a look at some options.
# .env
New Craft projects (opens new window) use DotEnv (opens new window) to load values into the environment from a .env
file in the root of your project. A basic .env
file contains pairs of keys and values:
CRAFT_APP_ID=my-project
CRAFT_ENVIRONMENT=dev
# ...and comments!
These values can be referenced in your config files by calling App::env() (opens new window), or using them directly in a control panel setting. Use of PHP’s getenv()
directly is discouraged, due to issues with thread-safety (opens new window). The equivalent Twig function uses App::env()
, and is therefore fine to use in templates.
Craft doesn’t require your variables to follow any kind of naming convention, but it will automatically discover some specific environment variables for general and database settings.
For most installations, the .env
file is the only place where secrets should be stored. Avoid checking it in to version control!
Some platforms (especially those with ephemeral filesystems) provide a GUI for managing environment variables in lieu of using a .env
file, and will automatically inject them when the server or process starts. App::env()
is still the recommended method for retrieving environment variables set in this way.
# Entry Script
Craft will also respond to a handful of specific environment variables or PHP constants, as long as they are set prior to bootstrapping the application in your entry script. The starter project (opens new window) shares a bootstrap.php
file between web/index.php
and the craft
executable to consolidate the definition of constants.
# Secrets
You can store sensitive values that won’t leak into the process’s environment in a special “secrets” file.
4.5.0+ The path to this file is determined by the CRAFT_SECRETS_PATH
environment variable or constant. When defined, Craft will attempt to include a file at that path (presumed to be a PHP script that return
s an associative array), and checks it prior to resolving any environment variable or constant with craft\helpers\App::env() (opens new window).
return [
'SUPER_SECRET_KEY' => '...',
];
Even though secrets aren’t automatically loaded into the environment on every request, they can still be accessed via application helpers, Twig templates (like system messages), other PHP scripts, or anyone with direct filesystem access.
This is only recommended in situations where environment variable exfiltration is among the last attack surfaces. If your server supports any form of remote access (say, via SSH), this is not a practical security measure!
# Setting and Resolving Options
Each setting accepts specific types and values (like an integer, interval expression string, or boolean), but Craft can resolve them in two ways:
- Statically: A value is set explicitly in a config file, and is the same in all environments. Example: Customizing file types that can be uploaded.
- Dynamically: Values are only known at runtime, or are set conditionally based on the current environment. Typically, this will involve a call to App::env() (opens new window) using the name of an environment variable that is expected to exist—or whose absence is significant. Example: Dev mode, database connection details, or a storage bucket URL.
# Priority
Craft takes the first discovered value, in this order:
- Environment Overrides: For general and database settings, Craft looks for special environment variables and PHP constants.
- Config Files: Craft evaluates and merges multi-environment and application type PHP config files.
- Defaults: Every option has a default value, even if it’s
null
. You can find these defaults in the documentation for each setting.
# Style: Map vs. Fluent
At its simplest, a config file returns a map of settings:
use craft\helpers\App;
return [
'devMode' => App::env('DEV_MODE') ?? false,
'userSessionDuration' => 'P1D',
];
If you are interested in auto-completion and type hints from your editor, the equivalent "fluent" style declaration 4.2.0+ would look like this:
use craft\config\GeneralConfig;
use craft\helpers\App;
return GeneralConfig::create()
->devMode(App::env('DEV_MODE') ?? false)
->userSessionDuration('P1D');
Each option becomes a method call, accepting the same values that you would provide in a config map. The modified configuration object is returned to allow chaining.
Fluent config is currently only available for general and database settings, and unsupported in plugins, custom config files, and application config. When in doubt, use a config map!
Config files can also return a closure that accepts a single $config
argument and returns a config object.
4.11.0+
// config/general.php
use craft\config\GeneralConfig;
return function(GeneralConfig $config) {
return $config
->aliases([
'@webroot' => dirname(__DIR__) . '/web',
])
// ...
;
};
Craft will always pass an instance of craft\config\GeneralConfig (opens new window) or craft\config\DbConfig (opens new window) to a closure in the primary general or database config files, respectively—but application type-specific files should accept whatever the primary file returns:
return [
'aliases' => [
'@webroot' => dirname(__DIR__) . '/web',
],
];
There is no equivalent to GeneralConfig
and DbConfig
for application. If you return an array from the primary file, there is limited value in using a closure in an application type-specific file.
The GeneralConfig
class has a special addAlias()
method that allows you to merge additional aliases, when using closures and fluent config.
# Application Types 4.11.0+
Craft has two primary application types—web and console. Web requests are typically initiated by an HTTP server via index.php
; console requests are initiated from the craft
executable, on the command line.
You can provide configuration that targets a specific application type by creating additional general, database, application, or custom configuration files with the appropriate suffix:
Category | File | Application Type |
---|---|---|
General | general.php | All |
general.web.php | Web only | |
general.console.php | Console only | |
Database | db.php | All |
db.web.php | Web only | |
db.console.php | Console only | |
Application | app.php | All |
app.web.php | Web only | |
app.console.php | Console only |
The primary config file is always evaluated, but only one of the web
or console
files are merged on top of it, when present.
See the previous section for some examples of how to combine application type-specific configuration and config styles.
# Types and Values
Most config settings expect a scalar (opens new window) value, and will generate exceptions if they are not (and can not be coerced to) a valid type.
Normalization may occur on some values. For instance, any setting that expects a “file size” (like maxUploadFileSize
) will interpret a numeric value in bytes—but passing a string allows you to use other formats like 256M
or 1G
by virtue of Craft normalizing the value with ConfigHelper::sizeInBytes() (opens new window).
A few settings support complex types, like arrays and closures:
use craft\config\GeneralConfig;
return GeneralConfig::create()
// Arrays:
->extraFileKinds([
'fonts' => [
'extensions' => ['otf', 'ttf', 'woff', 'woff2'],
],
])
// Functions or "closures":
->postLoginRedirect(function($siteHandle) {
// Perform tests on the signed-in User:
$user = Craft::$app->getUser()->getIdentity();
// Send to their account, if their profile is incomplete...
if (empty($user->someProfileField)) {
return 'account/profile';
}
// ...or the homepage, by default:
return '/';
});
In this example, the function passed to postLoginRedirect
will be called by ConfigHelper::localizedValue() (opens new window) with the current site’s handle, only at the time the value needed. This distinction is important, because Craft is not fully initialized when configuration files are evaluated, but will be by the time the application is ready to redirect a logged-in user.
Keep in mind that while scalar values are automatically normalized during configuration, the return value of a function is not.
Refer to a config property’s documentation for a full list of its supported types and values!
# Multi-Environment Configs
Config files using the traditional map style can define configurations for each of your environments all in one place—called a “multi-environment config”.
To establish that your config file should be treated as a multi-environment config, it must have a *
key which defines the base config that should be applied to each of your environments, followed by additional keys which will be matched against the CRAFT_ENVIRONMENT
environment variable or PHP constant.
When determining the exact configuration that should be used for a request, the base config and environment-specific config arrays will be merged together. If any config settings are defined by both arrays, the environment-specific config will take precedence.
For example, given the following multi-environment config:
// -- config/general.php --
return [
'*' => [
// Applies to all environments:
'defaultWeekStartDay' => 1,
'omitScriptNameInUrls' => true,
'allowAdminChanges' => false,
],
'dev' => [
// Only applies to development environments, overriding anything in `*`:
'allowAdminChanges' => true,
'devMode' => true,
],
'production' => [
// Only applies to the production environment, overriding anything in `*`:
'cpTrigger' => 'secret-word',
],
];
Environments matching dev
would end up with the following merged config:
return [
'defaultWeekStartDay' => 1,
'omitScriptNameInUrls' => true,
'allowAdminChanges' => true,
'devMode' => true,
];
Make sure your key(s) are sufficiently unique! Craft reads your array of config settings from top to bottom, applying config settings wherever the CRAFT_ENVIRONMENT
value contains the key.
If the environment cannot be determined, your server’s hostname will be used.
Do not combine fluent and multi-environment config in the same file. Merging fluent config models causes all previously-set values to be overwritten.
# Aliases
Some settings and functions in Craft support Yii aliases (opens new window), which are most often used as placeholders for file system paths and URLs.
Out of the box, Craft provides these aliases—but you can override them or provide new ones with the aliases config setting:
Alias | Description | Based On |
---|---|---|
@app | Path to Craft’s source code. | CRAFT_VENDOR_PATH |
@config | Path to your config/ folder. | CRAFT_BASE_PATH |
@contentMigrations | Path to your migrations/ folder. | CRAFT_BASE_PATH |
@craft | Path to Craft’s source code. | @app |
@dotenv | Path to your .env file. | CRAFT_DOTENV_PATH |
@lib | Path to extra libraries packaged with Craft. | @app |
@root | The root project path. | CRAFT_BASE_PATH |
@runtime | Path to your storage/runtime/ folder. | @storage |
@storage | Path to your storage/ folder. | CRAFT_STORAGE_PATH |
@templates | Path to your templates/ folder. | CRAFT_TEMPLATES_PATH |
@tests | Path to your tests/ folder. | CRAFT_TESTS_PATH |
@translations | Path to your translations/ folder. | CRAFT_TRANSLATIONS_PATH |
@vendor | Path to your vendor/ folder. | CRAFT_VENDOR_PATH |
@web | URL to the folder that contains the index.php file that was loaded for the request. | CRAFT_WEB_URL |
@webroot | Path to the folder that contains the index.php file that was loaded for the request. | CRAFT_WEB_ROOT |
Aliases can be set to plain strings, or to the content of an environment variable. Keep in mind that aliases are resolved recursively, so you can define one based on another (including those whose values came from the environment):
use craft\helpers\App;
return [
'aliases' => [
'@primaryUrl' => App::env('PRIMARY_SITE_URL'),
'@shared' => App::env('SHARED_PATH'),
'@uploads' => '@shared/web/uploads',
'@assets' => '@primaryUrl/uploads',
],
];
Assuming PRIMARY_SITE_URL
is defined as https://my-project.ddev.site
and SHARED_PATH
is /var/www/releases/123/shared
, these aliases would evaluate to:
@primaryUrl
:https://my-project.ddev.site
@shared
:/var/www/releases/123/shared
@uploads
:/var/www/releases/123/shared/web/uploads
@assets
:https://my-project.ddev.site/uploads
Recursive aliases are preferred to basic string interpolation, because they are evaluated at the time of use rather than definition. Aliases are only resolved at the beginning of a string.
# Environment Overrides
Craft allows some settings to be defined directly from environment variables, PHP constants, or secrets using the special CRAFT_
prefix.
Add the prefix to any general config (CRAFT_
) or database connection settings (CRAFT_DB_
) in screaming snake case (opens new window). For example:
- General: allowUpdates →
CRAFT_ALLOW_UPDATES
- Database:
port
→CRAFT_DB_PORT
- General: testToEmailAddress →
CRAFT_TEST_TO_EMAIL_ADDRESS
Any environment variable or constant names that match a known config setting (using the formula above) will have the highest priority! The CRAFT_
prefix is intended to reduce the likelihood of collisions with other environment variables that a server or platform might inject—it’s actually inadvisable to use this prefix when defining custom variables that aren’t intended to be used as overrides.
Enforcing a structure for database connection details (even with a multi-environment config file) can cause problems when working with others, or across environments. Overrides make it possible to use whatever connection parameters are available in the current environment, without having to maintain a config file just to map variables to config settings.
If you are working with others and your .env
isn’t checked in to version control (it probably shouldn’t be!), make sure you have a way of communicating what options are required to get your application running! A .env.example
file is a great place to store keys and comments, without exposing secrets—and it lets you simply copy the file when spinning up a new environment.
# Using Configured Values
Most configuration is applied automatically on every request, and requires no additional action.
However, Craft provides a powerful way to use dynamically-resolved config values in other parts of the system.
# Control Panel Settings
Most values in the Settings area of Craft’s control panel are recorded in Project config. While this makes schema changes much easier to move between environments, it presents a challenge when something like a URL needs to change per-environment, or an API key leaks into YAML files.
For this reason, Craft provides a way to bind system settings to dynamic aliases and environment variables.
Whenever you see this UI, you can provide a valid alias or environment variable name, in addition to plain values. Craft will always store and display the raw, unparsed value, but uses App::parseEnv() (opens new window) when the value is consumed. Here are some examples of settings for which dynamic values are useful:
- General Settings: System Name, Status, and Time Zone;
- Sites: Base URLs;
- Sections: Preview Target URIs;
- Asset Filesystems: Base URL, File System Path (Local only);
- Email: System Email Address, Sender Name, Email Template path, SMTP credentials;
Focusing one of these fields will immediately suggest some values. Type $
followed by an environment variable’s name or @
followed by an alias to narrow the suggestions and find your placeholder.
Aliases have the extra benefit of allowing extra path segments, so @primaryUrl/uploads
is a perfectly valid setting. If a combination of alias and path is used frequently, though, it might make sense to define a specific @uploads
alias and use that in the control panel, instead.
Plugins can add support for environment variables and aliases in their settings as well. See Environmental Settings to learn how.
# Templates and Modules
# Accessing Config Values
You can check the final resolved value of a setting in your templates or a module via the Config
service. For example, if you wanted to switch some debugging information on or off, you could do the following:
{# Output entry ID for debugging: #}
{% if craft.app.config.general.devMode %}
ID: <code>{{ entry.id }}</code>
{% endif %}
# Aliases and Environment Variables
In the event you need to evaluate an alias or environment variable directly in Twig or PHP, Craft provides some helpers:
{# Resolve an alias, recursively: #}
{{ alias('@uploadsBaseUrl') }}
{# Access a specific environment variable: #}
{{ getenv('SOME_ENV_VAR') }}
{# Fully resolve a value, as though it came from a control panel setting: #}
{{ parseEnv(craft.app.config.custom.myDynamicValue) }}
# Config Categories
To make config settings easier to find, they’re organized into a few groups.
# General
General config settings are set via the config/general.php
file, or using special environment variables.
# Database
Your database connection settings are set via the config/db.php
file, or using special environment variables.
# URL Rules
You can define custom URL rules (opens new window) in config/routes.php
. See Routing for more details.
# Application Configuration
Some projects may require customization of Craft application components beyond what is exposed through specific config files. This is done directly via the config/app.php
file.
# Advanced
In rare cases, you may need to customize parts of Craft that don’t follow the normal configuration scheme.
# Guzzle
Craft uses Guzzle (opens new window) to make HTTP requests, when…
- …checking for Craft updates;
- …sending a support request from the Craft Support widget;
- …loading RSS feeds from the Feeds widget;
- …working with assets on remote volumes, like Amazon S3;
You can customize the settings passed to Guzzle when initializing these requests by creating a guzzle.php
file in your config/
folder. The file does not support Craft’s multi-environment configuration and should only ever return an array with your config overrides at the top level.
return [
'headers' => ['Foo' => 'Bar'],
'query' => ['testing' => '123'],
'auth' => ['username', 'password'],
'proxy' => 'https://myproxy:1234',
];
The options defined here will be passed into new GuzzleHttp\Client
instances. See Guzzle’s documentation (opens new window) for a list of available options.
To use a proxy for all requests, set an httpProxy in general config. This will get merged with the Guzzle configuration, and passed to the front-end for use by JavaScript, in the control panel. Setting a proxy only in Guzzle’s config will not affect Ajax requests!
# Custom Settings
Settings defined in a config/custom.php
file don’t map to or affect any built-in Craft features, but can useful to centralize data, flags, or secrets that otherwise don’t have a place to live.
return [
'serviceBaseUrl' => 'https://api.service.com/v1',
'servicePublishableKey' => App::env('SERVICE_PUBLISHABLE_KEY'),
'servicePrivateKey' => App::env('SERVICE_PRIVATE_KEY'),
];
Custom config follows the same multi-environment structure as other files, so you can use the resolved values in a predictable way in any context:
{% set publishableKey = craft.app.config.custom.servicePublishableKey %}
{% js "https://cdn.service.com/client.js?key=#{publishableKey}" %}
If these settings need to be changed frequently, edited by a control panel user, or don’t depend on the environment, they may be a better fit for a Global Set.
# HTML Purifier
JSON files containing valid HTML Purifier configuration (opens new window) can be added to config/htmlpurifier/
.
When creating a Redactor (opens new window) or CKEditor (opens new window) field, you can select one of your predefined purifier configs—or provide a one-off config object. The purify
filter also accepts a reference to an existing config file or a complete config object.
A simple config that scrubs everything but paragraph and anchor tags would look like this:
{
"HTML.AllowedElements": "p, a",
}
For security, any keys not set will use their defaults (opens new window).
Note that HTML Purifier expresses many options with dot notation, like HTML.AllowedElements
. These are the literal keys, not an indication that keys should be nested!
# Bootstrap Config
Some customization is handled via special variables (set as PHP constants or environment vars) that Craft will take into account as it boots up. Depending on your installation, you may keep these in web/index.php
and the craft
CLI entry points, or consolidate common values into a single required
file, as the starter project (opens new window) does in bootstrap.php
—they’ll get picked up as long as they’re set prior to calling $app->run()
.
By virtue of accessing these via craft\helpers\App::env() (opens new window), Craft also honors values defined by your environment under the same names or keys. The majority of these settings are tied specifically to the structure of your project directory, though, and generally do not need to change between environments.
Constants you set directly in web/index.php
will only be defined for web requests, while any you set in the craft
executable will only be defined for console requests.
# CRAFT_BASE_PATH
The path to the base directory that Craft will look for config/, templates/, and other directories within by default. (It is assumed to be the parent of the vendor/
folder by default.)
// Tell Craft to look for config/, templates/, etc., two levels up from here
define('CRAFT_BASE_PATH', dirname(__DIR__, 2));
# CRAFT_COMPOSER_PATH
The path to the composer.json file. (It is assumed to live within the base directory by default.)
define('CRAFT_COMPOSER_PATH', 'path/to/composer.json');
# CRAFT_CONFIG_PATH
The path to the config/ folder. (It is assumed to live within the base directory by default.)
# CRAFT_CONTENT_MIGRATIONS_PATH
The path to the migrations/ folder used to store content migrations. (It is assumed to live within the base directory by default.)
# CRAFT_CP
Dictates whether the current request should be treated as a control panel request.
// Tell Craft that this is a control panel request
define('CRAFT_CP', true);
If this isn’t defined, Craft will treat the request as a control panel request if either of these are true:
- The baseCpUrl setting is set, and the request URL begins with it (plus the cpTrigger setting, if set).
- The baseCpUrl setting is not set, and the request URI begins with the cpTrigger setting.
# CRAFT_DOTENV_PATH
Path to your project’s .env
file, including the filename. Defaults to .env
, within CRAFT_BASE_PATH.
# CRAFT_EDITION
4.10.0+
Craft’s active edition is typically set via project config, but you can override it for testing with a valid edition (one of ).
It is possible to enable Craft editions that are not allowed by your current license. This means that you may see warnings in the control panel on public domains.
# CRAFT_ENVIRONMENT
The environment name that multi-environment configs can reference when defining their environment-specific config arrays.
Prior to Craft 4, craftcms/craft
starter projects allowed this fall back to the default production
value, for security. Now, the starter kit comes with three .env
examples, each of which explicitly sets a CRAFT_ENVIRONMENT
.
# CRAFT_EPHEMERAL
When set to true
, Craft will skip file system permission checks and operations that are not available in an environment with ephemeral or read-only storage.
# CRAFT_LICENSE_KEY
Your Craft license key, if for some reason that must be defined by PHP rather than a license key file. (Don’t set this until you have a valid license key.)
// Tell Craft to get its license key from a `LICENSE_KEY` environment variable
define('CRAFT_LICENSE_KEY', craft\helpers\App::env('LICENSE_KEY'));
# CRAFT_LICENSE_KEY_PATH
The path that Craft should store its license key file, including its filename. (It will be stored as license.key
within your config/ folder by default.)
# CRAFT_LOG_ALLOW_LINE_BREAKS
Adjusts the default log target config to allow or disallow multi-line log statements.
# CRAFT_LOG_PHP_ERRORS
Can be set to false
to prevent Craft from setting PHP’s log_errors (opens new window) and error_log (opens new window) settings, leaving it up to whatever’s set in php.ini
.
// Don’t send PHP error logs to storage/logs/phperrors.log
define('CRAFT_LOG_PHP_ERRORS', false);
# CRAFT_REBRAND_PATH
Override the path where the control panel’s Login Page Logo and Site Icon are stored, when uploaded via
- Settings
- General
storage/
directory, which is typically excluded from version control. // Use a top-level `rebrand/` directory for the site logo + icon:
define('CRAFT_REBRAND_PATH', '@root/rebrand');
Unlike other *_PATH
settings, CRAFT_REBRAND_PATH
’s value can include an alias or other environment variable because it is only resolved after the application is fully initialized.
# CRAFT_SECRETS_PATH
The path to a secrets file, whose values are not loaded into the environment.
// Check the `secrets.php` file next to this script for sensitive values:
define('CRAFT_SITE', dirname(__DIR__) . 'secrets.php');
# CRAFT_SITE
The Site handle or ID that Craft should be serving from this index.php
file. (Only set this if you have a good reason to. Craft will automatically serve the correct site by inspecting the requested URL, unless this is set.)
// Show the German site
define('CRAFT_SITE', 'de');
# CRAFT_STORAGE_PATH
The path to the storage/ folder. (It is assumed to live within the base directory by default.)
Make sure you set this to a valid folder path, otherwise it will be ignored.
# CRAFT_STREAM_LOG
When set to true
, Craft will send log output to stderr
and stdout
, instead of to log files. PHP fatal errors will be sent to stderr
.
# CRAFT_TEMPLATES_PATH
The path to the templates/ folder. (It is assumed to live within the base directory by default.)
# CRAFT_TRANSLATIONS_PATH
The path to the translations/
folder. (It is assumed to live within the base directory by default.)
# CRAFT_VENDOR_PATH
The path to the vendor/ folder. (It is assumed to live 4 directories up from the bootstrap script by default.)
# CRAFT_WEB_URL
Automatically sets the @web
alias.
# CRAFT_WEB_ROOT
Automatically sets the @webroot
alias.