Imagine you have a web app in either Angular, React or another web framework and now you would like to deploy it where the public can access and use it.

One of the most convenient places to deploy a web app is an AWS S3 bucket; it’s cheap, reliable and backed by AWS. But there is one big flaw – HTTPS is cannot be enabled on S3 buckets. Meaning that would leave you to use HTTP only for your S3 bucket, a less than ideal solution.

Fortunately, we can enable HTTPS on an AWS S3 bucket by integrating it with Cloudfront. The idea is that Cloudfront is going to be the main public facing infrastructure(which may be is integrated with AWS Route 53 as well). All the calls are going to come to Cloudfront but it is then going to route them to the S3 bucket.

We are also going to secure access between the S3 bucket and Cloudfront; only someone who has a certain header token is going to be able to access our S3 bucket, which in this case is going to be our Cloudfront distribution.

In this post, we are going to explore in detail as to how to achieve exactly that.

Create S3 bucket

First we create an S3 bucket to which we are going to deploy our code.

  • Go the AWS S3 console.
  • Click ‘Create Bucket’
    • Name And Region
      • Bucket Name: As desired
      • Region: As desired
    • Configure Options
      • Leave everything as default
    • Set Permissions:
      • Uncheck the ‘Block all public access’. This will uncheck all of it’s sub-components.
      • Then, check the following checkboxes:
        • Block public access to buckets and objects granted through new access control lists (ACLs)
        • Block public access to buckets and objects granted through any access control lists (ACLs)
      • Leave the other checkboxes unchecked.
    • Click ‘Create Bucket’
    • Now we update the policy for the bucket to restrict access:
      • Go to ‘Permissions’ -> ‘Bucket Policy’ and paste the following json inside it:
    "Version": "2012-10-17",
    "Id": "Policy1548855771485",
    "Statement": [
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::Your-s3-Bucket-Name/*",
            "Condition": {
                "StringEquals": {
                    "aws:UserAgent": "YourCustomTokenString"
  • Click Save.
  • NOTE: You need to replace the resource name with your bucket name. Also, replace the value of aws:UserAgent with a long custom string of your own using. We will use this string again later.

Now we are going to enable static website hosting for this S3 bucket:

  • Go to ‘Properties’ > ‘Static Website Hosting’
  • Choose ‘Use this bucket to host a website’
  • In ‘Index Document’, put in the text ‘index.html’
  • Click Save.


Now we are going to create a Cloudfront distribution which is going to integrate with the above S3 bucket and is going to face the public:

  • Go to the CloudFront console
  • Click ‘Create Distribution’.
  • Under ‘Web’, click ‘Get Started’.
  • The following are the only fields you need to change, leave the rest as default:
    • Origin Domain Name:
      • This is the static website hosting url of your S3 bucket. To get it:
        • Open the S3 console in a separate tab.
        • Click the desired bucket
        • Click ‘Properties’
        • Click ‘Static website hosting’
        • Copy the ‘Endpoint’ URL
        • Paste the URL. REMOVE the http://prefix. This is important.
    • In the ‘Origin Custom Headers’, add a header with the following:
      • Header Name: User-Agent
      • Value: This is the same long custom string you provided in the S3 bucket’s policy. To get it:
        • In your S3 bucket, click Permissions > Bucket Policy
        • Locate the element Statement > Condition > StringEquals > aws:UserAgent element.
        • Copy and paste the value.
    • Viewer Protocol Policy: Redirect HTTP to HTTPS
    • Object Caching: Leave as default or Customize if you wish to change TTL and other values.
    • Price Class:
      • Choose as desired. More locations means more cost.
  • Click ‘Create Distribution’.
  • Once the distribution is created, click on the distribution:
    • Click the ‘Error Pages’ tab.
    • Click ‘Create Custom Error Response’.
    • Set the values as following:
      • HTTP Error Code = 404 Not Found
      • Error Caching Minimum TTL = As you desire
      • Custom Error Response = Yes
      • Response Page Path = /index.html
      • HTTP Response Code = 200 OK
    • Click ‘Create’.

Wait till Status = Deployed and State = Enabled, which will then mean that the distribution is ready. This can take a while, sometimes even up to 20 minutes.

The url where you can access this distribution under Domain Name for a distribution:

By navigating to this url, you are going to see your deployed web app.

But we haven’t deployed our code yet. Let’s do that:

Deploying code to S3 bucket

programmatic deployment prerequisites

Before deploying your app programmatically, you have to:

  • Install AWS CLI.
  • Go to AWS IAM Console and create a new policy with the following permissions:
    "Version": "2012-10-17",
    "Statement": [
            "Resource": [
            "Sid": "Stmt1464826210000",
            "Effect": "Allow",
            "Action": [

TIP: The above is a policy that requires minimal permissions required for AWS CLI’s S3 operations. It is one of AWS best practices to use least possible permissions for programmatic use.

Moving forward:

  • Create a new AWS User and attach the policy to this user.
  • Get the security credentials for this user:
    • On the left side bar click Users.
    • Select your user from the list.
    • Click the Security Credentials tab.
    • Under access keys, click Create access key.
    • After the key is created, download or store them in a safe location. This is the only time you will get the secret key.
  • Run command aws configure and provide your access keys.

Angular Deployment

If you have created your Angular app using Angular CLI, then you will build and deploy your Angular app using the following commands. Go to the root of the project and run:

npm build --prod
aws s3 sync dist/init s3://your-bucket-name

React deployment

For a React app created with create-react-app, run the following commands to build and deploy:

npm run build
npm run deploy

Again, the npm run deploy command uses AWS CLI to deploy to S3 bucket.

Manual deployment

  • Open AWS S3 console.
  • Click your bucket.
  • In the overview, there is a button called Upload
  • Click it and select your files to upload to this bucket. For a web app like Angular or React, ofcourse you need to build your project and upload the output here.


In this post, we learned how to enable HTTPS on an AWS S3 bucket using Cloudfront. We also learned how to secure the S3 bucket so that only our Cloudfront distribution can access it and not everyone. The app to be deployed to S3 itself can be built using Angular, React or any other JS framework.

We also saw how to create an AWS profile for AWS CLI to work, which enabled us to deploy Angular and React apps programmatically. We used the minimal possible permissions required to perform AWS CLI’s S3 operations as it’s a best practice to use as less permissions as required for programmatic access.