Deploying a complex nodeJS application on Elastic Beanstalk is MUCH harder than I expected it to be but after slaving through it for a couple of days, I’ve decided to share some steps that should hopefully make it easier for you. My personal computer is a mac so I’m going to assume you’re using one as well and will assume you have a basic familiarity with AWS and have your account set up.

Step 1: Install Pip

Pip is the python package manager. You’ll need that in a little bit to install the AWS EB CLI tools.

sudo easy_install pip

Step 2: Create your keys in IAM

Create a Programmatic Access IAM User with full AWSElasticBeanstalkFullAccess privileges and save the Access key and secret keys in a password manager. You’ll need this when you go to set up the AWS EB CLI tool. This grants the CLI tool on your computer access to the AWS resources.

Step 3: Set up your local config

Create a file named ~/.aws/config.yml if it doesn’t already exist and add this content.

[profile <SOME_UNIQUE_NAME>eb-cli]
aws_access_key_id = <YOUR ACESSS KEY>
aws_secret_access_key = <YOUR SECRET KEY>

You don’t need to do this but by doing so you keep your environment flexible so that in the future, you can have multiple projects with different access keys on your machine.

Step 4: Get the EB CLI installed:

pip install --upgrade --user awsebcli

Once that’s done, add this to your PATH variable in your terminal ~/Library/Python/<Python version number>/bin

Step 5: Initializing your application (node.js can be replaced with your tech)

eb init --platform node.js --region us-west-2 --profile <PROFILE_NAME>
eb create <environment-name> --sample

Make sure the environment name is unique across your AWS account. So name it staging-project-name as opposed to staging or production-project-name as opposed to production. Your profile_name is what you defined in your ~/.aws/config file right after the word “profile”

To make sure other people who clone the git repository can push to Elastic Beanstalk in the future, run this.

git add -f .elasticbeanstalk/config.yml

They will need to make sure they create a profile on their local machines with exactly the same profile name though. Obviously they will use different keys though

Step 6: Set up managed deployment for auto server updates

Now you want to navigate to the Elastic Beanstalk section of your Amazon account and go to your application. As far as managed deployment is concerned, you SHOULD DO THIS. Ultimately, it makes sure you don’t have to worry about handling server updates, etc yourself. You can just worry about the application. I recommend choosing “instance replacement” and the “minor and patch” option. See docs here.

Step 7: Update your configurations

Head to the configuration section in the Elastic Beanstalk GUI in your browser and set any environment variables you have there. Update your configuration and rolling update type to immutable if the application is a critical application that has a low tolerance for downtime. Deployments will be much safer but will be slowed down big time).

While you’re in there, set your node version and add your start command for your app. Be sure to prefix your command with “node “. Putting the file file name is not enough. 

Don’t press Apply until you’re absolutely sure you got everything in correctly. Making changes costs you a lot of time with Elastic Beanstalk. You’ll have to wait minutes before you can try again as Elastic Beanstalk updates your application.

Step 8: Create and connect your RDS databases (docs)

  • Make it publically accessible though and then protect in with a security group
  • Creating it outside of the Elastic Beanstalk ecosystem prevents it from being coupled to the Elastic Beanstalk application.
  • You’ll need to add the Elastic Beanstalk Application’s security group to the RDS instance so they can communicate and then add an inbound mysql rule to that security group with the source being the group ID of that security group. This is confusing but once you get it, it will make sense. If you run into issues, test your application with the RDS being accessible from any IP and if your application starts working, you’ll know this is the issue. Be sure to get the security group figured out though. Don’t hang out in RDS public land for too long.
  • If you really have trouble here, just create an RDS instance within the Elastic Beanstalk GUI. The drawback here is that if you delete your Elastic Beanstalk application, the database goes with it.

Step 9: Create a CNAME that points to the EB URL

Obviously if you want a custom domain to serve your application, you’ll need to point a domain to the ELB load balancer. You can get the ELB URL from the Elastic Beanstalk application page in AWS.

Step 10: Set up SSL

Step 11: Setup postinstall scripts and auto migrations

If you’re not using Sequelize or any post install scripts, you can ignore this part.

Create a file named .ebextensions/00_env.config with the following contents

container_commands:
    10_db_migrate:
        command: ./node_modules/.bin/sequelize db:migrate
        leader_only: true
    11_other_script:
        command: node something.js
        leader_only: true

You’ll notice that we used a container command. This means that it runs within the context of your application. This is needed so that you have access to all of the env variables. We also specified leader_only: true to ensure that migrations are only executed on one of the instances instead of multiple.

Step 12: Deploy Your App

eb push <environment>

And when you’re ready to add another environment, just follow the process again with the new environment name starting from step 5 but ignoring the eb init command and the git add command.

Troubleshooting

To SSH to the server

  • You’ll need to add your SSH key to AWS via IAM
  • You may need to copy your private key in your .ssh folder and make sure it’s the exact name of your keypair in the AWS console.
  • You can then run eb ssh environment_name and you’ll be good to go.

Configuration changes on a broken deploy?

  • Sometimes it’s very challenging to make configuration changes on a broken deploy. You’ll make a change but because the deploy fails, it undoes your changes. If it ever gets too bad, I like to take the following approach.
  • Upload a zip of a simple application like this and then make sure that works, then update your configurations to get them to the point where you believe they will work with your actual deploy and then try to re-deploy your app.
  • If you have too many issues, you can just delete your elastic beanstalk application and try again… I know this is drastic but sometimes that will save you the most time.

Creating cronjobs (needs work)

In a nutshell, Elastic Beanstalk makes cronjobs a little harder. Instead of just running crontab -e, you instead need to create a worker application and create and endpoint in that application for each task which triggers the job. Once you do that, you can create the worker application and define your jobs. This is annoying but it results in much more scalable code so it’s a good thing. You CAN define cronjobs via ebextensions but getting them to work with your application’s environment variables gets hackish very quickly so I recommend the worker approach.

  • This is a good read to start
  • I like to name my worker file worker.js and place the application in the same codebase.
  • Then run this: eb create <environment-name> -t worker --sample to deploy my worker to AWS.
  • You’ll have to update the configuration and set the node script to worker.js and will obviously need to set any needed env vars, etc

Environment variables

  • The environment variables aren’t shell environment variables so they’re only accessible to the application and within container_commands. You won’t be able to use them in any commands you run after sshing to the instance or in regular commands.

Closing thoughts

That’s all I’ve got folks! Deploying to Elastic Beanstalk can be frustrating at times but once you get the initial gotchas out of the way, everything becomes a lot easier. Still having trouble with your elastic beanstalk deployment after reading this? My company would love to work with you to release the burden. You can reach us at labs@chiedo.com.

.   .   .

We're Hiring‼️ ?? Looking to join our team of web developers? We're passionate about innovation, family, and community. Apply today!