home / blog December 16th 2019

How to create an AWS S3 hosted Angular App with a Custom Domain, HTTPS and Continuous Deployment

A guide on how to host an Angular app in AWS S3 with a custom domain, HTTPS and continuous deployment from a GitHub repo. (accurate as of 16th of December 2019 _common era_)

Requirements

Basic Static Site Setup

S3
  • Create a bucket with site name (example.com)
  • Go to the 'Properties' tab
  • Select 'Static Website'
  • Select 'Use this bucket to host a website' and enter index.html for both Index document and Error document (for single page app)
  • Manually add an index.html file to the bucket for testing purposes
  • Make note of the Endpoint, we will be needing this later when setting up our CDN
  • Go to the 'Permissions' tab
  • Select 'Bucket Policy'
  • Copy the following json replacing BUCKET_NAME with the name of the bucket (example.com)
  • {
      "Statement": [
        {
          "Sid": "AllowPublicRead",
          "Effect": "Allow",
          "Principal": {
            "AWS": "*"
          },
          "Action": [
            "s3:GetObject"
          ],
          "Resource": [
            "arn:aws:s3:::BUCKET_NAME/*"
          ]
        }
      ]
    }

    Note: The policy found in bucket-policy.json will cause all objects in this bucket to be publicly available by default, this is required later by our deployment script as normally objects are made private by default. If you do not do this, your site will not be accessible.

    Custom Domain and HTTPS

    Route 53 and DNS

    AWS Certificate Manager (SSL Certs)

    AWS Cloud Front (CDN)

    Note: It will take 15 to 20 minutes to create your distribution, be patient and wait before moving on to the next step.

    Note: Your first 1,000 invalidation path requests each month are free, but invalidations after this will cost $0.005 per additonal path invalidated.

    Note: You can have a max of 3,000 path invalidation requests in progress at once. A wildcard '*' request can invalidate a max of 15 paths at once so if your app contains more than 15 files, you will need to remove each path manually in your deployment script, not using the wild card path.

    Back to Route 53

    Note: This may take several minutes to propogate, I have experienced site without www subdomain working before site with www subdomain. Eventually the www subdomain will work also so be patient. Your site should now be live under https://example.com and https://www.example.com

    Continuous Delivery

    AWS Code Pipeline AWS CodeBuild Copy the following to the buildspec.yaml file. Replace @SITE_NAME with your site name (example.com). Replace @ANGULAR_APP_NAME with the name of the folder which contains your angular app after running ng build which can be found inside the dist folder for default angular apps Replace @ANGULAR_APP_ENVIRONMENT with the build environment for your angular app, prod being the default value Replace @CLOUDFRONT_DISTRIBUTION_ID with the ID of the cloudfront distrubtion you created earlier. This can be found in your Cloudfront Dashboard.
    version: 0.2
        
    env:
      variables:
        S3_BUCKET: "@SITE_NAME"
        APP_NAME: "@ANGULAR_APP_NAME"
        BUILD_ENV: "@ANGULAR_APP_ENVIRONMENT"
        CDN_DISTRIBUTION_ID: "@CLOUDFRONT_DISTRIBUTION_ID"
        
      phases:
        install:
          runtime-versions:
            # NodeJS included in the docker image
            nodejs: 12
          commands:
            # Install node dependancies.
            - npm install
      
      build:
        commands:
          # Builds Angular application.
          - node ./node_modules/@angular/cli/bin/ng build --$BUILD_ENV
    
      post_build:
        commands:
          # Clear S3 bucket.
          - aws s3 rm s3://$S3_BUCKET --recursive
          # Copy files from dist to S3
          - cd dist
          - aws s3 cp $APP_NAME s3://$S3_BUCKET --recursive
          # Begin cloudfront invalidation
          - aws cloudfront create-invalidation --distribution-id $CDN_DISTRIBUTION_ID --paths "/*"
    
    CodePipeline IAM Role Permissions

    An IAM Role will have been created for both Code Pipeline and CodeBuild. You need to give the CodeBuild role the permission to access S3 and Cloudfront