Deploy Frontend & Backend using S3, EC2, CloudFront and add domain from Spaceship.com


Hello readers, Deployment is a process which isn’t straight forward thing for many of us, and it wasn’t for me either. But that doesn’t mean that it’s impossible to do. With basic understanding of different steps, one can not only deploy their entire application but also become proficient in doing so. There are many ways to deploy your application, and in this article, we shall see one of the ways.
In this article we would be discussing how to deploy our React Application on S3 and our Backend Nodejs + JS on an ec2 instance and connect them with each other and also link our frontend to a domain from any domain provider (Spaceship.com) in our case). We would also be setting up redirects for our websites URL. Let’s break down the entire process in small steps.
Basic Requirements
To follow the steps below, you need to have the below things checked out:
AWS account
Domain
Frontend
Backend Code on GitHub
Frontend Setup
Let us start with setting up our frontend on s3, follow the steps below
Login to your AWS account and search for S3
From the left tab select
General Purpose Buckets
In the main section click on Create Bucket
select General Purpose as bucket type
Give some name to the bucket (exampledeploy.com)
Select ACL’s enabled and Bucket Owner preferred under Object Ownership
Uncheck
Bock all public access
and check the warning that appears belowDisable Bucket versioning and ignore the tags section
SSE S3 for encryption type and you can disable or leave enabled Bucket Key
Click create bucket
click the bucket name (exampledeploy.com) →Properties tab → scroll to Static website hosting and click edit
Select all the options as stated in the image below, you can have separate error document, but in this case we shall go with index.html only:
Click Save Changes
Now go to the Permissions tab and click edit Bucket Polic
y
In policy enter:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadForWebsiteContent", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::your-unique-bucket-name/*" } ] }
Replace
your-unique-bucket-name
with your bucket namesave changes
Now in your React+Vite application, run
npm run build
this will create a dist folder in your app root levelGo back inside your bucket and click on Upload button
Click on add files and add folder and upload the contents of the dist folder that was generated ( do not upload the dist folder itself) and click upload in right corner end of screen.
Goto Properties bucket and scroll to the very end, there you shall find a link where the frontend is now present.
Your frontend deployment is complete.
Request for ACM certificates on AWS
The ACM certificates acts as proof that you actually own the domain that you claim to own, we have our domain from spaceship.com, follow the below steps:
Goto AWS Certificate Manager and click on Request
Remember your region now should be US East - N. Virginia in top right corner before going to the next step
Select request a public certificate and click next
Add www.<yourdomain> in the fully qualified domain textfield and add another textfield name <yourdomain>
Select DNS validation in Validation method and click request button on bottom right corner.
You shall be on domain page now, where you would see 2 domains and the corresponding CNAMES and CVALUES similar to the image below, you see the status is in pending validation step
Now go to spaceship.com or the domain provider of your domain, here I shall discuss for spaceship.com but the flow would be the same for other domain providers as well.
Login to your spaceship acc and click on library and select advance DNS in spaceship.com, you would see your domain there
Click your domain and now select on Add records, choose the type as CNAME.
On the left hand side you would see a text field and .<yourdomain> attached, in that text field copy the CNAME name from the 5th step, (NOTE: trim the .<yourdomain> from the CNAME before copy pasting because spaceship and other domain providers, attach it by default) and in the right hand side copy paste the CNAME value and leave the TTL as unchanged and click Add. Repeat the same for the second CNAME value as well.
Once verified, it shall take some 5-10 min and you shall see the same image on point 5 in your certificate page but this time with status as Succes
Setting Up Cloudfront
Cloud Front is responsible for serving your website with HTTPS, follow the steps to set it up:
Open AWS Cloudfront and click on Create Distribution
Under Origin settings:
Origin domain: select your S3 bucket’s static website endpoint, e.g.,
exampledeploy.com.s3-website.ap-south-1.amazonaws.com
(NOT the normal bucket name)Origin protocol policy:
HTTP only
Viewer protocol policy: Redirect HTTP to HTTPS
Allowed HTTP method: GET, HEAD
Leave other options as it is for now and find the section “Alternate domain name”, there you need to add one of domain name you had earlier created (e.g. www.exampledeploy.com), if you are wondering what about exampledeploy.com, then we shall use this domain to redirect to www.exampledeploy in future steps, so skip adding exampledeploy.com in this step but if you don’t want redirection then you can add this domain as well but for the sake of this blog, we won’t be and would suggest you don’t as well.
The next section would be custom SSL certificate, add the ACM certificate that you had earlier created in US- east region, (it shall show you in a dropdown)
Now simply click on create Distributions and wait for 10 mins while it is created
You shall get a custom domain from cloudfront now, copy the value and go back to spaceship .com or your domain provider, and select advance domain and click create CNAME record
Now for the CNAME record name, left hand add @ and then on the right hand side in value section paste the cloudfront domain that you received and click add, (i.e. now exampledeploy.com has started pointing to the s3 bucket you have) NOTE : This step needs to be done only if you have added your root domain (e.g.: exampledeploy.com) as alternate domain on step 5, if you are following this blog strictly, you should skip this step as of now.
Now for www create a CNAME record and in the value paste the cloudfront domain that was generated. (i.e. www.exampledeploy.com starts pointing to the s3 bucket of your frontend as well)
Redirecting Websites
This step is optional at beginners’ stage, but it’s highly suggested to escape SEO penalties and getting correct details for analytics. This step also helps in bringing consistency to how your website is accessed. So basically, why we are doing this step is that when someone tries to visit exampledeploy.com they are redirected to www.exampledeploy.com and if someone visits www.exampledeploy.com then they don’t need any redirection and are served the content.
(NOTE: This step could be performed only if you skipped add your root domain in point 5 of “Setting Up CloudFront”. In case you have added your root domain as well and also performed step 9, you should not follow this section entirely and jump to setting up your backend.
So, if this section interests you, follow along:
The first step is to create a new general purpose bucket (e.g. redirectexample.com).
Disable ACL and untick Block public access
Click on Create Bucket at the end of screen
now open your bucket, go to properties and scroll to the very end and then clicl on edit Static Website Hosting
Click Enable for Static website hosting
Click Redirect requests for an object
In the host name give your domain name starting with www (e.g. www.exampledeploy.com)
choose https for Protocol
Click Save Changes
Now go back to your bucket you created now and go to properties and scroll to the end
You shall see a Bucket website endpoint, clicking it would open your www domain, (e.g. www.exampledeploy.com)
Now open your CloudFront in AWS again and click Create Distributions
Under Origin settings:
Origin domain: select your redirect S3 bucket’s static website endpoint ( bucket name : redirectexample.com, you need to add the endpoint of this bucket now)
Origin protocol policy:
HTTP only
Viewer protocol policy: Redirect HTTP to HTTPS
Allowed HTTP method: GET, HEAD
In the alternate domain you now need to add your root domain (e.g.
exampledeploy.com
, in earlier cloudfront setup, you had addedwww.exampledeploy.com
.The next section would be custom SSL certificate, add the ACM certificate that you had earlier created in US- east region, (it shall show you in a dropdown)
Now simply click on create Distributions and wait for 10 mins while it is created
You shall get a custom domain from cloudfront now, copy the value and go back to spaceship .com or your domain provider, and select advance domain and click create CNAME record
This time for the root domain, just type @ and then in values add the cloudfront link that you received.
You are done; you have successfully completed setting up your frontend linked with your domain, now typing www.exampledeploy.com or simply typing exampledeploy.com will open www.exampledeploy.com.
If you don’t have a backend for your application, then the below steps are not for your use case, see you in the Conclusion part of this blog, and if you have a backend, bear a little more with me.
Spinning Up your EC2 Instance
Now that your frontend part is complete, the next step is to spin an ec2 server for your backend and connect it with your frontend as well. Before continuing further, remember you need to whitelist your domain in backend so that we don’t face any CORS error. And after the backend is set up, you would be required to save the backend URL point in your frontend, create a build for it and push it into the s3 folder which was responsible for displaying your content.
Let’s get started, this is actually the last stage of setting up your backend so gear up:
Open EC2 in AWS and click on Launch Instance
Give a name to your server
For machines select Ubuntu
You can select any instance type, we will be selecting t2.micro in this blog
click on create new key pair if you don’t have already and a popup shall appear, click on RSA and then select .pem and click Create key pair
Security Group:
- Allow ports 22, 80, 443 from anywhere (
0.0.0.0/0
)
- Allow ports 22, 80, 443 from anywhere (
Now log in to your server, this isn’t a difficult step, and you can refer to any online video to complete this exact step. It would take around 5-10 mins to understand
Now that you have logged into your server run the below commands to update the server and download nodejs and git and pm2. Pm2 is a software for production apps that would help run our apps even when the terminal is closed.
sudo apt update sudo apt install nodejs npm git -y sudo npm install -g pm2
Don’t be surprised or overwhelmed when you see a lot of files getting downloaded, you are in the right path.
Now it’s time to clone your backend gilt repo here, I assume it’s a public repo as for now. Run the below commands:
git clone https://github.com/your-username/your-backend-repo.git cd your-backend-repo npm install
replace the link after clone with your repo URL and backend-repo with your repo name.
Now I am assuming index.js is responsible for running your backend app, and it is present in src directory, you can replace your file responsible for running your app and your path as well.
#assuming that you are not into your project directory yet cd <yourDirectoryName> #my index.js is inside the src pm2 start src/index.js pm2 save pm2 startup #if you want to see real time logs follow the below command and press C to exit it pm2 logs
Make sure your backend is bug free and listens to a port
set up your env files if you have any by following this command
#suppose you want your env in root directory #you are in the root directory as of now nano .env #This shall open an editor, now type of paste your env variables #After you are done press cntrl+ o then enter button and then cntrl+ x #you shall be moved out of the editor now
Now we shall be setting up Nginx which is an open-source web server which we shall be using as reverse proxy server between our frontend and backend. But even before that we need to make sure our backend server requests on particular route starting with api (you can make your own choice as well), so when you make a request to an endpoint in the blog application it is.
https://api.exampledeploy.com/yor_route/
For the next steps, please READ THE COMMENTS that I provide and don’t copy paste blindly
sudo apt install nginx -y #instead of api.exampledeploy you could have anything (eg. backend.exampledeploy) sudo nano /etc/nginx/sites-available/api.exampledeploy.com #remember to replace api with whatever you choose server { listen 80; server_name api.exampledeploy.com; #you can change your server name to anything but remember it should have your root domain in end e.g. exampledeploy.com #your server name is api.exampledeploy.com now, remember it as it will be used #NOTE: In the next lines you see <PORT>, you should replace it with your application port no. #e.g. my app runs on port 3000, so i say http://localhost:3000/ location / { proxy_pass http://localhost:<PORT>/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } #This is it, now Save and exit: Ctrl+O, Enter, then Ctrl+X
Now lets enable our backend site, READ THE COMMENTS carefully
#in the previous step you had decided your server name replace <your_server_name> with it sudo ln -s /etc/nginx/sites-available/<your_server_name> /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx
Point Domain to Server (DNS Setup)
Now it is time to create a A record in your dns provider (spaceship.com in my case), what this step does is that it tells the internet that if anyone on internet is visiting api.exampledeploy.com
then send them to my EC2 server. Follow the below steps now:
Go to your domain provider and create a DNS record ( for spaceship users, you need to look into advance dns section and click add record)
select record type to be A
In the name section fill it as the subdomain you decided in step 19 (e.g.
api
)Click Add and its done
Secure HTTPS using Certbot & Let’s Encrypt
Now to server HTTPS requests securely on the server we need to have a valid certificate, this certificate is provided by Let’s Encrypt
for free and certbot
is a Lets’ Encrypt took which works great with Nginx, If you skip this section, browsers will refuse to connect over HTTPS. Before running the below commands make sure your pm2 is up by checking pm2 status
Install Certbot
sudo apt install certbot python3-certbot-nginx -y
Secure your domain with HTTPS, replace the A record domain name that you had set (e.g. api.exampledeploy.com)
sudo certbot --nginx -d api.exampledeploy.com
The above step shall prompt you for your email and agreement
Choose redirect HTTP to HTTPS.
Your output should look like
Congratulations! Your certificate and chain have been saved...
Test your API endpoint (e.g.: api.exampledeploy.com) with curl or browser:
curl https://api.exampledeploy.com/api/v1/auth/get
You should get a proper API response (or 401 if unauthorized, but no network errors).
Let’s Encrypt certificates expire after 90 days so to automatically renew them:
sudo certbot renew --dry-run
Now to check your certificate you can:
sudo certbot certificates
Frontend Environment Setup
In your .env file make sure that for prod, you use the endpoint that you set in the backend (e.g.: api.exampledeploy.com). Once done
Run npm run build
Upload the contents of the /dist folder in the s3 bucket you created to serve content (NOTE: not the bucket you created for redirect)
Final Sanity Checks:
You have come a long way make sure you check all the box:
Task | Status |
Set up S3 bucket to serve content | ✅ |
Create a S3 bucket to redirect request (optional) | ✅ |
Create certificates for your domain in AWS certificate manager | ✅ |
Set up the records for your domain | ✅ |
Create CloudFront Distribution | ✅ |
EC2 created + Elastic IP | ✅ |
SSH working | ✅ |
Backend + PM2 running | ✅ |
Nginx reverse proxy configured | ✅ |
Domain DNS pointing to EC2 | ✅ |
HTTPS via Certbot | ✅ |
Frontend updated to hit correct API | ✅ |
Conclusion
There are many more ways to deploy your application, there could be easier ways like using services of render or Netlify. But this is one of the ways where you can customize a lot of things, learn a lot more about your domain, the different records. Once your application is set up it’s suggested that you search for different topics that were mentioned in the blog, I would be writing about them as well. But that’s it for today. It would be great if your leave your websites URL in the comments that you deployed following the above steps.
Subscribe to my newsletter
Read articles from Saurav Pratap Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
