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_)
'Properties'
tab'Static Website'
'Use this bucket to host a website'
and enter index.html for both Index document and Error
document (for
single page app)'Permissions'
tab'Bucket Policy'
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.
'Properties'
tab'Static Website'
'Redirect requests'
and choose 'http'
for the protocolRoute 53 and DNS
'Create Hosted Zone'
and enter your domain example.com with type
'Public Hosted Zone'
ns
values from your newly created hosted zone to nameserver settings for your domainAWS Certificate Manager (SSL Certs)
us-east-1
region is selected as Cloud Front needs this (top right of dashboard). More
info on this here https://aws.amazon.com/certificate-manager/faqs/'www'
subdomain www.example.com then click
'Next'
'DNS Validation'
then click 'Next'
'Review'
'Confirm and Request'
'Create record in route53'
'Continue'
AWS Cloud Front (CDN)
'Create Distribution'
'Web'
click 'Get Started'
'Origin Domain Name'
enter the S3 Site Endpoint you made a note of earlier. It should be in
the format bucket.name.s3-website-aws-region.amazonaws.com'Viewer Protocol Policy'
, select 'redirect http to https'
'Price class'
select 'use only US, Canada and Europe'
. Users outside these
regions will experience more latency but this is cheaper'Alternate Domain Names (CNAMEs)'
enter your apex domain (example.com) and then on a new line
enter your domain with the 'www'
subdomain (www.example.com)'SSL Certificate'
select 'Custom SSL Certificate'
and choose the Certificate we
just created in AWS Certificate Manager'Default Root Object'
enter 'index.html'
'Create Distribuion'
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
'Hosted Zones'
'Create Record Set'
and leave name blank
Set 'Alias'
to 'Yes'
Select 'Alias Target'
and select the Cloud Front deployment that we created earlier from the dropdown
Click Create
'www'
as the name this time.'New service role'
, the default name is fine'Allow AWS CodePipeline to create a service role so it can be used with this new pipeline'
is checked'Next'
'Source provider'
dropdown, select 'GitHub'
'Connect To GitHub'
and allow AWS access to your GitHub account'Repository'
dropdown, select your repo'Branch'
dropdown, select your desired branch'Change detection options'
ensure 'GitHub webhooks'
is selected'Next'
'Build provider'
dropdown, select 'AWS CodeBuild'
'Region'
dropdown, select your desired AWS region'Project name'
, click 'Create project'
. This will bring you to a popup window.
'Project Name'
enter a desired name'Environment image'
select 'Managed image'
'Operating System'
select 'Ubuntu'
. This includes the language runtimes we need
for building our Angular App'Runtimes'
select 'Standard'
'Image'
select 'aws/codebuild/standard:3.0'
. This contains NodeJS version 12
which we want.'Image version'
select 'Always use the latest image for this runtime version'
'Environment Type'
select 'Linux'
'Service role'
select 'New Service Role'
and enter an appropriate name (for
example 'codebuild-service-role-s3-angular')'Build specifications'
select 'User a buildspec file'
'Continue to CodePipeline'
'Next'
'Skip deploy stage'
as we covered this in our build pipeline. 'Create pipeline'
buildspec.yaml
file in the root of your repo. This will be used during the CodeBuild part
of our CD
pipeline to build your angular app and copy it to the root of the S3 bucket.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
'Roles'
'Attach Policy'
'S3'
into the search bar and click the checkbox beside 'AmazonS3FullAccess'
.
'CloudFront'
into the search bar and click the checkbox beside
'CloudFrontFullAccess'
.'Attach Policy'
to add the policy to this role.