Jets Env SSM Parameter Store Support
AWS Systems Manager Parameter Store is supported. Jets dotenv files support referencing SSM Parameter Store values. This behavior only applies to Jets config/jets/env
files.
Autoload Convention Path
Jets will autoload SSM parameters under the path of /PROJECT/ENV/
. This means SSM parameters like
/demo/dev/DATABASE_URL
/demo/dev/SECRET_KEY_BASE
All you have to do is create them in AWS SSM parameter store, and they are automatically loaded. So the config/jets/env/.env
is entirely optional. This behavior can be configured with:
config/jets/project.rb
Jets.project.configure do
config.dotenv.ssm.autoload = true # default: true
end
This spares you from updating your config/jets/env
files with newly added SSM parameters. Here’s a useful CLI command to see what values are in SSM.
❯ aws ssm get-parameters-by-path --path "/demo/dev/" | jq -r '.Parameters[].Name' | sort
/demo/dev/DATABASE_URL
/demo/dev/SECRET_KEY_BASE
For those who prefer more control over the SSM env variables, you can turn off the behavior and use explicit jets/config/env
files. If you using both, the explicit values always win.
Note: Jets uses the optimized get_parameters_by_path API call. It efficiently retrieves multiple parameters that share a path hierarchy. This minimizes API calls compared to fetching parameters individually and avoids rate limit issues. The implementation does not use the recursive option by design, so the parameters should be within the same hierarchy level.
Explicit SSM Usage in Env Files
Storing secrets as SSM Parameters and referencing them your .env
files allows you to commit your .env
into source control. When you reference a parameter name with it will prefix the conventional /PROJECT/ENV/
. If you reference the parameter name with a leading / then the conventional prefix is not added. For example:
RELATIVE_DATABASE_URL=SSM:database-url # references /PROJECT/ENV/database-url
ABSOLUTE_DATABASE_URL=SSM:/path/to/database-url # references /path/to/database-url
The SSM parameters are fetched and interpolated into your environment at build time. After changing your SSM parameters, make sure to re-deploy your app to ensure they are picked up correctly.
Config
To customize the conventional behavior, you can use.
config/jets/project.rb
Jets.project.configure do
config.dotenv.ssm.one_dev = true
config.dotenv.ssm.convention_resolver = ->(ssm_leaf_name) do
"/#{Jets.project.name}/#{ssm_env}/#{ssm_leaf_name}"
end
end
Tip: Use jets dotenv:list
to quickly test changes.
SSM Helper: ssm_env
The ssm_env
helper resolves to an env value that is smarter than Jets.env
.
For JETS_ENV=dev
and JETS_ENV=prod
, ssm_env returns the corresponding JETS_ENV
. For other values, ssm_env returns dev.
This is because users often want additional dev-like environments but do not want to have to recreate all the SSM secrets for each environment. This allows the SSM params to be DRY. Here are some examples to explain:
JETS_ENV=dev # ssm_env => dev
JETS_ENV=prod # ssm_env => prod
JETS_ENV=qa # ssm_env => dev # config.dotenv.ssm.one_dev = true
This behavior can be changed with config.dotenv.ssm.one_dev = false
. In that case, JETS_ENV is passed through.
JETS_ENV=dev # ssm_env => dev
JETS_ENV=prod # ssm_env => prod
JETS_ENV=qa # ssm_env => qa # config.dotenv.ssm.one_dev = false
Shared SSM Parameters Example
The ssm_env
helper is also useful for shared env values. Here’s an example:
config/jets/bootstrap.rb
Jets.bootstrap.configure do
config.codebuild.project.env.vars = {
BUNDLE_GITHUB__COM: "SSM:/#{ssm_env}/BUNDLE_GITHUB__COM",
DOCKER_PASS: "SSM:/#{ssm_env}/DOCKER_PASS",
DOCKER_USER: "SSM:/#{ssm_env}/DOCKER_USER",
# Use your own docker host
DOCKER_HOST: "SSM:/#{ssm_env}/DOCKER_HOST",
JETS_SSH_KEY: "SSM:/#{ssm_env}/JETS_SSH_KEY",
JETS_SSH_KNOWN: "SSM:/#{ssm_env}/JETS_SSH_KNOWN"
}
end
This allows you to re-use the same SSM parameters for multiple projects and makes easier to manage and rotate them.
Reference
The table below covers each setting. Each option is configured with config.OPTION
. The config.
portion is not shown for conciseness. IE: logger.level
vs config.logger.level
.
Name | Default | Description |
---|---|---|
dotenv.ssm.autoload.default_skip | see desc | Default skip values for SSM autoloading. Default: ["BASIC_AUTH_USERNAME", "BASIC_AUTH_PASSWORD", "BASIC_AUTH_CREDENTIALS"] |
dotenv.ssm.autoload.enable | true | Autoload SSM values from conventional path. IE: /demo/dev/ |
dotenv.ssm.autoload.skip | [] | Skip these values for SSM autoloading. |
dotenv.ssm.convention_resolver | nil | A proc that receives ssm_leaf_value as the argument. You can use this to customize the SSM name conventional resolver. |
dotenv.ssm.long_env | false | Useful for legacy Jets 5 behavior, where JETS_ENV was encouraged to be development or production . Jets 6 uses dev and prod . |
dotenv.ssm.envs.unique | [“dev”,”prod”] | The unique env values that should resolve to the SSM env name. So the cases when JETS_ENV is the same as SSM env name. |
dotenv.ssm.envs.fallback | [“dev”] | When JETS_ENV is not one of the ssm.envs.unique envs, then fall back and use this env. IE: JETS_ENV=sandbox resolves to dev for the SSM env name. |
dotenv.ssm.project_name | nil | Override the ssm project name. When not set, defaults to project name set by config.name in config/jets/project.rb . |