140

The Amazon Elastic Beanstalk blurb says:

Elastic Beanstalk lets you "open the hood" and retain full control ... even pass environment variables through the Elastic Beanstalk console.

http://aws.amazon.com/elasticbeanstalk/

How to pass other environment variables besides the one in the Elastic Beanstalk configuration?

philipp
  • 4,133
  • 1
  • 36
  • 35
Ben
  • 4,301
  • 6
  • 37
  • 61

7 Answers7

167

As a heads up to anyone who uses the .ebextensions/*.config way: nowadays you can add, edit and remove environment variables in the Elastic Beanstalk web interface.

The variables are under Configuration → Software Configuration:

Environment Properties

Creating the vars in .ebextensions like in Onema's answer still works.

It can even be preferable, e.g. if you will deploy to another environment later and are afraid of forgetting to manually set them, or if you are ok with committing the values to source control. I use a mix of both.

Community
  • 1
  • 1
lime
  • 6,901
  • 4
  • 39
  • 50
  • 3
    Alternatively, you can also save the configuration, and launch the new environment using the configuration. – Michael Gallego Jul 26 '13 at 12:58
  • 1
    Yep, I'd say that's the best option. I just keep forgetting it and launch new environments willy-nilly. :) – lime Jul 26 '13 at 13:08
  • Does that mean that in the command one can just use $CUSTOM_ENV to get something-something? – dingdong Jun 13 '14 at 10:04
  • 1
    @dingdong: yep, and in particular you can access them in your application. E.g. in Rails `ENV["CUSTOM_ENV"]` would return `"something-something"`. – lime Jun 13 '14 at 11:25
  • 3
    If I add new properties, or change a property value, are they immediately available, do they require anything to be restarted etc? I recently changed the size of an autoscaling group and AWS terminated nearly all 40 of our instances and spun up 45 new ones. I don't want that to happen if I add a new property to an existing environment. Any ideas? – Engineer81 Feb 25 '15 at 16:27
  • @AntTheKnee: it does not restart the **instances**. There's a short period during which you can't submit new changes, but that's it. After that the new env is available. Your **app** will likely see the changes only on the next deploy though. – lime Feb 26 '15 at 10:01
  • @AntTheKnee: don't take my word for it though. If you are unsure, you should try it out on your staging environment first. ;) – lime Feb 26 '15 at 10:02
  • @lime I tried it and most of the instances became out of service in the load balancer and the env crashed. They didn't seem keen on coming back online so I had to manually terminate them and allow EB to autoscale new servers in place. We're running a custom AMI though and the new instances spun up with old code on them, so I had to redeplot *twice* to resolve. Maybe better if we're using a vanilla EB env – Engineer81 Feb 26 '15 at 14:07
  • 5
    Beware of the recent changes. As per this [answer](http://stackoverflow.com/a/36567121/2110188), they are not passed as environment variables. They are only passed as system properties – James May 26 '16 at 23:07
  • I'm using Spring Boot and adding `server.port` with value `5000` like this worked like a charm – cahen Sep 09 '16 at 16:48
  • One should know that you have a maximum of 4096 characters for Elastic Beanstalk environments – Steven Lu Apr 12 '17 at 00:34
  • This doesn't work for Java Tomcat/Spring Boot applications using Amazon SES because SES is still looking in the environment while Elastic Beanstalk is setting Java system properties. – Chloe Aug 03 '18 at 03:29
112

Only 5 values is limiting, or you may want to have a custom environment variable name. You can do this by using the configuration files. Create a directory at the root of your project called

.ebextensions/

Then create a file called environment.config (this file can be called anything but it must have the .config extension) and add the following values

option_settings:
  - option_name: CUSTOM_ENV
    value: staging

After you deploy your application you will see this new value under Environment Details -> Edit Configuration -> Container

for more information check the documentation here: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#customize-containers-format-options

Update

To prevent committing to your repository values like API keys, secrets and so on, you can put a placeholder value.

option_settings:
  - option_name: SOME_API_KEY
    value: placeholder-value-change-me

Later you can go to the AWS admin panel (Environment Details -> Edit Configuration -> Container) and update the values there. In my experience these values do not change after subsequent deployments.

Update 2 As @Benjamin stated in his comment, since the new look and feel was rolled out July 18, 2013 it is possible to define any number of environment variables directly from the console:

Configuration > Software Configuration > Environment Properties

Onema
  • 7,331
  • 12
  • 66
  • 102
  • Just an FYI for future readers: Elastic Beanstalk configuration files (as mentioned here) are a new feature and did not exist when the question was originally asked. This is now the preferred way of doing it, rather than using the "container". – jamieb Jan 24 '13 at 17:59
  • 2
    @Onema - How do you handle adding new keys to the config file? Will pushing the updated file update all the previously set keys with placeholder values? – Tabrez May 11 '13 at 14:33
  • 1
    @Tabrez, any previously set keys will retain their values. – Anarchtica May 31 '13 at 22:57
  • 2
    Sorry @Tabrez, I didn't have a chance to look into this before. To add to Anarchtica answer I ran some test and found out that if you use a placeholder, and then update the values in the AWS Console using real keys and then you update you placeholder values in the config file and push, the keys will not be replaced with the new placeholder. I find this a bit strange, but I think it is a welcome behavior as you will be force to manage all the env values in the console. – Onema Jun 01 '13 at 00:49
  • Anarchtica, Onema - thanks! That is indeed strange but it seems like a good thing! – Tabrez Jun 03 '13 at 18:56
  • 9
    @Anarchtica, I asked about this behavior to AWS support. They said that once you update the values in the console, they will take precedence and you will not be able to modified them using config files at all. If you never alter the values in the console, any changes made in the config file will be updated. – Onema Jun 04 '13 at 20:47
  • For information, it looks like the 5 values limit is gone: I've been able to set more than 5 key-value pairs, and haven't reached any limit. – BenMorel Aug 06 '13 at 15:30
  • For those who read on, Currently I believe the limit is 9 custom variables per the interface method... – vbbartlett Jun 15 '14 at 03:25
  • 1
    Does anyone know how to use the environment variables inside your config file for container_commands? I've tried `command: "nrsysmond-config --set license_key={$NR_INSTALL_KEY}"` – colllin Sep 09 '14 at 17:51
  • should I be setting the Enviroment variables via `eb setenv` when deploying Docker to Elastic Beanstalk ? (http://serverfault.com/q/737263/218934) Thank you – equivalent8 Nov 18 '15 at 14:44
  • You can also use the `aws:elasticbeanstalk:application:environment` namespace in your `*.config` file. [here](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html?shortFooter=true#command-options-general-elasticbeanstalkapplicationenvironment) – forzagreen Sep 28 '17 at 08:53
  • I think that every time that you create a environment or make modifications in Aws EBS using config files, you must to save a configuration as well. – Francis Rodrigues Feb 17 '18 at 22:06
  • Hi anyone having idea to add more then 5 environment variable with same process – KuldeeP ChoudharY Nov 21 '18 at 11:47
29

In the 2016 Java8 Tomcat8 AMI, ElasticBeanstalk fails to set environment variables from the web configuration. They are really setting jvm -D properties instead.

-- "The following properties are passed into the application as environment variables. Learn more."

This statement is incorrect for the Java Tomcat ami. Amazon does not set these as environment variables. They are set as System properties passed on the command line to Tomcat as a -D property for jvm. The method in Java to get environment variables is not the same for getting a property. System.getenv vs System.getProperty

I ssh'd into the box and verified that the environment variable was never set. However, in the tomcat logs I can see the -D property is set.

I've changed my code to check for both locations now as a workaround.

Ed J
  • 2,466
  • 4
  • 26
  • 20
  • 1
    And for .Net, they are inserted into your web.config file rather than put into environment vars, as per http://stackoverflow.com/a/33465765/1991614 . Further confusing the issue is that they aren't inserted if that key already exists in web.confg :( – bitcoder Jun 03 '16 at 19:08
  • You are my hero! Thanks you for noticing the -D property mapping in Tomcat 8. – shadowhorst Jun 13 '16 at 13:29
  • If you're setting a Tomcat variable, I'd expect that to make it through to Tomcat somehow. That's what you're saying, right? – Matthew Brown Aug 04 '16 at 21:38
  • The Node.JS AMI also doesn't have the values in the environment. The environment properties appear to be based as key value pairs to the application – speckledcarp Dec 27 '16 at 14:36
  • 1
    For those like myself that _really_ need to set system environment variables, you can retrieve those environment properties using a built-in beanstalk script. See this answer for more info: http://serverfault.com/a/770736/292741 – BoomShadow Feb 08 '17 at 19:51
  • 1
    `Amazon Linux 2017.03 v2.5.4 with Java8` also doesn't set env. – Sanoob Sep 22 '17 at 14:04
  • So how could I set `RAILS_ENV` for my JRuby on Rails app? – HarlemSquirrel Apr 12 '18 at 16:02
  • 2
    You can't SSH into the box and see the variables. They are set only in the shell that ran your app. https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-softwaresettings.html?icmpid=docs_elasticbeanstalk_console#environments-cfg-softwaresettings-accessing `In general, however, environment properties are passed only to the application and can't be viewed by connecting an instance in your environment and running env.` Your variables aren't set in a login script like `.bashrc`. However you are correct Tomcat variables are passed as properties. (See top of linked page.) – Chloe Aug 03 '18 at 03:12
21

AWS will interpret CloudFormation template strings in your environment variables. You can use this to access information about your EB environment inside your application:

In the AWS web interface the following will be evaluated as the name of your environment (note the back ticks):

`{ "Ref" : "AWSEBEnvironmentName" }`

Or, you can use an .ebextensions/*.config and wrap the CloudFormation template in back ticks (`):

{
  "option_settings": [
    {
      "namespace": "aws:elasticbeanstalk:application:environment",
      "option_name": "ENVIRONMENT_NAME",
      "value": "`{ \"Ref\" : \"AWSEBEnvironmentName\" }`"
    }
  ]
}
George Brassey
  • 401
  • 4
  • 9
14

Alternatively, you could use the Elastic Beanstalk CLI to set environment variables.

To set an environment variable: eb setenv FOO=bar

To view the environment variables: eb printenv

trex
  • 231
  • 3
  • 3
9

Environment Details -> Edit Configuration -> Container

enter image description here

Ben
  • 4,301
  • 6
  • 37
  • 61
5

This seems to be the only way to set ENVs with dynamic values in beanstalk. I came up with a workaround that works for my multi-docker setup:

1) Add this to your Dockerfile before building + uploading to your ECS repository:

CMD eval `cat /tmp/envs/env_file$`; <base image CMD goes here>;

2) In your Dockerrun.aws.json file create a volume:

{
    "name": "env-file",
    "host": {
        "sourcePath": "/var/app/current/envs"
    }
}

3) Mount volume to your container

{
  "sourceVolume": "env-file",
  "containerPath": "/tmp/envs",
  "readOnly": true
}

4) In your .ebextensions/options.config file add a container_commands block like so:

container_commands:
  01_create_mount:
    command: "mkdir -p envs/"
  02_create_env_file:
    command: { "Fn::Join" : [ "", [ 'echo "', "export ENVIRONMENT_NAME=" , { "Ref", "RESOURCE" }, ';" > envs/env_file;' ] ] }

5) eb deploy and your ENVS should be available in your docker container

You can add more ENVs by adding more container_commands like:

  02_create_env_file_2:
    command: { "Fn::Join" : [ "", [ 'echo "', "export ENVIRONMENT_NAME_2=" , { "Ref", "RESOURCE2" }, ';" >> envs/env_file;' \] \] }

Hope this helps!

dsorensen
  • 51
  • 1
  • 2
  • Lifesaver. If you have dynamic environment variables e.g. `X: '`{"Ref": "MyCache"}`'` value is not parsed (value is only '`{"Ref": "MyCache"}`') by default when container tries to access it. With this you can have dynamic variables like that. – Petter Kjelkenes Jan 05 '17 at 14:08