In my last post, I set up my AWS S3 ReactJS Single-page-application with an SSL Certificate using AWS Certificate Manager and AWS CloudFront. When I left off, my App was loading correctly except it was trying to talk to my non-https-enabled API; which the browser is not OK with. Below I'll describe how I got my NodeJS GraphQL API setup with SSL.
AWS - Amazon Web Services
AWS S3 - Amazon Simple Storage Service is a service offered by Amazon Web Services that provides object storage through a web service interface. This is where our static SPA is hosted.
AWS API Gateway - A service for creating, publishing, maintaining, monitoring, and securing REST and WebSocket APIs. It gives us a public domain for attaching the SSL certificate.
AWS Certificate Manager - a service that lets you easily provision, manage, and deploy public and private Secure Sockets Layer/Transport Layer Security (SSL/TLS) certificates for use with AWS services and your internal connected resources. SSL/TLS certificates are used to secure network communications
AWS CloudFront - a content delivery network offered by Amazon Web Services. It's how we create, and attach, the SSL certificate to our S3 bucket.
SPA - Single Page Application. In this case it will be a static Webpack-built ReactJS App.
Getting my EC2 instance, Node API, behind a domain
There are a bunch of different AWS Server/Service configurations to achieve this goal. They all come with pros and cons in terms of complexity, speed, scalability, flexibility, and cost. This project is a for-fun side project right now, so I don't want to set it up in a way that it could scale to a million users if it will cost me a fortune every month. Especially since it may very likely generate $0 indefinitely.
There are two ways I considered right off the bat. These are by no means the only two ways. If you know of a better, more cost-effective way, let me know in the comments.
- Use API gateway to route the API traffic to the EC2 API and the UI traffic to the S3 bucket. API Gateway will be able to use the cert I generated in the last article. This is probably the preferred way but it comes at a +$16 minimum monthly cost just to turn on the API Gateway.
- Drop the API Gateway and the Cloudfront Distribution and run all of the traffic to Nginx to an EC2 instance where my NodeJS is running. Then have Nginx be the SSL terminator and route the /api traffic to the API running on
localhost:4000and all other traffic to my S3 bucket for the front-end.
In either option, the browser would hit my site at
mydomain.com and then it would make the API calls to
I ended up going with Option 2, if only temporarily until this project is generating revenue. This meant throwing away some of the work I covered in the last article where I was using AWS CloudFront and AWS Certificate Manager to route traffic to my S3 bucket. Instead, the flow of loading the app will look like this.
This should have been pretty straightforward as there were 2 things that needed done:
- Update the DNS of my website to include:
A @ IP_OF_EC2 CNAME www @
- Update Nginx to do the proper proxying
Embarrassingly, That took way longer than it should have because I kept ending up with dirty EOL characters all over and so I had to keep piping the changes through this tool every time. Which would collapse the file down with no spaces which made re-editing it a PITA. It was driving me nuts. Even when I'd edit it in Vim directly to try and remove the characters it still found them nested into my code in a way I couldn't seem to remove directly. I ended up fixing this by copying to "fixed' file back into Pycharm and installing this plugin and then highlighting the text and choosing "Reformat Code" which did the trick. I should have done this right off the bat instead of fighting through it, but I digress.
Once I had Nginx configured correctly, and the DNS changes had propagated to point my domain to my EC2 Public IP, the site was loading again on HTTP properly. The next step is adding SSL to the mix.
Get HTTPS Setup with Certbot
Since I"m on AWS Amazon Linux 2 kernel which uses
YUM instead of
APT, I started with this tutorial and followed up through step 5 where they start getting into Apache Configuration.
Next jump to step 4 here: https://certbot.eff.org/lets-encrypt/centosrhel7-nginx.html. At that point, you've got the certbot installed and you can proceed for a generic Nginx setup.
After wrapping that up, I was able to reload my site and it immediately got kicked over to HTTPS and all was well. I was kind of surprised to see even my WebSocket connection was using
WSS:// without any issues.