<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ryuichi Miyazaki</title>
    <description>The latest articles on DEV Community by Ryuichi Miyazaki (@rmiyazaki6499).</description>
    <link>https://dev.to/rmiyazaki6499</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F339123%2Faed0b62f-ca30-45c5-ba45-be9416b9714e.jpeg</url>
      <title>DEV Community: Ryuichi Miyazaki</title>
      <link>https://dev.to/rmiyazaki6499</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rmiyazaki6499"/>
    <language>en</language>
    <item>
      <title>Deploying a Production-ready Django app on AWS</title>
      <dc:creator>Ryuichi Miyazaki</dc:creator>
      <pubDate>Wed, 26 Aug 2020 22:27:22 +0000</pubDate>
      <link>https://dev.to/rmiyazaki6499/deploying-a-production-ready-django-app-on-aws-1pk3</link>
      <guid>https://dev.to/rmiyazaki6499/deploying-a-production-ready-django-app-on-aws-1pk3</guid>
      <description>&lt;p&gt;In this tutorial, I will be going over to how to deploy a Django app from start to finish using AWS and EC2. Recently, my partner &lt;a href="https://github.com/tuvo1106" rel="noopener noreferrer"&gt;Tu Vo&lt;/a&gt; and I launched our app &lt;a href="https://hyggehomes.dev/" rel="noopener noreferrer"&gt;Hygge Homes&lt;/a&gt; (a vacation home rental app for searching and booking vacation homes based off Airbnb) and we wanted to share with other developers some of the lessons we learned along the way.&lt;/p&gt;

&lt;p&gt;Following this tutorial, you will have an application that has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS EC2 server configured to host your application&lt;/li&gt;
&lt;li&gt;SSL-certification with Certbot&lt;/li&gt;
&lt;li&gt;A custom domain name&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Continuous deployment with Github Actions/SSM Agent&lt;/p&gt;

&lt;p&gt;We have provided a dummy repo to follow along with &lt;a href="https://github.com/rmiyazaki6499/django-app.git" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but feel free to apply it to your own application as necessary.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Project Layout&lt;/li&gt;
&lt;li&gt;Previewing the Project&lt;/li&gt;
&lt;li&gt;
Previewing the Django-app project with Docker

&lt;ul&gt;
&lt;li&gt;Install Docker&lt;/li&gt;
&lt;li&gt;Cleaning up the Container and Image&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Previewing the Django-app project Locally&lt;/li&gt;

&lt;li&gt;Creating an AWS Account&lt;/li&gt;

&lt;li&gt;

Creating an AWS EC2 Instance

&lt;ul&gt;
&lt;li&gt;EC2 Console&lt;/li&gt;
&lt;li&gt;AMI&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;li&gt;Instance Details&lt;/li&gt;
&lt;li&gt;Key Pairs&lt;/li&gt;
&lt;li&gt;Elastic IP&lt;/li&gt;
&lt;li&gt;Connecting to your EC2 Instance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

EC2 Environment Setup

&lt;ul&gt;
&lt;li&gt;Firewall Setup&lt;/li&gt;
&lt;li&gt;Installing Dependencies&lt;/li&gt;
&lt;li&gt;Setting up the Project on the Remote Server&lt;/li&gt;
&lt;li&gt;Configuring Gunicorn&lt;/li&gt;
&lt;li&gt;Configuring NGINX&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up Continuous Deployment

&lt;ul&gt;
&lt;li&gt;Activate SSM Agent&lt;/li&gt;
&lt;li&gt;Create SSM Role&lt;/li&gt;
&lt;li&gt;Assign SSM Role to EC2 Instance&lt;/li&gt;
&lt;li&gt;Github Secrets&lt;/li&gt;
&lt;li&gt;Deployment Script&lt;/li&gt;
&lt;li&gt;yml File&lt;/li&gt;
&lt;li&gt;Issues with Github Actions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up your Domain

&lt;ul&gt;
&lt;li&gt;Creating Domain records&lt;/li&gt;
&lt;li&gt;Configuring our Web Server&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

HTTPS

&lt;ul&gt;
&lt;li&gt;Installing Certbot&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Closing Thoughts&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Layout
&lt;/h2&gt;

&lt;p&gt;Here is the project layout:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

django-app
|___ backend/ (Django Backend settings)
|   |___ settings.py
|___ static_files/
|___ templates/ (Django Templates)
|   |___ index.html
|___ manage.py
|___ requirements.txt



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  Previewing the Project
&lt;/h3&gt;

&lt;p&gt;Start by cloning the project with the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ git clone https://github.com/rmiyazaki6499/django-app.git


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Previewing the &lt;code&gt;django-app&lt;/code&gt; project with Docker
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Install Docker
&lt;/h3&gt;

&lt;p&gt;To make this as easy as possible, we will be using &lt;em&gt;Docker Compose&lt;/em&gt; to creat our container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you do not have Docker yet, start by downloading it if you are on a Mac or Windows:&lt;br&gt;
  &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or if you are on a Linux Distribution follow the directions here:&lt;br&gt;
  &lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;https://docs.docker.com/compose/install/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To confirm you have Docker Compose, open up your terminal and run the command below:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  $ docker-compose --version
  docker-compose version 1.26.2, build eefe0d31
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  - Go into the project directory to build and run the container with:

      ```


      $ cd mern-app/
      $ docker-compose up --build


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Navigate to &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt;, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F87993902-8d27df00-caa0-11ea-8f66-990932b37ca3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F87993902-8d27df00-caa0-11ea-8f66-990932b37ca3.png" alt="django-default"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cleaning up the Container and Image
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To stop the container from running, use &lt;code&gt;&amp;lt;Ctrl-C&amp;gt;&lt;/code&gt; twice.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To close down the container use the command:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  $ docker-compose down
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  - Then to clean up the container and image which we are no longer using use the command:

      ```


      $ docker system prune -fa


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Confirm that the container and image is no longer there with:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  $ docker system df -v
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
## Previewing the `django-app` project locally

To preview the project on your local machine, follow the directions below.

  - Create a virtual environment:

      ```


      $ cd django-app/
      $ python3 -m venv env
      $ source env/bin/activate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install dependencies for Django (make sure you have pip (&lt;a href="https://pip.pypa.io/en/stable/installing/)):" rel="noopener noreferrer"&gt;https://pip.pypa.io/en/stable/installing/)):&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  $ pip3 install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  - Migrate the database and collect the static files:

      ```


      $ python3 manage.py makemigrations
      $ python3 manage.py migrate
      $ python3 manage.py collectstatic


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Run the development server with the following command:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  $ python3 manage.py runserver
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  - Run the production server with the following command:

      ```


      $ ENV_PATH=.env-prod python3 manage.py runserver


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Navigate to http://localhost:8000 to view the site on the local server.
  It should look something like this:

  ![django-default](https://user-images.githubusercontent.com/41876764/87993902-8d27df00-caa0-11ea-8f66-990932b37ca3.png)

  ___
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Creating an AWS Account
&lt;/h2&gt;

&lt;p&gt;Why choose AWS?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It offers a lot of free services for new accounts.&lt;/li&gt;
&lt;li&gt;Very popular among startups and even enterprises.&lt;/li&gt;
&lt;li&gt;Customer service support, in our opinion, is a step above the competition.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you do not have an account, check out this step by step guide by Amazon &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before you provision a new server, it is best practice to make sure your account is as secure as possible by following the prompts on your Security Status checklist. This can be found under the IAM tab from your console's homepage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527279-47d5a180-be52-11ea-97e0-537b62a987b7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527279-47d5a180-be52-11ea-97e0-537b62a987b7.png" alt="security_status"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Creating an AWS EC2 Instance
&lt;/h2&gt;

&lt;p&gt;Amazon's EC2 or Elastic Compute Cloud is one of the core products/services AWS provides and is the main building block for many of AWS's other services. It allows users to essentially rent virtual computers on which to run their own applications. You can learn more about EC2 &lt;a href="https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start out by going into the AWS Console and going to the EC2 tab. An easy way to get there is through the Services link at the top and search for EC2 in the prompt.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We recommend setting your AWS Region to the one closest to you or your intended audience. However, please note that not all AWS Services will be available depending on the region. For our example, we will be working out of the us-east-1 as this region supports all AWS Services.&lt;/em&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;EC2 Console&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;You should see this screen (as of July 2020):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527285-5a4fdb00-be52-11ea-9de2-8ad9dabfd9f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527285-5a4fdb00-be52-11ea-9de2-8ad9dabfd9f3.png" alt="ec2_console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the &lt;strong&gt;Running Instances&lt;/strong&gt; link on the EC2 dashboard and click Launch Instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527322-c8949d80-be52-11ea-9bcb-83ab9a1c8ac6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527322-c8949d80-be52-11ea-9bcb-83ab9a1c8ac6.png" alt="ec2_running_instances"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;AMI&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;In this step, AWS will prompt you to choose an AMI. AMI's are templates to configure new instances. For this tutorial, we will be using Ubuntu 18.04 64-bit (free tier).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527338-dba76d80-be52-11ea-834b-f0576918cc40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527338-dba76d80-be52-11ea-834b-f0576918cc40.png" alt="ec2_choose_ami"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select the &lt;strong&gt;t2.micro&lt;/strong&gt; instance type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527344-eb26b680-be52-11ea-8636-3c49552b5872.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527344-eb26b680-be52-11ea-8636-3c49552b5872.png" alt="ec2_choose_instance_type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next screen, keep clicking next until you see the option to &lt;strong&gt;Configure Security Group&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;Security Groups&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Security groups are virtual firewalls for your instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;em&gt;by default, there is an implicit deny on all ports meaning if you do not add rules, all incoming/outgoing traffic is blocked. Security groups are also stateful, which means setting inbound rules for a certain port will also affect the outbound rules for that port.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Set your Security Group settings with the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F87994611-45a25280-caa2-11ea-8239-a1e409e4000a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F87994611-45a25280-caa2-11ea-8239-a1e409e4000a.png" alt="django_security_groups"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Setting Anywhere on Source for Custom TCP will display a warning flag, but you can ignore that for this tutorial. Ideally, you only want to set known IP addresses.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Port Range&lt;/th&gt;
&lt;th&gt;Description.&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Port for SSH'ing into your server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;Port for HTTP requests to your web server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;443&lt;/td&gt;
&lt;td&gt;Port for HTTPS requests to your web server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom TCP&lt;/td&gt;
&lt;td&gt;8000&lt;/td&gt;
&lt;td&gt;Port which Django will run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom TCP&lt;/td&gt;
&lt;td&gt;5432&lt;/td&gt;
&lt;td&gt;Port at which to connect to PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see with the warning near the bottom of the screen, you do not want to set your &lt;em&gt;SSH Source IP&lt;/em&gt; as anywhere. This will create a security vulnerability as anyone can try to attempt to log into your server.&lt;/p&gt;

&lt;p&gt;Therefore, be sure to set it to your own IP address and any other IP address which may need access to the instance.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;Instance Details&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Click forward to &lt;strong&gt;Review and Launch&lt;/strong&gt; to view all configurations of your Instance/AMI.&lt;br&gt;
If the configurations look correct go ahead and hit &lt;strong&gt;Launch&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;Key Pairs&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Once you launch the instance, AWS will prompt you to create a key pair. A key pair consists of a public key that AWS stores and a private key file that you store. Together they allow you to connect to your instance securely through asymmetrical encryption.&lt;/p&gt;

&lt;p&gt;If this is the first time you are creating a key pair for your project, select &lt;strong&gt;Create a new key pair&lt;/strong&gt; from the drop-down and add a name for the key pair.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Be sure to store the key pair in a secure location. It is generated only once and AWS will not have access to it if you lose it. This is your only means to log into the EC2 instance via SSH.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527366-0bef0c00-be53-11ea-9f2c-570e3daa3105.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527366-0bef0c00-be53-11ea-9f2c-570e3daa3105.png" alt="key_pair"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have downloaded the &lt;strong&gt;key pair&lt;/strong&gt; make sure to move the &lt;strong&gt;.pem&lt;/strong&gt; file to the root directory of your project on your local computer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527373-17423780-be53-11ea-91fe-fa2a108cc937.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527373-17423780-be53-11ea-91fe-fa2a108cc937.png" alt="mern-app_root_w_pem"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, check the checkbox acknowledging that you have access to the private key pair and click Launch Instances. This should take you to the Launch Status page.&lt;/p&gt;


&lt;h2&gt;
  
  
  Accessing your EC2 Instance
&lt;/h2&gt;

&lt;p&gt;Click on the Instances tab on your EC2 console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527378-21643600-be53-11ea-8323-f92d50ed00a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527378-21643600-be53-11ea-8323-f92d50ed00a8.png" alt="ec2_instance_first_initializing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The instance may take a couple of minutes to launch. Once it passes its' status checks, the instance state should show a green circle and a "running" state.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;Elastic IP&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Before you can log into your EC2 instance, it is important to first generate an Elastic IP and associate it to your EC2 instance.&lt;/p&gt;

&lt;p&gt;An Elastic IP is a dedicated IP address for your EC2 instance. Although the instance has a public IP address assigned upon creation, that IP address is dynamic and does not persist if you stop and start the instance. With an Elastic IP address, you can mask the failure of an instance by remapping the address to another instance in your account.&lt;/p&gt;

&lt;p&gt;Therefore, by using an Elastic IP, you can have a dedicated IP to which users from the internet can access your instance. This will come in handy later when you assign a custom domain name and add SSL certification to the server.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: If you are using the free tier, AWS will charge you if your Elastic IP is NOT associated with an AWS identity.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the EC2 dashboard, look under the &lt;strong&gt;Network &amp;amp; Security&lt;/strong&gt; tab and go to &lt;strong&gt;Elastic IPs&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527387-2e812500-be53-11ea-92c6-806ecc97ae2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527387-2e812500-be53-11ea-92c6-806ecc97ae2c.png" alt="elastic_ips_link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should take you here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527390-393bba00-be53-11ea-8c83-4496e091e78c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527390-393bba00-be53-11ea-8c83-4496e091e78c.png" alt="elastic_ip_addresses"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Allocate Elastic IP address&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It should take you here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527396-422c8b80-be53-11ea-83a2-8c8b49963bbf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527396-422c8b80-be53-11ea-83a2-8c8b49963bbf.png" alt="allocate_ip_address"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Allocate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527403-4f497a80-be53-11ea-8649-d00eded3a2dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527403-4f497a80-be53-11ea-8649-d00eded3a2dc.png" alt="elastic_ip_created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should create an Elastic IP. The next step is to associate that Elastic IP to the instance.&lt;/p&gt;

&lt;p&gt;With the Elastic IP checked on the left side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Actions&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Associate Elastic IP address&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Make sure your Resource type is Instance&lt;/li&gt;
&lt;li&gt;Search for your instance (if this is your first time, it should be the only one)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Associate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To check if everything is done correctly, go to the Instances tab and in the instance details, you should see the Elastic IP.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;Connecting to your EC2 Instance&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;With the instance selected in the EC2 console, click Connect near the top. You will be prompted with directions on how to connect to your EC2 instance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527414-5b353c80-be53-11ea-975f-c2f53c3e7de8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527414-5b353c80-be53-11ea-975f-c2f53c3e7de8.png" alt="connect_to_your_instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Changing the .pem file's permission to read-only ensures nobody can modify your private key.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;Connecting to your EC2 Instance&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we have our instance and have allocated an Elastic IP to it. &lt;br&gt;
It is time to connect to our server!&lt;/p&gt;

&lt;p&gt;If you have not already, go to the &lt;strong&gt;Instances&lt;/strong&gt; link in the EC2 Dashboard.&lt;/p&gt;

&lt;p&gt;With the instance highlighted, click on &lt;strong&gt;Connect&lt;/strong&gt; on the top banner of the Instaces Dashboard.&lt;/p&gt;

&lt;p&gt;It should give you a pop up with directions on how to connect to your EC2 instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527414-5b353c80-be53-11ea-975f-c2f53c3e7de8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527414-5b353c80-be53-11ea-975f-c2f53c3e7de8.png" alt="connect_to_your_instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go back to your project root directory and make sure that your &lt;strong&gt;.pem&lt;/strong&gt; file has the correct permissions.&lt;/p&gt;

&lt;p&gt;Run the command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ chmod 400 *.pem


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next run the command given to you in the example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ ssh -i "&amp;lt;KEY-PAIR&amp;gt;.pem" ubuntu@&amp;lt;YOUR-IP-ADDRESS&amp;gt;.compute-1.amazonaws.com


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The ssh should prompt you that the authenticity of host &lt;em&gt;instance&lt;/em&gt; can't be established and will show an ECDSA key fingerprint.&lt;br&gt;
It will also ask you &lt;code&gt;Are you sure you want to continue connecting (yes/no)?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; and &lt;em&gt;Enter&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This should take you into the EC2 Instance.&lt;br&gt;
If not, try the &lt;code&gt;ssh&lt;/code&gt; command again.&lt;/p&gt;

&lt;p&gt;Congratulations you are inside your EC2 Instance!&lt;/p&gt;




&lt;h2&gt;
  
  
  EC2 Environment Setup
&lt;/h2&gt;

&lt;p&gt;Once you are logged into your server, we will install all of the project dependencies:&lt;br&gt;
We will install the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django and Python3&lt;/li&gt;
&lt;li&gt;pip&lt;/li&gt;
&lt;li&gt;gunicorn&lt;/li&gt;
&lt;li&gt;NGINX&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UFW (Firewall)&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Firewall Setup&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Enable Firewall and allow OpenSSH&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo ufw enable
% sudo ufw allow OpenSSH
% sudo ufw allow 'Nginx Full'


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Check to make sure we are allowing OpenSSH&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo ufw status


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Expected output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

To                         Action      From
--                         ------      ----
Nginx Full                 ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
Nginx Full (v6)            ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Installing Dependencies
&lt;/h2&gt;

&lt;p&gt;Updating packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo apt update
% sudo apt upgrade


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Installing Python 3, PostgreSQL, NGINX and Gunicorn:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx gunicorn curl


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Setting up the Project on the Remote Server&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Recall the steps earlier we did with the dummy project on our local machine. We will repeat that on the EC2 instance.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% git clone https://github.com/rmiyazaki6499/django-app.git
% python3 -m venv env
% source env/bin/activate
% pip3 install -r requirements.txt
% python3 manage.py makemigrations
% python3 manage.py migrate
% python3 manage.py collectstatic


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note: Make sure to update your .env file so that your project has the correct Environment Varialbes necessary to run.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Configuring Gunicorn&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Create a gunicorn.socket file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo vim /etc/systemd/system/gunicorn.socket


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Configure the gunicorn.socket file with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next configure the gunicorn.service file with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo nano /etc/systemd/system/gunicorn.service


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Use the configurations below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=djangoadmin
Group=www-data
WorkingDirectory=/home/ubuntu/&amp;lt;YOUR-PROJECT&amp;gt;
ExecStart=/home/djangoadmin/pyapps/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
&amp;lt;YOUR-PROJECT&amp;gt;.wsgi:application

[Install]
WantedBy=multi-user.target


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Start and enable Gunicorn:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo systemctl start gunicorn.socket
% sudo systemctl enable gunicorn.socket


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Check the status of gunicorn with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo systemctl status gunicorn.socket


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Configuring NGINX&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Next, we need to configure NGINX to redirect web traffic.&lt;/p&gt;

&lt;p&gt;Create a new NGINX config file with the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo vim /etc/nginx/sites-available/&amp;lt;YOUR-PROJECT-NAME&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Paste in the following configurations and replace any of the ALL CAPS sections with your own project details:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

server {
listen 80;
server_name YOUR_INSTANCE_IP_ADDRESS;

location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/ubuntu/&amp;lt;YOUR-PROJECT&amp;gt;;
}

location /media/ {
root /home/ubuntu/&amp;lt;YOUR-PROJECT&amp;gt;;    
}

location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once your NGINX config is set up, make sure there are no syntax errors with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo nginx -t


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, create a soft link of your config file from sites-available to the sites-enabled directory. This step is important because NGINX will use the configuration settings located at /etc/nginx/sites-available/default by default if there is nothing in sites-enabled.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo ln -s /etc/nginx/sites-available/&amp;lt;YOUR-PROJECT-NAME&amp;gt; /etc/nginx/sites-enabled


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Restart the NGINX Web Server with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo systemctl restart nginx


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now if you go to your Elastic IP on your browser it should show the app!&lt;/p&gt;

&lt;p&gt;Back to Table of Contents&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up Continuous Deployment
&lt;/h2&gt;

&lt;p&gt;Continuous Deployment is helpful because it saves you the time of having to ssh into your EC2 instance each time you make an update on your codebase. &lt;/p&gt;

&lt;p&gt;In this project, we will be using a Github Action called &lt;a href="https://github.com/marketplace/actions/aws-ssm-send-command" rel="noopener noreferrer"&gt;AWS SSM Send-Command&lt;/a&gt; created by &lt;strong&gt;peterkimzz&lt;/strong&gt; to implement auto-deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Github Actions&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Github Actions is a service by Github that allows you to perform actions such as run scripts every time something happens to a repository. In our case, we will run a script to install the latest dependencies and restart our server every time a push is made to master.&lt;/p&gt;

&lt;p&gt;For Github Actions to work, it needs a way to communicate with the EC2 Instance and vice-versa. In order to do that, we need to assign permissions via IAM roles.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Create SSM Role&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;To create an &lt;strong&gt;IAM Role&lt;/strong&gt; with &lt;code&gt;AmazonSSMFullAccess&lt;/code&gt; permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the IAM console at &lt;a href="https://console.aws.amazon.com/iam/" rel="noopener noreferrer"&gt;https://console.aws.amazon.com/iam/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In the navigation panel, select &lt;strong&gt;Roles&lt;/strong&gt;, and then click &lt;strong&gt;Create role&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;em&gt;Select type of trusted entity&lt;/em&gt;, choose &lt;strong&gt;AWS service&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the &lt;em&gt;Choose a use case&lt;/em&gt; section, choose &lt;strong&gt;EC2&lt;/strong&gt;, and then choose &lt;strong&gt;Next: Permissions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On the Attached permissions policy page, search for the &lt;code&gt;AmazonSSMFullAccess&lt;/code&gt; policy, choose it, and then choose &lt;strong&gt;Next: Review&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Review&lt;/strong&gt; page, type a name in the Role name box, and then type a description.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose &lt;strong&gt;Create role&lt;/strong&gt;. The system returns you to the Roles page.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Assigning an SSM Role to EC2 Instance&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Once you have the &lt;strong&gt;Role&lt;/strong&gt; created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;EC2 Instance Dashboard&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Go to the &lt;strong&gt;Instances&lt;/strong&gt; link&lt;/li&gt;
&lt;li&gt;Highlight the Instance&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instance Settings&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attach/Replace IAM Role&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select the SSM Role you had created earlier&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hit &lt;strong&gt;Apply&lt;/strong&gt; to save changes&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Github Secrets&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;With our instance being able to use the SSM Agent, we will need to provide it some details so that it can access our EC2 instance.&lt;/p&gt;

&lt;p&gt;Now that the instance is able to communicate to Github via SSM Agent, you will need to provide the repo with credentials. Github Secrets act like environment variables for repositories and store sensitive data such as AWS login information. In order for the Github Actions script to work, it needs these three secrets: AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY, and INSTANCE_ID.&lt;/p&gt;

&lt;p&gt;There is an article by AWS on how to find your AWS Access Key and Secret Access Key &lt;a href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Your instance ID is shown on your instances tab under EC2.&lt;/p&gt;

&lt;p&gt;Start by going to your Github project repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then go to your &lt;strong&gt;Settings&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;On the menu on the left, look for the link for &lt;strong&gt;Secrets&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There, add the three &lt;em&gt;Secrets&lt;/em&gt; with these keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;INSTANCE_ID&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once these &lt;strong&gt;Secrets&lt;/strong&gt; are set, we are ready to move on!&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Deployment script&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Next, let's create a bash script to download dependencies and restart NGINX and PM2. Inside the EC2 instance, create a deploy.sh script in the root of the directory:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% vim deploy.sh


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Fill the contents with the bash commands we ran to build the project earlier:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

#!/bin/sh     
sudo git pull origin master
sudo pip3 install -r requirements.txt
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py collectstatic
sudo systemctl restart nginx
sudo systemctl restart gunicorn


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;YAML File&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;AWS SSM Send-Command&lt;/em&gt; requires a .yml file to execute. At the root of the project, create these two directories:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% mkdir -p .github/workflows/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create a new YAML file with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo vim .github/workflows/deploy.yml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Paste in the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

name: Deploy using AWS SSM Send-Command 

on:
    push:
        branches: [master]

jobs:
    start:
        runs-on: ubuntu-latest 

        steps:
        - uses: actions/checkout@v2

        - name: AWS SSM Send Command
        uses: peterkimzz/aws-ssm-send-command@1.0.1
        with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID  }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY  }}
        aws-region: us-east-1
        instance-ids: ${{ secrets.INSTANCE_ID  }}
        comment: Deploy the master branch
        working-directory: /home/ubuntu/&amp;lt;YOUR PROJECT DIRECTORY&amp;gt;
        command: /bin/sh ./deploy.sh


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Secrets we provided to the repo earlier comes into use in this script.&lt;/p&gt;

&lt;p&gt;There are 3 parts of the .yml file to configure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The aws-region should be the same region as where you have created your EC2 instance. (If you do not know, check the top left of your EC2 console to confirm the region you are in).&lt;/li&gt;
&lt;li&gt;working-directory should be the directory where you created the deploy.sh script.&lt;/li&gt;
&lt;li&gt;command should be the command you would like the SSM agent to run.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once this is complete, commit and push the workflow to your repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up your Domain
&lt;/h2&gt;

&lt;p&gt;So far, users can access the site using the Elastic IP. However, it can be difficult to remember and share so we will configure a custom domain name.&lt;/p&gt;

&lt;p&gt;To get started, you need to first purchase a domain. This can range from $10 to $1,000+s. Amazon has a service called Route53 you can use or you can choose other providers such as &lt;a href="https://domains.google/" rel="noopener noreferrer"&gt;Google Domains&lt;/a&gt;, &lt;a href="https://www.godaddy.com/" rel="noopener noreferrer"&gt;GoDaddy&lt;/a&gt;, etc. (we used Google for AlgoAcademy which was $10/year).&lt;/p&gt;

&lt;p&gt;There are two steps you would need to configure to connect the project with a custom domain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create domain records with DNS registrar&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure NGINX on the EC2 instance to recognize the domain&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Creating Domain records&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Let's start with configuring our DNS with records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;DNS&lt;/strong&gt; portion of your registrar.&lt;/li&gt;
&lt;li&gt;Find where you can create custom resource records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set the records like so:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;TTL&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;1h&lt;/td&gt;
&lt;td&gt;YOUR-ELASTIC-IP-ADDRESS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;1h&lt;/td&gt;
&lt;td&gt;your-awesome-site.com&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Configuring our Web Server&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Edit the NGINX config file inside your EC2 instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo vim /etc/nginx/sites-available/default


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Update the &lt;code&gt;server:server_name&lt;/code&gt; section of the config file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

server {
server_name &amp;lt;YOUR-ELASTIC-IP&amp;gt; your-awesome-site.com www.your-awesome-site.com;
...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save and restart NGINX:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

sudo sudo systemctl restart nginx


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;DNS changes can take up to 48 hours to update so your results may vary. Once it is complete, going to your custom domain should redirect you to your app.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  HTTPS
&lt;/h2&gt;

&lt;p&gt;Secure Sockets Layer (SSL) is a standard security technology for establishing an encrypted link between a server and a client. So far, we have been serving web content over HTTP, which can be dangerous as data sent between the server and client is not encrypted. If you are handling user sign-in and need to protect data such as passwords or credit card information, it is always best practice to have SSL certification on your applications.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will be using Certbot by letsencrypt.org, a non-profit organization that provides free SSL Certificates.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Installing Certbot&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;On your browser go to &lt;a href="https://certbot.eff.org/instructions" rel="noopener noreferrer"&gt;https://certbot.eff.org/instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Select the Software and Operating System (OS) you are using. In this case, we are using NGINX and Ubuntu 18.04 LTS (bionic).&lt;/p&gt;

&lt;p&gt;Inside your EC2 Instance, follow the command-line instructions until you see these instructions:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

% sudo certbot --nginx


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After running this command, Certbot will present to you the following prompt: Which names would you like to activate HTTPS for? &lt;/p&gt;

&lt;p&gt;If NGINX is configured correctly, it should show both your root domain as well as with the www subdomain:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

1: your-awesome-site.com
2: www.your-awesome-site.com


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Select enter to activate both HTTP and HTTPs. The next prompt will be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the web server configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Select option 2 as this will redirect all traffic through HTTPS and is the most secure option. Afterward, Certbot will make changes to the NGINX configuration file.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Once your site is using HTTPS, double-check your API calls and make sure that they are going to the https:// endpoint rather than http://. This may be an unnecessary precaution, but it is an easy bug to miss.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, go to your custom domain. Check to see if there is a lock icon next to your URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527267-2674b580-be52-11ea-9405-874f4f4ba7f0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F41876764%2F86527267-2674b580-be52-11ea-9405-874f4f4ba7f0.png" alt="secure_site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully deployed a web app with HTTPS!&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;I hope this provided some help for those getting started with web development and AWS. If you run into any problems, please feel free to reach out to either me or &lt;a href="https://github.com/tuvo1106/tuvo1106" rel="noopener noreferrer"&gt;Tu&lt;/a&gt; and we can try our best to help. Thank you for reading!&lt;/p&gt;

&lt;p&gt;Back to Table of Contents&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>aws</category>
    </item>
    <item>
      <title>Deploying a Production-ready React-Express app on AWS</title>
      <dc:creator>Ryuichi Miyazaki</dc:creator>
      <pubDate>Wed, 26 Aug 2020 22:23:35 +0000</pubDate>
      <link>https://dev.to/rmiyazaki6499/deploying-a-production-ready-react-express-app-on-aws-62m</link>
      <guid>https://dev.to/rmiyazaki6499/deploying-a-production-ready-react-express-app-on-aws-62m</guid>
      <description>&lt;p&gt;In this tutorial, I will be going over to how to deploy a Javascript app from start to finish using AWS and EC2. Recently, my partner &lt;a href="https://github.com/tuvo1106" rel="noopener noreferrer"&gt;Tu Vo&lt;/a&gt; and I launched our app &lt;a href="https://algoacademy.dev/" rel="noopener noreferrer"&gt;AlgoAcademy&lt;/a&gt; (a resource for reviewing algorithms and data structures) and we wanted to share with other developers some of the lessons we learned along the way.&lt;/p&gt;

&lt;p&gt;Following this tutorial, you will have an application that has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A React frontend, Express backend&lt;/li&gt;
&lt;li&gt;An AWS EC2 server configured to host your application&lt;/li&gt;
&lt;li&gt;SSL-certification with Certbot&lt;/li&gt;
&lt;li&gt;A custom domain name&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Continuous deployment with Github Actions/SSM Agent&lt;/p&gt;

&lt;p&gt;We have provided a dummy repo to follow along with &lt;a href="https://github.com/rmiyazaki6499/mern-app.git" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but feel free to apply it to your own application as necessary.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Project Layout&lt;/li&gt;
&lt;li&gt;Previewing the Project&lt;/li&gt;
&lt;li&gt;
Previewing the Mern-app project with Docker

&lt;ul&gt;
&lt;li&gt;Install Docker&lt;/li&gt;
&lt;li&gt;Cleaning up the Container and Image&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Previewing the Mern-app project Locally&lt;/li&gt;

&lt;li&gt;Creating an AWS Account&lt;/li&gt;

&lt;li&gt;

Creating an AWS EC2 Instance

&lt;ul&gt;
&lt;li&gt;EC2 Console&lt;/li&gt;
&lt;li&gt;AMI&lt;/li&gt;
&lt;li&gt;Security Groups&lt;/li&gt;
&lt;li&gt;Instance Details&lt;/li&gt;
&lt;li&gt;Key Pairs&lt;/li&gt;
&lt;li&gt;Elastic IP&lt;/li&gt;
&lt;li&gt;Connecting to your EC2 Instance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

EC2 Environment Setup

&lt;ul&gt;
&lt;li&gt;Setting up the Project on the Remote Server&lt;/li&gt;
&lt;li&gt;Starting PM2&lt;/li&gt;
&lt;li&gt;Configuring NGINX&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up Continuous Deployment

&lt;ul&gt;
&lt;li&gt;Github Actions&lt;/li&gt;
&lt;li&gt;Create SSM Role&lt;/li&gt;
&lt;li&gt;Assigning SSM Role to EC2 Instance&lt;/li&gt;
&lt;li&gt;Github Secrets&lt;/li&gt;
&lt;li&gt;Deployment Script&lt;/li&gt;
&lt;li&gt;YAML File&lt;/li&gt;
&lt;li&gt;Issues with Github Actions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up your Domain

&lt;ul&gt;
&lt;li&gt;Creating Domain records&lt;/li&gt;
&lt;li&gt;Configuring our Web Server&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

HTTPS

&lt;ul&gt;
&lt;li&gt;Installing Certbot&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Closing Thoughts&lt;/p&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Layout
&lt;/h2&gt;

&lt;p&gt;Here is the project layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mern-app
|__ client/ (React App Frontend)
|  |__ public/
|  |__ src/
|__ scripts/
|__ app.js (Express Backend)
|__ package.json
|__ Dockerfile
|__ docker-compose.yml

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Previewing the Project
&lt;/h3&gt;

&lt;p&gt;Start by cloning the project with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/rmiyazaki6499/mern-app.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Previewing the &lt;code&gt;mern-app&lt;/code&gt; project with Docker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install Docker
&lt;/h3&gt;

&lt;p&gt;To make this as easy as possible, we will be using &lt;em&gt;Docker Compose&lt;/em&gt; to creat our container.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you do not have Docker yet, start by downloading it if you are on a Mac or Windows:&lt;br&gt;
  &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or if you are on a Linux Distribution follow the directions here:&lt;br&gt;
  &lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;https://docs.docker.com/compose/install/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To confirm you have Docker Compose, open up your terminal and run the command below:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  $ docker-compose --version
  docker-compose version 1.26.2, build eefe0d31
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go into the project directory to build and run the container with:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  $ cd mern-app/
  $ docker-compose up --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navigate to &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt;, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp8kp04urqkfphajiu9ee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp8kp04urqkfphajiu9ee.png" alt="mern-app_react_success" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cleaning up the Container and Image
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To stop the container from running, use &lt;code&gt;&amp;lt;Ctrl-C&amp;gt;&lt;/code&gt; twice.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To close down the container use the command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  $ docker-compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then to clean up the container and image which we are no longer using use the command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  $ docker system prune -fa
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirm that the container and image is no longer there with:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  $ docker system df -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Previewing the &lt;code&gt;mern-app&lt;/code&gt; project locally
&lt;/h2&gt;

&lt;p&gt;To preview the project on your local machine, follow the directions below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install dependencies for both Express and React:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;mern-app/
  &lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;client/
  &lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To run the React server, use this command in the client directory:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you go to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpg4uzhsgr4nncqp45si.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpg4uzhsgr4nncqp45si.png" alt="mern-app_react" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The API call is not working yet because we have not started the Express server. In another terminal session, run the command "npm start" at the root directory of the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadptalo67ojw9s1k3ctg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadptalo67ojw9s1k3ctg.png" alt="mern-app_run_server" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Express is now running on port 5000. Switch back to the window with &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; and refresh the page. You should see an updated message at the bottom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp8kp04urqkfphajiu9ee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp8kp04urqkfphajiu9ee.png" alt="mern-app_react_success" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have two servers running: one for the React frontend and one for the Express backend. For this tutorial, however, we only need one server running, so we will run a reverse proxy for React and have Express serve all the content. Stop the React server on port 3000 with Ctrl-C.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;client&lt;/code&gt; directory run the command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;npm run-script build
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;React will create a production build of your app which serves as an entry point for the static content (HTML, CSS, and Javascript). Now, if you go to &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt;, you should see the same React page from earlier!&lt;/p&gt;

&lt;p&gt;This project currently will only display locally, so in order for anyone on the internet to see it, we will need a remote computer to serve our app.&lt;/p&gt;

&lt;p&gt;Back to Table of Contents&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating an AWS Account
&lt;/h2&gt;

&lt;p&gt;Why choose AWS?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It offers a lot of free services for new accounts.&lt;/li&gt;
&lt;li&gt;Very popular among startups and even enterprises.&lt;/li&gt;
&lt;li&gt;Customer service support, in our opinion, is a step above the competition.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you do not have an account, check out this step by step guide by Amazon &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before you provision a new server, it is best practice to make sure your account is as secure as possible by following the prompts on your Security Status checklist. This can be found under the IAM tab from your console's homepage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm5uupqrk9bl2fy6efkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frm5uupqrk9bl2fy6efkt.png" alt="security_status" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating an AWS EC2 Instance
&lt;/h2&gt;

&lt;p&gt;Amazon's EC2 or Elastic Compute Cloud is one of the core products/services AWS provides and is the main building block for many of AWS's other services. It allows users to essentially rent virtual computers on which to run their own applications. You can learn more about EC2 &lt;a href="https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start out by going into the AWS Console and going to the EC2 tab. An easy way to get there is through the Services link at the top and search for EC2 in the prompt.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We recommend setting your AWS Region to the one closest to you or your intended audience. However, please note that not all AWS Services will be available depending on the region. For our example, we will be working out of the us-east-1 as this region supports all AWS Services.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;EC2 Console&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;You should see this screen (as of July 2020):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznv9ern8tv5pstpi5gff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznv9ern8tv5pstpi5gff.png" alt="ec2_console" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the &lt;strong&gt;Running Instances&lt;/strong&gt; link on the EC2 dashboard and click Launch Instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad8guj8e50c2bzb0w16x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad8guj8e50c2bzb0w16x.png" alt="ec2_running_instances" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;AMI&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;In this step, AWS will prompt you to choose an AMI. AMI's are templates to configure new instances. For this tutorial, we will be using Ubuntu 18.04 64-bit (free tier).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4s8kkto9s7ikuakunis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4s8kkto9s7ikuakunis.png" alt="ec2_choose_ami" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select the &lt;strong&gt;t2.micro&lt;/strong&gt; instance type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61dgnnz8n9mlr7g5gws6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61dgnnz8n9mlr7g5gws6.png" alt="ec2_choose_instance_type" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next screen, keep clicking next until you see the option to &lt;strong&gt;Configure Security Group&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Security Groups&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Security groups are virtual firewalls for your instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;em&gt;by default, there is an implicit deny on all ports meaning if you do not add rules, all incoming/outgoing traffic is blocked. Security groups are also stateful, which means setting inbound rules for a certain port will also affect the outbound rules for that port.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Set your Security Group settings with the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0xvyx3en283y8grm656.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0xvyx3en283y8grm656.png" alt="ec2_security_group_configuration" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Setting Anywhere on Source for Custom TCP will display a warning flag, but you can ignore that for this tutorial. Ideally, you only want to set known IP addresses.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Port Range&lt;/th&gt;
&lt;th&gt;Description.&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Port for SSH'ing into your server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;Port for HTTP requests to your web server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;443&lt;/td&gt;
&lt;td&gt;Port for HTTPS requests to your web server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom TCP&lt;/td&gt;
&lt;td&gt;5000&lt;/td&gt;
&lt;td&gt;Port which Express will run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom TCP&lt;/td&gt;
&lt;td&gt;27017&lt;/td&gt;
&lt;td&gt;Port at which to connect to MongoDB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see with the warning near the bottom of the screen, you do not want to set your &lt;em&gt;SSH Source IP&lt;/em&gt; as anywhere. This will create a security vulnerability as anyone can try to attempt to log into your server.&lt;/p&gt;

&lt;p&gt;Therefore, be sure to set it to your own IP address and any other IP address which may need access to the instance.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Instance Details&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Click forward to &lt;strong&gt;Review and Launch&lt;/strong&gt; to view all configurations of your Instance/AMI.&lt;br&gt;
If the configurations look correct go ahead and hit &lt;strong&gt;Launch&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;Key Pairs&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Once you launch the instance, AWS will prompt you to create a key pair. A key pair consists of a public key that AWS stores and a private key file that you store. Together they allow you to connect to your instance securely through asymmetrical encryption.&lt;/p&gt;

&lt;p&gt;If this is the first time you are creating a key pair for your project, select &lt;strong&gt;Create a new key pair&lt;/strong&gt; from the drop-down and add a name for the key pair.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Be sure to store the key pair in a secure location. It is generated only once and AWS will not have access to it if you lose it. This is your only means to log into the EC2 instance via SSH.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ufbj5myds8oim5y6gp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ufbj5myds8oim5y6gp9.png" alt="key_pair" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have downloaded the &lt;strong&gt;key pair&lt;/strong&gt; make sure to move the &lt;strong&gt;.pem&lt;/strong&gt; file to the root directory of your project on your local computer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0r7ogksdxkybewb6xry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0r7ogksdxkybewb6xry.png" alt="mern-app_root_w_pem" width="789" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, check the checkbox acknowledging that you have access to the private key pair and click Launch Instances. This should take you to the Launch Status page.&lt;/p&gt;


&lt;h2&gt;
  
  
  Accessing your EC2 Instance
&lt;/h2&gt;

&lt;p&gt;Click on the Instances tab on your EC2 console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzryzn4v4wj91wrizw2im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzryzn4v4wj91wrizw2im.png" alt="ec2_instance_first_initializing" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The instance may take a couple of minutes to launch. Once it passes its' status checks, the instance state should show a green circle and a "running" state.&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;em&gt;Elastic IP&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Before you can log into your EC2 instance, it is important to first generate an Elastic IP and associate it to your EC2 instance.&lt;/p&gt;

&lt;p&gt;An Elastic IP is a dedicated IP address for your EC2 instance. Although the instance has a public IP address assigned upon creation, that IP address is dynamic and does not persist if you stop and start the instance. With an Elastic IP address, you can mask the failure of an instance by remapping the address to another instance in your account.&lt;/p&gt;

&lt;p&gt;Therefore, by using an Elastic IP, you can have a dedicated IP to which users from the internet can access your instance. This will come in handy later when you assign a custom domain name and add SSL certification to the server.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: If you are using the free tier, AWS will charge you if your Elastic IP is NOT associated with an AWS identity.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the EC2 dashboard, look under the &lt;strong&gt;Network &amp;amp; Security&lt;/strong&gt; tab and go to &lt;strong&gt;Elastic IPs&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yjh0bpipk9whzhnxi0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yjh0bpipk9whzhnxi0w.png" alt="elastic_ips_link" width="299" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should take you here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupqyokdqak8000vto4tw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fupqyokdqak8000vto4tw.png" alt="elastic_ip_addresses" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Allocate Elastic IP address&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It should take you here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftupui7gpkbxflihkppzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftupui7gpkbxflihkppzz.png" alt="allocate_ip_address" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Allocate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3w9m441cufwpja0b3ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3w9m441cufwpja0b3ls.png" alt="elastic_ip_created" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should create an Elastic IP. The next step is to associate that Elastic IP to the instance.&lt;/p&gt;

&lt;p&gt;With the Elastic IP checked on the left side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Actions&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Associate Elastic IP address&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Make sure your Resource type is Instance&lt;/li&gt;
&lt;li&gt;Search for your instance (if this is your first time, it should be the only one)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Associate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To check if everything is done correctly, go to the Instances tab and in the instance details, you should see the Elastic IP.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;Connecting to your EC2 Instance&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;With the instance selected in the EC2 console, click Connect near the top. You will be prompted with directions on how to connect to your EC2 instance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn95xaqmmcwsseyfe62dh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn95xaqmmcwsseyfe62dh.png" alt="connect_to_your_instance" width="800" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Changing the .pem file's permission to read-only ensures nobody can modify your private key.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  EC2 Environment Setup
&lt;/h2&gt;

&lt;p&gt;Once you are logged into your server, use the following script to install all of the project dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://gist.githubusercontent.com/cornflourblue/f0abd30f47d96d6ff127fe8a9e5bbd9f/raw/e3047c9dc3ce8b796e7354c92d2c47ce61981d2f/setup-nodejs-mongodb-production-server-on-ubuntu-1804.sh | sudo bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 10.x &amp;amp; NPM&lt;/li&gt;
&lt;li&gt;MongoDB 4.0&lt;/li&gt;
&lt;li&gt;PM2&lt;/li&gt;
&lt;li&gt;NGINX&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UFW (Firewall)&lt;/p&gt;

&lt;p&gt;*Note: If you would like to better understand what is going on in this script please check out his blog &lt;a href="https://jasonwatmore.com/post/2018/09/26/setup-nodejs-mongodb-production-server-on-ubuntu-1804" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Setting up the Project on the Remote Server&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Recall the steps earlier we did with the dummy project on our local machine. We will repeat that on the EC2 instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% git clone https://github.com/rmiyazaki6499/mern-app.git
% cd mern-app/
% npm install
% cd client/
% npm install
% npm run-script build (or npm build if you have that set up)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;em&gt;Starting PM2&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;PM2 is a daemon process manager for Node.js applications that manages and keeps applications online. To take a look at our current PM2 processes, use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% sudo pm2 status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that we do not have any processes running yet.&lt;br&gt;
At the root of your project directory with our Express app run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% sudo pm2 start app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: We are using app.js for our app but yours may use server.js&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To stop Express, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% sudo pm2 stop app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have stopped it, start Express again, this time with flags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% sudo pm2 start app.js -i max --watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-i max&lt;/code&gt; - allows us to run processes with the max number of threads available. Because NodeJS is single-threaded, using all available cores will maximize the performance of the app.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--watch&lt;/code&gt; - allows the app to automatically restart if there are any changes to the directory. You can think of it as similar to the package nodemon but for production.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Configuring NGINX&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Next, we need to configure NGINX to redirect web traffic. The goal is to have API endpoints go through Express and have React code serve the rest.&lt;/p&gt;

&lt;p&gt;Create a new NGINX config file with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% sudo vim /etc/nginx/sites-available/&amp;lt;YOUR-PROJECT-NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste in the following configurations and replace any of the ALL CAPS sections with your own project details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
server_name &amp;lt;YOUR EC2 ELASTIC IP ADDRESS&amp;gt;;

# react app &amp;amp; front-end files
location / {
root /home/ubuntu/&amp;lt;YOUR PROJECT DIRECTORY&amp;gt;/client/build/;
try_files $uri /index.html;
}

# node api reverse proxy // the /api/ is assuming your api routes start with that i.e. www.your-site.com/api/endpoint
location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_pass http://localhost:5000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The root line in &lt;code&gt;location/&lt;/code&gt; needs to be where the static files are served. In this case, it is in the client's build directory. For the follow-along, it would be &lt;code&gt;home/ubuntu/mern-app/client/build/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The proxy_pass in location /api needs to be the location of where Express is running (in this case &lt;em&gt;localhost:5000&lt;/em&gt;, but it can be different depending on your configuration).&lt;br&gt;
  Once your NGINX config is set up, make sure there are no syntax errors with:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  % sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Next, create a soft link of your config file from sites-available to the sites-enabled directory. This step is important because NGINX will use the configuration settings located at /etc/nginx/sites-available/default by default if there is nothing in sites-enabled.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  % sudo ln -s /etc/nginx/sites-available/&amp;lt;YOUR-PROJECT-NAME&amp;gt; /etc/nginx/sites-enabled
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Restart the NGINX Web Server with:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  % sudo systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now if you go to your Elastic IP on your browser it should show the app!&lt;/p&gt;

&lt;p&gt;Back to Table of Contents&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up Continuous Deployment
&lt;/h2&gt;

&lt;p&gt;Continuous Deployment is helpful because it saves you the time of having to ssh into your EC2 instance each time you make an update on your codebase. &lt;/p&gt;

&lt;p&gt;In this project, we will be using a Github Action called &lt;a href="https://github.com/marketplace/actions/aws-ssm-send-command" rel="noopener noreferrer"&gt;AWS SSM Send-Command&lt;/a&gt; created by &lt;strong&gt;peterkimzz&lt;/strong&gt; to implement auto-deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Github Actions&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Github Actions is a service by Github that allows you to perform actions such as run scripts every time something happens to a repository. In our case, we will run a script to install the latest dependencies and restart our server every time a push is made to master.&lt;/p&gt;

&lt;p&gt;For Github Actions to work, it needs a way to communicate with the EC2 Instance and vice-versa. In order to do that, we need to assign permissions via IAM roles.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Create SSM Role&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;To create an &lt;strong&gt;IAM Role&lt;/strong&gt; with &lt;code&gt;AmazonSSMFullAccess&lt;/code&gt; permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the IAM console at &lt;a href="https://console.aws.amazon.com/iam/" rel="noopener noreferrer"&gt;https://console.aws.amazon.com/iam/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In the navigation panel, select &lt;strong&gt;Roles&lt;/strong&gt;, and then click &lt;strong&gt;Create role&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;em&gt;Select type of trusted entity&lt;/em&gt;, choose &lt;strong&gt;AWS service&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the &lt;em&gt;Choose a use case&lt;/em&gt; section, choose &lt;strong&gt;EC2&lt;/strong&gt;, and then choose &lt;strong&gt;Next: Permissions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On the Attached permissions policy page, search for the &lt;code&gt;AmazonSSMFullAccess&lt;/code&gt; policy, choose it, and then choose &lt;strong&gt;Next: Review&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Review&lt;/strong&gt; page, type a name in the Role name box, and then type a description.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose &lt;strong&gt;Create role&lt;/strong&gt;. The system returns you to the Roles page.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Assigning an SSM Role to EC2 Instance&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Once you have the &lt;strong&gt;Role&lt;/strong&gt; created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;EC2 Instance Dashboard&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Go to the &lt;strong&gt;Instances&lt;/strong&gt; link&lt;/li&gt;
&lt;li&gt;Highlight the Instance&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instance Settings&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attach/Replace IAM Role&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select the SSM Role you had created earlier&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hit &lt;strong&gt;Apply&lt;/strong&gt; to save changes&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Github Secrets&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;With our instance being able to use the SSM Agent, we will need to provide it some details so that it can access our EC2 instance.&lt;/p&gt;

&lt;p&gt;Now that the instance is able to communicate to Github via SSM Agent, you will need to provide the repo with credentials. Github Secrets act like environment variables for repositories and store sensitive data such as AWS login information. In order for the Github Actions script to work, it needs these three secrets: AWS_ACCESS_KEY, AWS_SECRET_ACCESS_KEY, and INSTANCE_ID.&lt;/p&gt;

&lt;p&gt;There is an article by AWS on how to find your AWS Access Key and Secret Access Key &lt;a href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Your instance ID is shown on your instances tab under EC2.&lt;/p&gt;

&lt;p&gt;Start by going to your Github project repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then go to your &lt;strong&gt;Settings&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;On the menu on the left, look for the link for &lt;strong&gt;Secrets&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There, add the three &lt;em&gt;Secrets&lt;/em&gt; with these keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;INSTANCE_ID&lt;/code&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Deployment script&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Next, let's create a bash script to download dependencies and restart NGINX and PM2. Inside the EC2 instance, create a deploy.sh script in the root of the directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% vim deploy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste in the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh     
sudo git pull origin master
sudo npm install
cd client
npm install
sudo npm run-script build
cd ..
sudo systemctl restart nginx
sudo pm2 restart all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;em&gt;YAML File&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;AWS SSM Send-Command&lt;/em&gt; requires a .yml file to execute. At the root of the project, create these two directories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% mkdir -p .github/workflows/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new YAML file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% &lt;span class="nb"&gt;sudo &lt;/span&gt;vim .github/workflows/deploy.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy using AWS SSM Send-Command&lt;/span&gt; 

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt; 

        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS SSM Send Command&lt;/span&gt;
              &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peterkimzz/aws-ssm-send-command@1.0.1&lt;/span&gt;
          &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY_ID  }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY  }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
          &lt;span class="na"&gt;instance-ids&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.INSTANCE_ID  }}&lt;/span&gt;
          &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy the master branch&lt;/span&gt;
          &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/home/ubuntu/&amp;lt;YOUR PROJECT DIRECTORY&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/bin/sh ./deploy.sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Secrets we provided to the repo earlier comes into use in this script.&lt;/p&gt;

&lt;p&gt;There are 3 parts of the .yml file to configure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The aws-region should be the same region as where you have created your EC2 instance. (If you do not know, check the top left of your EC2 console to confirm the region you are in).&lt;/li&gt;
&lt;li&gt;working-directory should be the directory where you created the deploy.sh script.&lt;/li&gt;
&lt;li&gt;command should be the command you would like the SSM agent to run.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once this is complete, commit and push the workflow to your repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up your Domain
&lt;/h2&gt;

&lt;p&gt;So far, users can access the site using the Elastic IP. However, it can be difficult to remember and share so we will configure a custom domain name.&lt;/p&gt;

&lt;p&gt;To get started, you need to first purchase a domain. This can range from $10 to $1,000+s. Amazon has a service called Route53 you can use or you can choose other providers such as &lt;a href="https://domains.google/" rel="noopener noreferrer"&gt;Google Domains&lt;/a&gt;, &lt;a href="https://www.godaddy.com/" rel="noopener noreferrer"&gt;GoDaddy&lt;/a&gt;, etc. (we used Google for AlgoAcademy which was $10/year).&lt;/p&gt;

&lt;p&gt;There are two steps you would need to configure to connect the project with a custom domain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create domain records with DNS registrar&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure NGINX on the EC2 instance to recognize the domain&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Creating Domain records&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Let's start with configuring our DNS with records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;DNS&lt;/strong&gt; portion of your registrar.&lt;/li&gt;
&lt;li&gt;Find where you can create custom resource records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Set the records like so:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;TTL&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;1h&lt;/td&gt;
&lt;td&gt;YOUR-ELASTIC-IP-ADDRESS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;www&lt;/td&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;1h&lt;/td&gt;
&lt;td&gt;your-awesome-site.com&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Configuring our Web Server&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Edit the NGINX config file inside your EC2 instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% &lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/nginx/sites-available/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;server:server_name&lt;/code&gt; section of the config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
server_name &amp;lt;YOUR-ELASTIC-IP&amp;gt; your-awesome-site.com www.your-awesome-site.com;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and restart NGINX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo sudo systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;DNS changes can take up to 48 hours to update so your results may vary. Once it is complete, going to your custom domain should redirect you to your app.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  HTTPS
&lt;/h2&gt;

&lt;p&gt;Secure Sockets Layer (SSL) is a standard security technology for establishing an encrypted link between a server and a client. So far, we have been serving web content over HTTP, which can be dangerous as data sent between the server and client is not encrypted. If you are handling user sign-in and need to protect data such as passwords or credit card information, it is always best practice to have SSL certification on your applications.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will be using Certbot by letsencrypt.org, a non-profit organization that provides free SSL Certificates.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Installing Certbot&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;On your browser go to &lt;a href="https://certbot.eff.org/instructions" rel="noopener noreferrer"&gt;https://certbot.eff.org/instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Select the Software and Operating System (OS) you are using. In this case, we are using NGINX and Ubuntu 18.04 LTS (bionic).&lt;/p&gt;

&lt;p&gt;Inside your EC2 Instance, follow the command-line instructions until you see these instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% sudo certbot --nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this command, Certbot will present to you the following prompt: Which names would you like to activate HTTPS for? &lt;/p&gt;

&lt;p&gt;If NGINX is configured correctly, it should show both your root domain as well as with the www subdomain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1: your-awesome-site.com
2: www.your-awesome-site.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select enter to activate both HTTP and HTTPs. The next prompt will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the web server configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select option 2 as this will redirect all traffic through HTTPS and is the most secure option. Afterward, Certbot will make changes to the NGINX configuration file.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Once your site is using HTTPS, double-check your API calls and make sure that they are going to the https:// endpoint rather than http://. This may be an unnecessary precaution, but it is an easy bug to miss.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, go to your custom domain. Check to see if there is a lock icon next to your URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg51s28c6j49hl9sk9nz2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg51s28c6j49hl9sk9nz2.png" alt="secure_site" width="320" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully deployed a web app with HTTPS!&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;I hope this provided some help for those getting started with web development and AWS. If you run into any problems, please feel free to reach out to either me or &lt;a href="https://github.com/tuvo1106/tuvo1106" rel="noopener noreferrer"&gt;Tu&lt;/a&gt; and we can try our best to help. Thank you for reading!&lt;/p&gt;

&lt;p&gt;Back to Table of Contents&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>node</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
