Meteor on AWS Elastic Beanstalk with SSL
Because neither Galaxy nor Modulus would let me use my AWS credits ($5,000 via WeWork Labs) with them, I decided to roll my own deployment workflow. Turns out, it’s not actually that difficult. Things you’ll need:
- An AWS account
- A MongoDB Cloud Manager account
- A Meteor project
- A couple hours of uninterrupted time
- Some patience
I should note, this is not a “budget” option. I plan on scaling what I’m building over the next few years (optimistic, I know), so I wanted a proper set up that I had 100% control over. I should also note, this is not a detailed, step-by-step retelling — more of an overview of steps.
These are the steps I took:
- Set up a new VPC in AWS with a private and public subnet.
- Have a custom domain name with access to make DNS changes (I transferred mine to Amazon’s Route 53 — takes a couple of days). You can’t use [app].elasticbeanstalk.com because of the SSL certificate.
- In the MongoDB Cloud Manager, set up a connection to the AWS account.
- Then provisioned a replica set of three m4.large servers in the VPC. When done, it looked like this:
- Made sure the security group for the MongoDB servers was configured so that no ports were accessible from the outside world. All inbound rules (SSH on 22 or Custom on 27000) should only allow connections from within the VPC.
- Set up a new Elastic Beanstalk App. Make sure to configure it so that it’s also in the VPC. I have two m3.large servers that will auto scale.
- Set up a CNAME record for the custom domain name to point to [app].elasticbeanstalk.com — don’t point the IP address!
- Get the AWS CLI tools set up.
- Bought an SSL certificate and followed the SSL instructions to get the certificate uploaded. For SSL, I set the EB port and protocol settings to the following:
If you’re all set up in AWS, you should have at least 5 EC2 servers (3 MongoDB and 2 Elastic Beanstalk app). You should be able to SSH to your EB servers from outside the VPC but *not* the MongoDB servers. If you need to access them directly, SSH to the EB server first (you can use “eb ssh” from the command line) and then to the MongoDB server. The EB servers can act as bastion hosts.
So far nothing is related to Meteor — pretty standard stuff.
Now, for the Meteor part. I’ve since automated this part with a build script of my own that wraps “meteor build,” but I’m going to explain it the ugly way so you know what’s happening:
- Create a new directory that’s a sibling to your Meteor app. If your Meteor app is at ~/workspace/app, create ~/workspace/app-build.
- Run “eb init” in that folder to make sure the .elasticbeanstalk directory is created and associated with the app your created via the web interface.
- From the root level directory of your existing Meteor app, run “meteor build ~/Downloads”
- Go to ~/Downloads and untar your build.
- Go into bundle/programs/server/npm and delete the npm-bcrypt folder (assuming you’re doing all this on a Mac).
- Copy the contents of the bundle folder into your app-build folder
- Create a package.json file at the root of your app-build folder with the following:
- Create an .ebextensions folder at the root of your app-build folder. Inside that folder, add an app.config file for your app (where app is the name of your EB app):
- At this point, you can zip up the contents of your app-build directory and deploy them to EB. You can do this by uploading the Archive.zip file directly via the web interface.
Hopefully that helps if you’re looking to go down this road. Mostly I just needed to get this out of my head. Feel free to comment, ask for help, make suggestions, etc.