Upgrade CPU of EC2 instance on AWS

The purpose of the article is to show you how to increase the CPU of your instance on AWS. In this case, I will upgrade my t2.micro instance to a t2.medium instance. You may need to upgrade the CPU on your EC2 instance as the demand for internal operations increases or you see a noticeable decrease in overall performance. Be mindful of the added cost of upgrading your EC2 instance because your bill can accumulate quickly. 

You can find the breakdown of general purpose EC2 instances here https://aws.amazon.com/ec2/instance-types/

Step 1 – Stop your currently running instance

Select the EC2 instance you want to upgrade, then click Actions>Instance State>Stop

Step 2 – Change instance type

Once your EC2 instance has stopped, got to Actions>Instance Settings>Change Instance Type

Once you click on Change Instance Type you will select which instance you want to upgrade to. In this case, I will upgrade my t2.micro to a t2.medium

Step 3 – Start the instance 

Start the instance in Actions>Instance State>Start

Once the instance starts back up you will have successfully upgraded your EC2 instance! In the case that you want to downgrade your instance, you would follow the same steps and select an instance with a lower CPU.

Simple Angular CI/CD pipeline with GitLab & AWS

In this tutorial, I will show you how to set up a simple CI/CD pipeline that compiles code on GitLab and then deploys to AWS EC2 via AWS CodeDeploy. This tutorial assumes:

  1. You have a working EC2 Ubuntu instance set up with a web server such as Nginx or Apache running and configured. 
  2. You have an existing code repository hosting an Angular project on GitLab.

Technologies Used: 

  • Angular 7
  • Gitlab CI/CD
  • AWS S3
  • AWS CodeDeploy
  • AWS EC2 Ubuntu 18.04 LTS

I’ve made a start project that I will be referencing throughout this project on Github will all the files you need already built in. Check it out here!

Step 1 – Create an S3 to AWS CodeDeploy Pipeline

I really don’t like dropping links in tutorials like this, however, for the sake of not re-writing Amazon’s documentation, I will have to tell you to follow all instructions in the tutorial in the link below. Only once you finished the tutorial will you be able to continue with the rest of this tutorial. Once you’re done with Amazon’s tutorial, you will have a CD pipeline ready to go waiting for GitLab to send the code.

https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-simple-s3.html

If you have successfully completed the above tutorial, any changes pushed to your S3 bucket will be deployed immediately to your EC2 instance. Then steps below will show you how to upload your production bundle to S3 from Gitlab to complete the CI/CD pipeline.

Step 2 – Create an appspec.yml 

Welcome back! The first thing we’ll have to do is create an appspec.yml file in the src/ folder of our project. The appspec.yml will tell AWS CodeDeploy to deploy your code in a specific file directory on the server – in our case, it’s the /var/www/ directory. 

version: 0.0
os: linux
files:
  - source: ./
    destination: /var/www/

Then we have to tell angular to include this file as an asset so it stays preserved during the production build. To do this, we edit the assets block in our angular.json file to include "src/appspec.yml":

...
"tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/manifest.json",
              "src/appspec.yml"
            ],
            "styles": [
...

Step 3 – Create .gitlab-ci.yml

Gitlab offers a continuous integration service if you add a

.gitlab-ci.yml

file to the root directory fo your code repository. I’ve provided a sample .gitlab-ci.yml file as seen in example Github project. Please be sure to update the group name and repository name for your own project. If you copy this code please be sure to use your own repository name.

image: node:10

stages:
  - build
  - deploy

build:
  stage: 'build'
  script:
    - apt update
    - apt-get install -y nodejs
    - npm install -y npm@6.11.0
    - nodejs -v
    - npm -v
    - ls -la -F
    - npm ci
    - npx ng build --prod
  cache:
    paths:
      - node_modules/
  artifacts:
    when: on_success
    name: '$CI_JOB_NAME-$CI_COMMIT_REF_NAME'
    paths:
      - dist/angular-gitlab-ci-cd-example/
  only:
    - dev
    - master

deploy:
  stage: 'deploy'
  environment:
    name: production
  script:
    - apt update
    - apt install -y software-properties-common
    - apt install -y python-dev
    - apt install -y python-pip
    - pip install awscli
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region us-east-1
    - ls -la -F
    - mv dist/angular-gitlab-ci-cd-example/appspec.yml dist/
    - cd dist
    - ls -al -F
    - cd ..
    - aws deploy push --application-name angular-gitlab-ci-cd-example --s3-location $AWS_S3_LOCATION --ignore-hidden-files --source dist
  only:
    - master

If you commit to your master branch with this file in the root directory of your project, a CI pipeline will initiate with two steps outlined line-by-line below:

The Build Stage

1.Update the packages in the node:10 Docker container

- apt update

2. Install node & npm

- apt-get install -y nodejs
- npm install -y npm@6.11.0
- nodejs -v
- npm -v

3. Run npm install

- npm install

4. Build the production bundle of Angular using the local cli

- npx ng build --prod

6. Tell GitLab to cache your node_modules so that your project builds faster next time around

cache: 
    paths: 
      - node_modules/

7. This code block creates a build artifact that will be passed onto the next stage in the pipeline if all operations in the container run without error. In the case of Angular7, I’m passing the created dist/ directory to the next stage so that GitLab can send it to AWS to be deployed

  artifacts: 
    when: on_success    
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    paths: 
      - dist/angular-gitlab-ci-cd-example/

8. This keyword tells GitLab only to run this stage when a commit is pushed to either the master and dev branches. You can customize any stage to run a specific set of branched or all branches if that’s what you need. 

  only:
    - dev
    - master

The Deploy Stage

1. Update the packages on the node:10 Docker image, install the python libraries needed for AWS CLI and then install the AWS CLI.

script: 
    - apt update
    - apt install -y software-properties-common
    - apt install -y python-dev  
    - apt install -y python-pip
    - pip install awscli

2. Navigate to your CI/CD settings in GitLab and add the following variables for your $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY from the CodeDeploy IAM User you created earlier from following the AWS tutorial in Step 1. You should also include the $AWS_S3_LOCATION as a CI/CD variable as well in the following format:

s3://your-bucket-name/your-bundle-name.zip

The <key> will be by the same name as the zip created from the build stage.

3. In this step, we are configuring the AWS CLI with the IAM Credentials of a user with the correct CodePipeline policies attached.

    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region us-east-1

4. Remember from step 1 how we made sure the appspec.yml was preserved in the dist/ production bundle? Well, now we have to move it out it to the same directory level as the dist/ folder so that it sits on the same level as the dist/ folder. We have to do this to make the appspec.yml visible to AWS. If we do not do this, the AWS CLI will throw an error stating that it cannot find the appspec.yml file in the next step.

- mv dist/angular-gitlab-ci-cd-example/appspec.yml dist/
- cd dist
- cd .. 

5. Use the AWS CLI to deploy the dist/ bundle to AWS S3

 - aws deploy push --application-name angular-gitlab-ci-cd-example --s3-location $AWS_S3_LOCATION --ignore-hidden-files --source dist
only:
    - master

You’re Done!

Once you push your code to the master branch, navigate to the CI/CD pipeline and watch your code being built. Once GitLab is done building the production bundle, it will send it to AWS S3, which in turn will be deployed onto your live server moments later. I would love to hear your feedback on how I can improve this simple pipeline. 

Stuck on 92% Chunk Optimization on Angular Production Builds?

The purpose of this article is to show you how I overcame an out-of-memory issue while building the production version of my Angular web application on my Ubuntu server by adding swap space.

Please keep in mind that building the Angular production bundle using another cloud providers resources (like building Angular on an AWS EC2) can get expensive fast. In light of that I figured out a way to automatically build and deploy Angular production builds essentially for free on GitLab.

The Problem

While Angular CLI was building the production build on the server, the machine returned a process out of memory error message. Here is what the stack trace looked like on the terminal:


FATAL ERROR: Committing semi space failed. 
Allocation failed - process out of memory 
1: node::Abort() [ng build --prod --aot]

At the time of writing this post this was my technology stack:

• Ubuntu 16.04.5 LTS (xenial)
• Node 8.12.0
• Angular CLI 6.1.3
• Angular 6.1.2

The Solution

After some doing some online research I found that a solution to this problem was to add additional swap space on my server. In this post, I will show you how I added swap space to my Ubuntu 16.04.5 LTS.

What is Swap Space?

Swap space is essentially emergency RAM that that sits on your hard drive and is utilized whenever you’re running your RAM close to max capacity. Sometimes large programs make the entire system need extra memory. Swap space can be a dedicated partition of your hard drive, a swap file, or a combination of both. The steps below will show you how to add more swap space to your machine.

Click here for the Official Ubuntu Swap Faq

Checking System Swap Information

First, we will check out our system to see if there are any existing swap configurations with the following:

$ sudo swapon --show

If the machine does not return an output then your system does not swap space available.

You can verify that there is no active swap using the free utility:

$ free -h

If you see a row of 0B‘s in the Swap row, no swap is active on the system.

Check Available Hard Drive Space

The most common way of allocating space for swap is to use a separate partition devoted to the task. However, altering the partitioning scheme is not always possible. We can just as easily create a swap file that resides on an existing partition.

Before we do this, we should check the current disk usage by typing:

$ df -h

The device under /dev in the output is our disk in this case.

For machines with less than 1 GB, it is highly recommended that the swap space should be at bare minimum equal to the amount of RAM. On top of that, it’s also recommended that swap space is at maximum, twice the amount of RAM depending on the currently available disk space. If need more swap space than twice your RAM then you should upgrade your server or add more RAM.

Create a Swap File

Let’s create a file of the swap size that we want to be called swapfile in our root directory.

My server had 512MB of RAM so for this example I will create a 1GB file with fallocate. Please adjust the file size to meet the needs of your own server.

More information on fallocate

$ sudo fallocate -l 1G /swapfile

Once the swap file is created we can verify that the correct amount of space was allocated with the following command:

$ ls -lh /swapfile

output:

$ -rw-r--r-- 1 root root 1.0G Oct 02 12:15 /swapfile

Enabling the Swap File

With the swap file available we need to tell the machine to leverage the extra space available in the swap file. First, we need to set the swap file permissions to 600 to prevent other users from being from being able to access or modify the file.

$ sudo chmod 600 /swapfile

Format the file as swap with mkswap:

$ sudo mkswap /swapfile

More information on mkswap

output:

Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=41e86209-3802-424b-9a9d-d7683142dab7

After marking the file as swap space, we can enable the swap file allowing our system to start utilizing it:

sudo swapon /swapfile

We can verify that the swap space is available by typing:

$ sudo swapon --show

The terminal should return an output like the following:


NAME      TYPE  SIZE USED PRIO
/swapfile file 1024M   0B   -1

Enable the Swap File Permanently

If we reboot our server at the current moment, the machine won’t keep any of the changes we’ve made to the hard drive partition. To make the changes permanent we will have to copy our swap to the /etc/fstab.

$ sudo cp /etc/fstab /etc/fstab.bak

Last we must add the swap file details to /etc/fstab to make it available at boot up permanently.

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Final Notes


Aside from this one case, there are many other reasons that one would need swap space which is included but not limited to memory consuming programs, hibernation (suspend-to-ask), unforeseeable circumstances, or optimizing memory usage. Please let me know if I could improve this post by making anything more clear!

Dockerized Flask App with Nginx & PostgreSQL

The purpose of the article is to share my Github project dockerized-nginx-flask-postgres , a dockerized Flask application that starts 3 docker container setup. This article assumes that you have docker and docker-compose installed on your local as you will need these tools to run this project. To run my project $ git clone my repository and then run the following command in the root directory of the project:

$ docker_init.sh

When this command is run a few things will happen:

  1. docker-compose will build the 3 container setup
  2. docker-compose will spin up the cluster on one network
  3. Flask-Migrate will initialize the PostgreSQL database with basic user authentication tables

When Docker finishes initializing the application you will see the following output in of your terminal:

$ ------------------------------------ 
$ The cluster has been initialized 
$ Navigate to http://localhost:8080 
$ to see the running flask app 
$ ------------------------------------ 

Open the browser to http://localhost:8080 and if the compilation of the application was successful then you will see the message Time to get building on the web page.

What’s the Goal of this Project

The goal of this project is to build an adaptable and modular stack that can be configured to be a lean full-stack framework or API depending on your business objectives needs with little to no configuration.

Why I Chose These Technologies

  • Docker – Leveraging the modularity of Docker allowed me to structure the application in a way such that anyone who forks my repository can switch out the source code, web server, or database to whatever technologies they feel comfortable using. For example, switching out PostgreSQL for MySQL is as easy as updating the docker-compose.yml and 1 line of code in the Alembic configuration and that’s it! When technologies change you will be able to swap out any container to stay one step ahead of disruption.
  • Nginx – Nginx was specifically written to address the performance limitations of Apache web servers. It can be deployed as a standalone web server or front-end proxy for other servers. Nginx was designed to support high concurrency where each worker process can handle thousands of HTTP connections simultaneously.
  • Flask – Most of my experiences in web development have come from working with full-stack frameworks such as Laravel or CakePHP that are out of the box and heavy solutions. Full-stack frameworks are great to have many layers of abstraction for a reason, however, they abstract away a lot of what goes on under the hood. I chose Flask because I have full control of what goes on in my application and only import the libraries that are essential to the application. Flask is everything you need it to be and nothing you don’t want it to be. Building out each feature and functionality from scratch has given me a much better understanding of what happens behind the scenes of full-stack frameworks.
  • PostgreSQL – I chose PostgreSQL because it is a powerful open source RDBMS (relational database management system) and I’m most familiar with. Since Flask does not have an ORM (object-relational model) library built in I use Flask-Migrate to manage the evolution of my database.

What’s Next on My TODO List?

  • Mapping the hot reload port on the Flask Container to my Local for faster development
  • Show how to connect your PostgreSQL container to Navicat for PostgreSQL
  • Show configuration for using MySQL instead of PostgreSQL
  • Show how to connect a MySQL DB visitation tool (e.g. MySQL Workbench) to the right port on the database docker container
  • Build out restful routes to populate the basic user authentication tables

Let’s Collaborate

Check it out on Github – I would love to collaborate with anyone! Pass this project along to anyone who you know would benefit from using it or be interested in improving it with me. I will update this blog post as I improve this project.

How to connect Navicat to your remote PostgreSQL server on EC2

The purpose of this article is to show you how to connect you Navicat Database Admin Software tool to PostgreSQL server hosted on AWS EC2. Navicat is a vendor that offers a series of database management tools for PostgreSQL, Oracle, MariaDB, Microsoft SQL Server, MySQL and more. This article will assume that you already have a running EC2 Ubuntu 16.04 LTS instance with a PostgreSQL server running.

Step overview

  • Step 1 – Configure Security Group on EC2
  • Step 2 – Update PostgreSQL Configuration Files
  • Step 3 – Connect from Navicat

Step 1 – Configure Security Group on EC2

Log into your AWS account and select the AWS instance running the PostgreSQL server you would like to connect to on the EC2 dashboard. Next, you will edit the Security Group Inbound Rules.

Add an inbound rule with the following parameters:

  • Type: PostgreSQL
  • Protocol: TCP
  • Port Range: 5432 (This is the PostgreSQL port by default. If you changed the default port then use your custom port instead of the default one)
  • Source: [Write the single IP or IP range that you will be accessing your PostgreSQL database. Please be sure to restrict inbound port access to those who should not be able to access your database]

Once the inbound rules have been updated let’s proceed to update the PostgreSQL configuration files on the server.

Step 2 – Update PostgreSQL Configuration Files

First, we will ssh into the server via the command line and edit the postgresql.conf file with the following command.

$ sudo vim /etc/postgresql/9.5/main/postgresql.conf

Once in the file, we will include this line below which means the PostgreSQL server will listen for inbound communications from all IP addresses.

... listen_address='*' ... 

Next, we’ll edit the user access in the pg_hba.conf file.

$ sudo vim /etc/postgresql/9.5/main/pg_hba.conf 

Once in the file, we will include this line below which means the PostgreSQL server will allow access to only those who have the username and password to the database.

host    all    all    0.0.0.0/0    md5 

Keep in mind that these configurations may be too open to your preferences. I encourage you to update your database access to more exclusive IPs.

Step 3 – Connect from Navicat

All the hard work is done! Now the easy part. Open up the Navicat application and add a new connection. All you’ll need to do is enter the following information to make a new connection:

  • Host: [The Public IP of your EC2]
  • Port: [The port your PostgreSQL server is accessed thorugh]
  • Initial Database: [The name of the database you want to connect to on the server first]
  • User Name: [The username of the PostgreSQL user that has permissions to access the database]
  • Password: [The password of the PostgreSQL user that has permissions to access the database]

Once all of this information is filled out you should be able to connect no problem!

Final Notes

After you are connected you can begin to utilize the full potential of Navicat by generating relational diagrams, update your database, running backups, and so much more. I used to be a user of phppgadmin and I longed for the days I could seriously upgrade my database admin tool and Navicat was the answer.

Please like, share or comment if you found this article useful!

Deploy an Angular App in Production with Nginx & Ubuntu on EC2

This purpose of this tutorial is to show you how to configure Nginx to serve an Angular app on AWS EC2. This tutorial assumes the following:

  • You already have an Amazon Web Services account (if not you can make one here) and have basic knowledge of security groups
  • You already have a purchased a domain name and have associated it with a publicly accessible IP address
  • You have an existing Angular Project hosted on a code repository (Github, GitLab, BitBucket, etc.) and have some basic knowledge of Angular

Summary of technologies used

  • Ubuntu 16.04 LTS
  • Nginx 1.10.3
  • AWS EC2
  • Angular 6.1.3

Step overview

  • Step 1 – Open an EC2 instance
  • Step 2 – Install packages and dependencies
  • Step 3 – Configure Nginx
  • Step 4 – Deployment

Step 1 – Open an EC2 instance

Log into your AWS account, navigate to the EC2 Dashboard, and select “Launch Instance”. From the list of AMIs select Ubuntu Server 16.04 LTS (HVM).

While setting up the instance, you will be brought to a page where you select the instance type. Select t2.micro (free tier eligible). Once selected, click “Review and Launch” at the bottom of the page. On the next page click “Launch” on the bottom of the page as well.

Once launched it will take a few minutes for AWS to boot up your very own EC2 instance. Store your generated key pair in a safe place on your local computer. (Here’s documentation from AWS on how to handle your key pair)

Note: You may have to adjust the security group on your EC2 instance so that your website is publicly available. There’s plenty of resources and stack overflow questions solving this potential issue.


Step 2 – Install packages and dependencies

Time to ssh into your Ubuntu server with:

ssh -i ~/path-to-your-key-pair ubuntu@ec2-your-public-ip.compute-1.amazonaws.com

Once you have successfully logged into your public server it’s time to install some packages. Execute these commands from within your Ubuntu machine:

# update Ubuntu's local package index 
$ sudo apt-get update 

# install git 
$ sudo apt-get install -y git 

# install Nginx 
$ sudo apt-get install -y nginx 

# clear out the local repository of retrieved package files 
$ sudo apt-get -s clean 

Step 3 – Configure Nginx

If you are new to Nginx I highly recommend reading the following to understand what these next steps actually do.

Common Pitfalls using Nginx

Nginx Quick Start

Nginx Configuration

Navigate the sites-available directory.

$ cd /etc/nginx/sites-available

and use your preferred editor (I use vim) to create a new file. In this case we’re storing our nginx configuration as example.com.

$ sudo vim example.com

Enter the following in your new file:

server {     
    listen 80;      
    listen [::]:80;            
    root /var/www/your-angular-app-name/dist;   
    server_tokens off;   
    index index.html index.htm;     
 
    location / {         
        # First attempt to server request as file, then         
        # as directory, then fall back to displaying a 404.          
        try_files $uri $uri/ /index.html =404;      
    } 
}

***The line root /var/www/your-angular-app-name/dist will tell Nginx where the index.html file is for your compiled Angular app.

Save your new file and symlink it to the sites-enabled folder.

$ cd /etc/nginx/sites-enabled 
$ sudo ln -s ../sites-available/example.com 
$ ls -l

Remove the default file that comes with Nginx in the sites-enabled directory. This default file was placed here by Nginx when it was installed.

$ sudo rm default

For good practice run a test on your Nginx configuration to correct any configuration or syntax errors (syntax always gets the best of us).

$ sudo nginx -t

• Restart Nginx:

$ sudo nginx -s reload

Step 4 – Deployment

Before deploying an angular application we must use the Angular CLI to create the production build that will be served on our EC2. You have the option of building the production bundle right on your local or on your live server. If you are working by yourself on a project, it’s okay to build and add the generated dist folder to git source control. Otherwise you should avoid adding the compiled dist bundle to git when working with others to avoid merge conflicts from everyone’s own build.

Angular CLI documentation on deployments

Below I will show you two ways to deploy your app. Both methods below are ok to “test the waters” to build small applications to understand how to deploy an Angular app but I don’t recommend you keep deploying Angular in the ways detailed below. It is well worth your time to learn how to build an automation pipeline that takes care of this process for you. See my article building a simple CI/CD pipeline from GitLab to AWS. (You can build and deploy your Angular app virtually free!)

Path 1: Building the production bundle locally

In the case that you are building the production build on your local you will need to run:

$ ng build --prod

If there are no errors when Angular is building the production bundle then a dist directory will be generated in the root directory (/) of your project.

Check in the new dist dist folder to source control so that you can pull it into your server.

You will then have to ssh into your EC2 and clone the git repository into the /var/www/ directory.

$ cd /var/www
var/www $ git clone https://your-project-name

Note: You may need to use the $ sudo flag if your user inside the server does not have the right permissions to run these commands.

Restart Nginx:

$ sudo nginx -s reload

Navigate to your URL or Elastic IP address and your site should be live! If all you see is an Nginx 404 page then double check the directory on the root ...; line in your Nginx sites-available file is pointing to the right directory.

Path 2: Building on the server

DISCLAIMER: Depending on how large your application is this following method can run up your cloud provider bill.

In the case that you are building the production build on your server, you will then have to ssh into your EC2 and clone the git repository into the /var/www/ directory:

$ cd /var/www
var/www $ git clone https://your-project-name

Note: You may need to use the $ sudo flag if your user inside the server does not have the right permissions to run these commands.

Now it’s time to create the production build right on the server by making sure you currently are in your source code directory. First we must install some additional dependencies on the EC2 instance with the following commands:

# install node package manager 
$ sudo apt-get install -y npm 

# install curl 
$ sudo apt-get install -y curl  
  
# install node.js $ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - 
 

# update node.js 
$ sudo apt-get install -y nodejs 
 
# install the Angular CLI 
$ sudo npm install -g @angular/cli  

Next we navigate to the directory where we cloned the repository

$ cd /var/www/the-project-you-just-cloned

Once in the project directory, you will run:

$ ng build --prod

If there is an issue with the production build then your website will display the generic Nginx 404 page. To avoid this I highly recommend testing the production build process by running the $ ng build --prod command on your local first for testing.

Once the dist folder has been built we will restart Nginx. Nginx has already been configured to look at the var/www/your-project/dist from our configuration above.

Restart Nginx:

$ sudo nginx -s reload

Navigate to your URL or Elastic IP address and your site should be live! If all you see is an Nginx 404 page then double check the directory on the root ...; line in your Nginx sites-available file is pointing to the right directory.


If you have this process down pat and want more of a challenge then check out my next post on building a simple CI/CD pipeline from GitLab to AWS.

How to preserve your static assets in the production bundle

If you want your static assets (images, svgs, etc.) to show up in production you’ll have to do the following:

  1. In your angular.json make sure that your assets folder holding your static assets is included in the assets block like so:
“tsconfig”:…
“assets”: [
  “src/favicon.ico”,
  “src/assets”,
  “src/robots.txt”,
  “src/sitemap.xml”
],
“styles”:…

With this addition to angular.json, you’re telling angular where to find the assets when you reference them throughout your code in the build process.

2. Make sure that you’re referencing the correct directory path to your assets in your HTML blocks. In the configuration above, each asset in the assets folder should be accessed like the following:

<img src="/assets/images/my_cool_image.jpg" /> 

Now when you build and deploy, the assets should show up because Angular knows where to find them now.

You’re done!

If you’ve followed all these steps, you’ll be able to navigate to your site domain in any browser and see your basic angular app up and running. If not, remember it can take up to 48 hours for any DNS changes to fully propagate if you’ve just associated your Elastic IP to your domain name manager! Thanks for reading!