You are browsing the Symfony 4 documentation, which changes significantly from Symfony 3.x. If your app doesn't use Symfony 4 yet, browse the Symfony 3.4 documentation.

How to Configure Symfony With Environment Variables

4.2 version
Maintained

How to Configure Symfony With Environment Variables

In Configuring Symfony (and Environments), you learned how to manage your application configuration. In this article you'll learn how to use environment variables (or "env vars" for short) to configure some of those options, which is a common practice to configure sensitive options such as credentials and passwords.

Referencing Env Vars in Configuration Files

First, define the value of the env var, using your shell environment or the .env file at the project root directory. For example, consider the DATABASE_URL env var defined when installing the doctrine recipe (by convention the env var names are always uppercase):

1
2
# .env
DATABASE_URL="mysql://db_user:[email protected]:3306/db_name"

Then, you can reference those env vars in any configuration option enclosing their names with env(). Their actual values will be resolved at runtime (once per request), so that dumped containers can be reconfigured dynamically even after being compiled:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            url: '%env(DATABASE_URL)%'
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- config/packages/doctrine.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:doctrine="http://symfony.com/schema/dic/doctrine"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/doctrine
            https://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">
    
        <doctrine:config>
            <doctrine:dbal
                url="%env(DATABASE_URL)%"
            />
        </doctrine:config>
    
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // config/packages/doctrine.php
    $container->loadFromExtension('doctrine', [
        'dbal' => [
            'url' => '%env(DATABASE_URL)%',
        ]
    ]);
    

You can also give the env() parameters a default value, which will be used whenever the corresponding environment variable is not found:

  • YAML
    1
    2
    3
    # config/services.yaml
    parameters:
        env(DATABASE_HOST): localhost
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    <!-- config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="env(DATABASE_HOST)">localhost</parameter>
        </parameters>
    </container>
    
  • PHP
    1
    2
    // config/services.php
    $container->setParameter('env(DATABASE_HOST)', 'localhost');
    

Configuring Environment Variables in Production

During development, you'll use the .env file to configure your environment variables. On your production server, it is recommended to configure these at the web server level. If you're using Apache or Nginx, you can use e.g. one of the following:

  • Apache
    1
    2
    3
    4
    5
    <VirtualHost *:80>
        # ...
    
        SetEnv DATABASE_URL "mysql://db_user:[email protected]:3306/db_name"
    </VirtualHost>
    
  • Nginx
    1
    fastcgi_param DATABASE_URL "mysql://db_user:[email protected]:3306/db_name";
    

Caution

Beware that dumping the contents of the $_SERVER and $_ENV variables or outputting the phpinfo() contents will display the values of the environment variables, exposing sensitive information such as the database credentials.

The values of the env vars are also exposed in the web interface of the Symfony profiler. In practice this shouldn't be a problem because the web profiler must never be enabled in production.

Environment Variable Processors

The values of environment variables are considered strings by default. However, your code may expect other data types, like integers or booleans. Symfony solves this problem with processors, which modify the contents of the given environment variables. The following example uses the integer processor to turn the value of the HTTP_PORT env var into an integer:

  • YAML
    1
    2
    3
    4
    # config/packages/framework.yaml
    framework:
        router:
            http_port: '%env(int:HTTP_PORT)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:router http-port="%env(int:HTTP_PORT)%"/>
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // config/packages/framework.php
    $container->loadFromExtension('framework', [
        'router' => [
            'http_port' => '%env(int:HTTP_PORT)%',
        ],
    ]);
    

Symfony provides the following env var processors:

env(string:FOO)

Casts FOO to a string:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(SECRET): 'some_secret'
    framework:
        secret: '%env(string:SECRET)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(SECRET)">some_secret</parameter>
        </parameters>
    
        <framework:config secret="%env(string:SECRET)%"/>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(SECRET)', 'some_secret');
    $container->loadFromExtension('framework', [
        'secret' => '%env(string:SECRET)%',
    ]);
    
env(bool:FOO)

Casts FOO to a bool:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(HTTP_METHOD_OVERRIDE): 'true'
    framework:
        http_method_override: '%env(bool:HTTP_METHOD_OVERRIDE)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(HTTP_METHOD_OVERRIDE)">true</parameter>
        </parameters>
    
        <framework:config http-methode-override="%env(bool:HTTP_METHOD_OVERRIDE)%"/>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(HTTP_METHOD_OVERRIDE)', 'true');
    $container->loadFromExtension('framework', [
        'http_method_override' => '%env(bool:HTTP_METHOD_OVERRIDE)%',
    ]);
    
env(int:FOO)
Casts FOO to an int.
env(float:FOO)
Casts FOO to a float.
env(const:FOO)

Finds the const value named in FOO:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/packages/security.yaml
    parameters:
        env(HEALTH_CHECK_METHOD): 'Symfony\Component\HttpFoundation\Request::METHOD_HEAD'
    security:
        access_control:
            - { path: '^/health-check$', methods: '%env(const:HEALTH_CHECK_METHOD)%' }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/security.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:security="http://symfony.com/schema/dic/security"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="env(HEALTH_CHECK_METHOD)">Symfony\Component\HttpFoundation\Request::METHOD_HEAD</parameter>
        </parameters>
    
        <security:config>
            <rule path="^/health-check$" methods="%env(const:HEALTH_CHECK_METHOD)%"/>
        </security:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    // config/packages/security.php
    $container->setParameter('env(HEALTH_CHECK_METHOD)', 'Symfony\Component\HttpFoundation\Request::METHOD_HEAD');
    $container->loadFromExtension('security', [
        'access_control' => [
            [
                'path' => '^/health-check$',
                'methods' => '%env(const:HEALTH_CHECK_METHOD)%',
            ],
        ],
    ]);
    
env(base64:FOO)
Decodes the content of FOO, which is a base64 encoded string.
env(json:FOO)

Decodes the content of FOO, which is a JSON encoded string. It returns either an array or null:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(TRUSTED_HOSTS): '["10.0.0.1", "10.0.0.2"]'
    framework:
        trusted_hosts: '%env(json:TRUSTED_HOSTS)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(TRUSTED_HOSTS)">["10.0.0.1", "10.0.0.2"]</parameter>
        </parameters>
    
        <framework:config trusted-hosts="%env(json:TRUSTED_HOSTS)%"/>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(TRUSTED_HOSTS)', '["10.0.0.1", "10.0.0.2"]');
    $container->loadFromExtension('framework', [
        'trusted_hosts' => '%env(json:TRUSTED_HOSTS)%',
    ]);
    
env(resolve:FOO)

Replaces the string FOO by the value of a config parameter with the same name:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    # config/packages/sentry.yaml
    parameters:
        env(HOST): '10.0.0.1'
        sentry_host: '%env(HOST)%'
        env(SENTRY_DSN): 'http://%sentry_host%/project'
    sentry:
        dsn: '%env(resolve:SENTRY_DSN)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- config/packages/sentry.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="env(HOST)">10.0.0.1</parameter>
            <parameter key="sentry_host">%env(HOST)%</parameter>
            <parameter key="env(SENTRY_DSN)">http://%sentry_host%/project</parameter>
        </parameters>
    
        <sentry:config dsn="%env(resolve:SENTRY_DSN)%"/>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    // config/packages/sentry.php
    $container->setParameter('env(HOST)', '10.0.0.1');
    $container->setParameter('sentry_host', '%env(HOST)%');
    $container->setParameter('env(SENTRY_DSN)', 'http://%sentry_host%/project');
    $container->loadFromExtension('sentry', [
        'dsn' => '%env(resolve:SENTRY_DSN)%',
    ]);
    
env(csv:FOO)

Decodes the content of FOO, which is a CSV-encoded string:

1
2
3
4
parameters:
    env(TRUSTED_HOSTS): "10.0.0.1, 10.0.0.2"
framework:
   trusted_hosts: '%env(csv:TRUSTED_HOSTS)%'
env(file:FOO)

Returns the contents of a file whose path is the value of the FOO env var:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(AUTH_FILE): '../config/auth.json'
    google:
        auth: '%env(file:AUTH_FILE)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(AUTH_FILE)">../config/auth.json</parameter>
        </parameters>
    
        <google auth="%env(file:AUTH_FILE)%"/>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(AUTH_FILE)', '../config/auth.json');
    $container->loadFromExtension('google', [
        'auth' => '%env(file:AUTH_FILE)%',
    ]);
    
env(key:FOO:BAR)

Retrieves the value associated with the key FOO from the array whose contents are stored in the BAR env var:

  • YAML
    1
    2
    3
    4
    5
    # config/services.yaml
    parameters:
        env(SECRETS_FILE): '/opt/application/.secrets.json'
        database_password: '%env(key:database_password:json:file:SECRETS_FILE)%'
        # if SECRETS_FILE contents are: {"database_password": "secret"} it returns "secret"
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(SECRETS_FILE)">/opt/application/.secrets.json</parameter>
            <parameter key="database_password">%env(key:database_password:json:file:SECRETS_FILE)%</parameter>
        </parameters>
    </container>
    
  • PHP
    1
    2
    3
    // config/services.php
    $container->setParameter('env(SECRETS_FILE)', '/opt/application/.secrets.json');
    $container->setParameter('database_password', '%env(key:database_password:json:file:SECRETS_FILE)%');
    

It is also possible to combine any number of processors:

1
2
3
4
5
6
7
8
parameters:
    env(AUTH_FILE): "%kernel.project_dir%/config/auth.json"
google:
    # 1. gets the value of the AUTH_FILE env var
    # 2. replaces the values of any config param to get the config path
    # 3. gets the content of the file stored in that path
    # 4. JSON-decodes the content of the file and returns it
    auth: '%env(json:file:resolve:AUTH_FILE)%'

Custom Environment Variable Processors

It's also possible to add your own processors for environment variables. First, create a class that implements EnvVarProcessorInterface:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;

class LowercasingEnvVarProcessor implements EnvVarProcessorInterface
{
    public function getEnv($prefix, $name, \Closure $getEnv)
    {
        $env = $getEnv($name);

        return strtolower($env);
    }

    public static function getProvidedTypes()
    {
        return [
            'lowercase' => 'string',
        ];
    }
}

To enable the new processor in the app, register it as a service and tag it with the container.env_var_processor tag. If you're using the default services.yaml configuration, this is already done for you, thanks to autoconfiguration.

Constants

The container also has support for setting PHP constants as parameters. See Constants as Parameters for more details.

Miscellaneous Configuration

You can mix whatever configuration format you like (YAML, XML and PHP) in config/packages/. Importing a PHP file gives you the flexibility to add whatever is needed in the container. For instance, you can create a drupal.php file in which you set a database URL based on Drupal's database configuration:

1
2
3
4
5
6
7
// config/packages/drupal.php

// import Drupal's configuration
include_once('/path/to/drupal/sites/default/settings.php');

// set a app.database_url parameter
$container->setParameter('app.database_url', $db_url);

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.