A Guide to Deploying your React App with AWS S3
(HTTPS, Custom Domain, a CDN and continuous deployment)
What we will be building:
Here is a deployment of the app we will be building: https://react-s3-intro.co.uk/ (Notice the custom URL and HTTPS).
The technologies used in this guide are:
- Amazon S3 (https://aws.amazon.com/s3/) for static web hosting
- Buddy (https://buddy.works/) for continuous deployment
- Github for hosting your source code
- Amazon Route 53 (https://aws.amazon.com/route53/) for your domain registration/management
- Amazon CloudFront (https://aws.amazon.com/cloudfront/) for your CDN
- AWS Certificate Manager (https://aws.amazon.com/certificate-manager/) for providing certificates to make your app secure
- AWS Identity and Access Management (IAM) for creating an account with restricted permissions for Buddy
- A Github account (https://github.com/join)
- An AWS account (https://portal.aws.amazon.com/billing/signup#/start)
- A Buddy account (https://app.buddy.works/sign-up)
- Node installed (https://nodejs.org/en/download/)
Creating our app:
For this introduction, we will be using Create React App (https://facebook.github.io/create-react-app/). To get started, run the following commands in your terminal:
npx create-react-app introduction
If you navigate to http://localhost:3000/ you should see the following:
We won’t be developing the front-end any further in this tutorial.
Pushing the app to Github:
The code then needs to be hosted on Github where we will continually push new code as we develop features. In Github, click the shortcut
You should then see the following page:
Name your repository (I named mine ‘introduction’) and click
From here follow the on screen instructions by typing these commands into the terminal where you created your app: (Note that you need to alter the the repository in bold to use the repository that you just created):
git add .
git commit -m "first commit"
git remote add origin email@example.com:AndrewBestbier/introduction.git
git push -u origin master
You should then see all the starter code in Github:
If you don’t have SSH set up, I recommend taking a look at this article: https://help.github.com/en/enterprise/2.15/user/articles/adding-a-new-ssh-key-to-your-github-account.
First steps with AWS S3:
Now we will move on to storing your built app in AWS S3. First login to the AWS management console and navigate to the S3 service:
As you can see in my screenshot, I have a few buckets in S3 already which I have covered with a pink box.
Create bucket where you will be prompted to enter a bucket name (It has to be unique globally) before clicking
Next. I have chosen my bucket name to be ‘andrew-aws-introduction’:
Configure options tab, you don’t need to do anything so again click
Next . On the
Set permissions tab, you need to uncheck
Block all public access. As we will be hosting your built app with this bucket, we will need the public to access your code.
Next again, review your bucket configuration and click
Create bucket. You should see your new bucket:
Now click on your bucket as some further configuration is needed.
Click on the
Properties tab and then the
Static website hostingbox.
Use this bucket to host a website. Also specify that the index document should be index.html before saving:
If you attempt to navigate to provided endpoint, you will see an error saying that access is denied:
To fix this, navigate to the the
Permissions tab and click
Enter the following policy so that public users can read information from your bucket: (Remember to change the bolded text below to your own bucket name)
If you now visit your website again, you will see a different error but this is because your bucket is empty and therefore does not have an index.html file:
To remedy this, go to your terminal and build the application with:
Go to the
Overview tab of your bucket, click
Upload and drag the contents of the build folder (not the folder itself) onto the screen and click the modal’s
If you navigate to the bucket’s url, you should see your React application:
In this step we will set up continuous deployment so that each code push to your repository will automatically be deployed to your S3 bucket. To do so, we will be using Buddy https://buddy.works.
First, login to Buddy. If this is your first time using this service, you should see this introductory screen:
Create a new project by connecting to Github and selecting the repository you created earlier:
Once you have linked Buddy and Github successfully we can build a new deployment pipeline:
Call your pipeline whatever you wish and trigger the pipeline
A few actions then need to be defined. The first is building your application from the source code to be ready for deployment. Click
add the first action and search for ‘Node.js’. Ensure that the following commands are run:
yarn // Installing dependencies
yarn build // Building your application
Now, on every push to your repository, your application will be built. We now need to add another action to take these built files and deploy them to your S3 bucket. Unfortunately, connecting Buddy to AWS is not as simple as it is with Github. You need to create a special account so that Buddy can programatically control some resources on your AWS account. In this example, we want Buddy to be able to access and write files to your new bucket.
Navigate to the IAM (Identity Access Management) service in AWS and click
Add user give them a username (I chose BuddyClient) and select
Permissions page click
Attach existing policies directly and search for
AmazonS3FullAccess. This policy will enable Buddy to write to your new bucket without being able to access any other AWS resource.
Next and add tags if you wish. Finally, click
You will now see an Access key ID and Secret access key. Copy these to a secure location as this is your only opportunity to view these credentials.
Now switch back to Buddy so that we can add a new action to our pipeline. Search for ‘S3’:
A modal will then appear prompting you to input the credentials we generated earlier through IAM:
Then configure the action as follows:
- Set the source to ‘Pipeline Filesystem’ as this is where your built application from the previous step now lives
- Set the ‘Source path’ to
- Set the ‘Bucket ID’ to the bucket you created earlier
Your pipeline should now look like this:
Run pipeline to check that everything is working properly:
Now test this all out by making a change locally and pushing a commit to Github. Buddy should automatically run your pipeline and deploy your app to S3.
Buying a Domain name:
At the moment your application has an ugly url which we can fix by purchasing a domain through Route 53 which is Amazon’s scalable DNS and Domain registration service.
First, navigate to Route 53 and type the domain name you wish to buy. In this case, I typed ‘react-s3-intro.co.uk’:
Fortunately this domain was available so I added it to my Shopping cart:
AWS then requires a few personal details which I have blocked out below. Agree to the terms and click
This can take a few days to register (although it took me only 10 minutes). We will now pause any further work on Route 53 and come back to it at a later stage.
HTTPs and a CDN:
Important! for this step you will need to change your region to Northern Virginia as your CDN is global and therefore needs a certificate based in Northern Virginia. This (weird) step trips many people up and is just an AWS quirk.
Click on Certificate Manager which is Amazon’s service that provisions and manages and deploys SSL/TLS certificates. On this screen click
Request a certificate:
Request a public certificate, and then
Request a certificate:
You then need to add the details of the domain name you purchased earlier. In my case, these were react-s3-intro.co.uk and www.react-s3-intro.co.uk respectively. If you wish, you can also use a wildcard.
DNS validation and
To validate your certificates automatically through AWS, click the small arrow next to each Domain. These should expand to reveal buttons saying
Create record in Route 53. Click these buttons so that AWS can configure all this for you.
Continue and wait for your certificates to be validated:
Create a CDN with CloudFront:
Next, we will create a CDN through CloudFront so that your website can be accessed quickly anywhere in the world. Open CloudFront and then click
Web as the distribution you wish to create:
For ‘Origin Domain Name’, input the url of your S3 bucket (note that you shouldn’t use the dropdown here, input it yourself):
Further down the page, input your new domain name in ‘Alternate Domain Names’ (mine is react-s3-intro.co.uk). Below that, select
Custom SSL Certificate and select your newly created certificate. If your certificate does not appear, you probably missed the step earlier where I specified that it must be create in the Northern Virginia region.
No further changes are needed so create the distribution and make yourself a coffee as it takes about 30 minutes to spin up.
When your CDN is up and running, navigate back to your hosted zone in Route 53 as we want to point our domain (react-s3-intro.co.uk/ in my case) to the CDN which, in turn, will point to your S3 bucket.
Create Record Set and a modal should appear from the right. Leave the ‘Name’ empty, set the ‘Type’ to ‘A — IPv4 address’ and set ‘Alias’ to ‘Yes’. Here the Alias Target should be the url of your newly created CloudFront distribution — this should be available in the drop down box that appears. Finally click
https://YOUR_DOMAIN (note the https) and you should see your app securely displayed:
Finally, on each code push we want the caches to be purged on your CDN network. To do this, we need to give Buddy access to CloudFront. Navigate to the User you created earlier in IAM and click
Attach existing policies directly and search for ‘CloudFrontFullAccess’:
Switch back to buddy so that we can add a final action to your pipeline. Search for ‘CloudFront’:
If Buddy does indeed have access, you should be able to select the Distribution you wish to purge:
Your final pipeline should look like this:
If you have made it this far, congratulations!
If you have have any questions feel free to ask them below or email them to me at firstname.lastname@example.org as I am happy to help you out. Also, if you spot any errors or have suggestions of how to do this better please let me know!