Host angular app in AWS S3 and CloudFront using Terraform (complete setup)
Tags: aws, terraform, angular, devops
Published: 2023-08-19 19:51:10

In this guide, I'll walk you through the steps to host your Angular app on AWS S3 and then optimize its delivery using CloudFront. Let's dive in!

**What We're Going to Build**
Before diving into the technicalities, let's set the stage by understanding what we aim to achieve by the end of this guide


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z556enzhrzzpwnk8zspc.png)

1. Angular Application: We'll start with a basic Angular application. If you already have one, great! If not, don't worry. We'll briefly touch upon how to set up a simple Angular app using the Angular CLI. This will serve as our demo project to be hosted on AWS.

2. AWS S3 Bucket: We'll create an S3 bucket, which is essentially a storage space in AWS where we'll upload our Angular app's build files. This bucket will act as our web server, serving the static files of our application.

3. AWS CloudFront Distribution: To ensure our Angular app is delivered quickly and securely to users worldwide, we'll set up a CloudFront distribution. This will pull the static files from our S3 bucket and distribute them across a network of data centers (edge locations) around the globe. When a user accesses our app, they'll be served from the nearest edge location, ensuring minimal latency.

4. Custom Domain (Optional): For those who want to take it a step further, we'll also touch upon how to link a custom domain to our CloudFront distribution. This way, users can access our app using a friendly URL rather than the default AWS-generated one.

5. SSL Certificate for HTTPS: Security is paramount. We'll guide you on how to set up an SSL certificate (for free) using AWS Certificate Manager, ensuring that our Angular app is accessible via HTTPS, providing an encrypted and secure connection for our users.

By the end of this guide, you'll have a fully functional Angular application hosted on AWS, optimized for speed and security. Whether you're looking to host a personal project, a portfolio, or even a production-ready application, this setup will ensure your Angular app is accessible to users around the world with top-notch performance.

Let's get started!

---
## **Angular application**
Let's create a simple "Hello World" Angular application using the Angular CLI.

**Prerequisites:**

- Node.js and npm: Ensure you have Node.js and npm installed. If not, download and install them from Node.js official website.

- Angular CLI: If you haven't installed the Angular CLI yet, you can do so using npm:
```bash
npm install -g @angular/cli
```

**Steps to Create a Simple "Hello World" Angular App:**

- Create a New Angular Project:
Open your terminal or command prompt and run the following command to create a new Angular project named my-app:

```bash
ng new my-app
```
- Edit the App Component:
Open the my-app/src/app/app.component.html file in your favorite code editor. Replace its content with:

```html
<div style="text-align:center; margin-top: 40px;">
    <h1>Hello World!</h1>
    <p>Welcome to my simple Angular app.</p>
</div>
```
- Serve the Application:
```bash
ng serve -o
```
Once compiled successfully, you can open your browser and navigate to http://localhost:4200/. You should see the "Hello World!" message displayed.
And that's it! You've successfully created a simple "Hello World" Angular application using the Angular CLI. This app can now be built for production and hosted on platforms like AWS, as discussed earlier.

## **Infrastructure**

Alright! Let's set up the infrastructure for hosting our Angular app on AWS using Terraform. We'll create an S3 bucket for storing our app's static files and a CloudFront distribution for content delivery.

**Prerequisites**:
- Terraform Installed: Ensure you have Terraform installed. If not, download and install it from Terraform's official website.

- AWS CLI Configured: Ensure you have the AWS CLI installed and configured with the necessary access rights.

- Existing Domain name (if you don't have any then follow instructions https://aws.amazon.com/getting-started/hands-on/get-a-domain/)

**Steps to Create Infrastructure using Terraform**

You can find all IaC in [my repo ](https://github.com/nbekenov/angular-app-in-s3/tree/main/infra)
Update variables with your domain name and bucket name. Update backend configuration (backend.tf file)
Then run:
```bash
terraform init
terraform plan
terraform apply
```

Let's break down the infrastructure components we're setting up:

1. S3 Bucket for Source Code:
We are creating an S3 bucket, which is Amazon's object storage service. This bucket will store the static files of our Angular application. Once the application is built using the Angular CLI, the output files from the dist/ directory will be uploaded to this S3 bucket. By configuring the bucket as a website, it can serve these static files as a web application.
[infra/modules/cloudfront-s3-cdn/s3_origin.tf](https://github.com/nbekenov/angular-app-in-s3/blob/main/infra/modules/cloudfront-s3-cdn/s3_origin.tf)

2. CloudFront Distribution with Geographical Restrictions:
CloudFront is AWS's content delivery network (CDN) service. We're setting up a CloudFront distribution to deliver our Angular app's content to users. The key advantage of using CloudFront is its vast network of edge locations worldwide, which caches content closer to the end-users, ensuring faster load times. For this setup, we're adding a geographical restriction to whitelist only the USA. This means that users outside the USA will not be able to access the content, ensuring that the application is only available to a specific audience.
[infra/modules/cloudfront-s3-cdn/main.tf](https://github.com/nbekenov/angular-app-in-s3/blob/main/infra/modules/cloudfront-s3-cdn/main.tf)

3. S3 Bucket for CloudFront Access Logs:
Monitoring and logging are crucial for any application. We'll set up a separate S3 bucket dedicated to storing CloudFront's access logs. These logs provide detailed records about every user request that CloudFront receives. By analyzing these logs, you can gain insights into user behavior, troubleshoot issues, and even detect potential security threats.
[infra/modules/cloudfront-s3-cdn/log_bucket.tf](https://github.com/nbekenov/angular-app-in-s3/blob/main/infra/modules/cloudfront-s3-cdn/log_bucket.tf)

4. SSL Certificate:
Security is paramount for web applications. We're integrating an SSL certificate to ensure that our Angular app is served over HTTPS. This encrypts the data between the user's browser and CloudFront, providing a secure browsing experience. We'll use AWS Certificate Manager (ACM) to provision, manage, and deploy the SSL/TLS certificate.
[infra/dns.tf](https://github.com/nbekenov/angular-app-in-s3/blob/main/infra/dns.tf)

5. Record in Route 53:
AWS Route 53 is a scalable domain name system (DNS) web service. Once our Angular app is up and running with CloudFront, we might want to link a custom domain to it, rather than using the default AWS-generated URL. We'll create a record in Route 53 that points our custom domain to the CloudFront distribution. This ensures that users can access our app using a friendly and memorable domain name.
[infra/dns.tf](https://github.com/nbekenov/angular-app-in-s3/blob/main/infra/dns.tf)

In summary, this infrastructure setup ensures that our Angular app is not only hosted efficiently but is also optimized for speed, security, and specific audience targeting. By leveraging AWS services like S3, CloudFront, ACM, and Route 53, we're building a robust and scalable hosting solution.

## **Deploy**

**Deploy to S3 using aws s3 sync:**

Once you have your Angular application built and your AWS infrastructure set up using Terraform, the next step is to deploy the built Angular app to the S3 bucket. One of the most efficient ways to do this is by using the aws s3 sync command provided by the AWS CLI.

```bash
cd my-app
ng build --prod
aws s3 sync dist/my-app/ s3://my-angular-app-bucket/
```
Replace my-angular-app-bucket with the name of the S3 bucket you created using Terraform.


**Invalidate CloudFront Cache (Optional):**

If you've made changes to your app and want them to be immediately reflected via CloudFront, you might need to invalidate the CloudFront cache. This ensures that CloudFront fetches the latest version of your app from the S3 bucket:
```
aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths "/*"

```
Replace YOUR_DISTRIBUTION_ID with the ID of your CloudFront distribution.

**Access the Application:**

Once deployed, you can access your Angular app either through the S3 bucket's website URL or, preferably, through the CloudFront distribution URL. If you've set up a custom domain with Route 53, you can use that domain to access your app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zrfmkbfxwfmocdf7y3c.png)


And that's it! Your Angular app is now live on AWS, hosted in an S3 bucket and delivered globally via CloudFront. 
Great job! 👏 

Further read [Use CodeArtifact with Angular builds](https://dev.to/aws-builders/use-aws-codeartifact-with-angular-app-builds-52kg)