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):
provider:
# ...
environment:
APP_ENV: prod
DEFAULT_URI: 'https://example.com'The variables most Symfony applications need:
APP_ENV: set it toprod. WithAPP_ENV=prod,APP_DEBUGdefaults to0, so you do not need to setAPP_DEBUG.APP_SECRET: a random string, for example generated withphp -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.):
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 Cloud
bref secret:create APP_SECRET --env=prod
bref secret:create DATABASE_URL --env=prodThe 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:
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_URLThe 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.
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 Cloud
bref secret:create SYMFONY_DECRYPTION_SECRET "$(php -r 'echo base64_encode(require "config/secrets/prod/prod.decrypt.private.php");')" --env=prodThen reference it in 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.