Skip to Content
🎉 Bref 3.0 is released. Read more →
DocumentationSymfonyEnvironment variables and secrets

Symfony environment variables and secrets

Symfony reads its configuration from environment variables (%env(...)% in the configuration files). On AWS Lambda, define these variables in serverless.yml, and store secret values in SSM or in the Symfony secrets vault.

Environment variables

Define environment variables in the environment section of serverless.yml (read Environment variables for the details):

serverless.yml
provider: # ... environment: APP_ENV: prod DEFAULT_URI: 'https://example.com'

The variables most Symfony applications need:

  • APP_ENV: set it to prod. With APP_ENV=prod, APP_DEBUG defaults to 0, so you do not need to set APP_DEBUG.
  • APP_SECRET: a random string, for example generated with php -r 'echo bin2hex(random_bytes(32));'. It is a secret, store it as explained below.
  • DATABASE_URL: it contains the database password, so it is a secret too.
  • DEFAULT_URI: recent Symfony skeletons need it, read Deploying for production.

APP_ENV is not the deployment environment (bref deploy --env=staging or serverless deploy --stage=staging): a staging deployment usually runs with APP_ENV=prod too. To set different values per deployment environment, use stage parameters.

.env files on Lambda

How Symfony uses .env files on Lambda depends on whether the Dotenv component is disabled in the deployed application.

With Dotenv disabled

The deployment script in Deploying for production disables Dotenv by creating a .env.local.php file that returns an empty array. Symfony then ignores all .env files on Lambda: every variable the application uses must be defined in serverless.yml or stored as a secret, APP_ENV included.

With Dotenv enabled

If the .env files are deployed and there is no .env.local.php, Symfony loads .env, then .env.local, .env.prod and .env.prod.local if they are in the deployed package. Variables defined in serverless.yml take precedence over the values from .env files.

serverless.yml deploys every file that is not excluded, including git-ignored files. Exclude local overrides, they usually contain local values (database on 127.0.0.1, etc.):

serverless.yml
package: patterns: # ... - '!.env.local' - '!.env.*.local'

composer dump-env prod compiles the .env files into .env.local.php. Symfony then reads that file instead of parsing the .env files, and variables defined in serverless.yml still take precedence.

With useDotenv: true in serverless.yml, no .env* file is deployed, .env.local.php included. Add the files Symfony needs on Lambda (for example '.env.local.php') to package.patterns to deploy them.

Secrets

Do not write secret values (APP_SECRET, DATABASE_URL, API keys) in serverless.yml or in .env files. Store them either:

  • as SSM parameters, one parameter per secret,
  • or in the Symfony secrets vault : the secrets are encrypted in the repository, and only the decryption key is stored in SSM.

SSM parameters

Create one secret per variable:

bref secret:create APP_SECRET --env=prod bref secret:create DATABASE_URL --env=prod

The command asks for the value. Bref Cloud stores each secret as an SSM parameter named /<app>/<environment>/<secret-name>. Read Creating secrets for the other options.

Then reference them in serverless.yml:

serverless.yml
provider: environment: APP_ENV: prod APP_SECRET: ${ssm:/my-app/${sls:stage}/APP_SECRET} DATABASE_URL: ${ssm:/my-app/${sls:stage}/DATABASE_URL}

The values are injected when deploying. To load them when the Lambda function starts instead, use the bref-ssm: prefix, read Retrieving secrets at runtime.

Symfony secrets vault

Add secrets to the production vault with the secrets:set command:

APP_RUNTIME_ENV=prod php bin/console secrets:set DATABASE_URL

The first time, this generates the vault keys in config/secrets/prod/. Commit that directory, except the decryption key prod.decrypt.private.php (Symfony’s .gitignore already ignores it).

serverless.yml deploys git-ignored files too: exclude the decryption key from the deployed package.

serverless.yml
package: patterns: # ... - '!config/secrets/prod/prod.decrypt.private.php'

On Lambda, Symfony reads the decryption key from the SYMFONY_DECRYPTION_SECRET environment variable. Store it as a secret:

bref secret:create SYMFONY_DECRYPTION_SECRET "$(php -r 'echo base64_encode(require "config/secrets/prod/prod.decrypt.private.php");')" --env=prod

Then reference it in serverless.yml:

serverless.yml
provider: environment: APP_ENV: prod SYMFONY_DECRYPTION_SECRET: ${ssm:/my-app/${sls:stage}/SYMFONY_DECRYPTION_SECRET}

With Symfony 7.2 and later, APP_SECRET does not need to be defined when the vault is used: Symfony derives it from the decryption key.

An environment variable takes precedence over the vault secret of the same name, unless it is empty. With Dotenv enabled, remove from the deployed .env files the variables stored in the vault, for example the development DATABASE_URL, or they will be used instead of the vault values.

Last updated on