React-SASS-PM2-EC2-Production-App mapped with a custom domain and secured with SSL layer.

Written by balasubramanim | Published 2018/06/23
Tech Story Tags: react | sass | pm2 | ec2 | ssl

TLDRvia the TL;DR App

In this tutorial, we will be creating a sample react app using create-react-app, configure SASS in it and upload it in GitHub and deploy the application in EC2, configure our DNS, Nginx and finally we will map our custom domain and add SSL layer to it.

To make it more clear, here is the agenda we are going to learn now.

  1. Create React App
  2. Configure SASS
  3. Upload our code in GitHub
  4. Configure SSH access in EC2 instance
  5. PM2 configuration
  6. EC2 configuration
  7. DNS configuration — (Domain mandatory)
  8. Nginx configuration
  9. Deploy your application
  10. Add SSL certificate using Let’s Encrypt

Create React App

Let’s create a basic react application using create-react-app

$ npx create-react-app react-sass-pm2-production-app$ cd react-sass-pm2-production-app$ npm start

Now you will be automatically redirected to http://localhost:3000/ where you will see your react app built in seconds.

Configure SASS

Create a folder called styles in thesrc folder and inside of it, create a file called style.sass.

SASS files should be intended properly to convert it to CSS. Only perfectly intended SASS files can be converted. So I will install a package called SassBeautify which will beautify our SASS file using a special command.

If you are using Sublime Text Editor, give a High-Five. I will guide you step by step to install and configure it.

Others — Kindly bear with me. These are just optional and you may even intend your code manually. However, I recommend you to configure the same package in your editor to make your code perfect.

Open your sublime and press Cmd+Shift+P and type Install Package and press enter to open install packages menu. Now type SassBeautify and press enter to install the package.

This plugin uses sass-convert, and so you need to have sass installed. Read the sass download page to view the installation options.

That’s it. You have configured your beautifier package. Let’s add some code and beautify it.

Before that, let’s specify the command to run SassBeautify to intend and save. The plugin does not set any default key bindings, thus you will need to specify your own.

In your keymap file (Preferences >> Key bindings — User), add a below custom key binding and save it.

[{"keys": ["alt+w"],"command": "sass_beautify"}]

Now, paste the following code in your style.sass file and press alt+w to intend and save the file automatically.

$font-stack:    Helvetica, sans-serif$primary-color: #333body  font: 100% $font-stack  color: $primary-color

You can see the file intended and saved.

If you see the following error while intending,

**There was an error beautifying your Sass:/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/universal-darwin17/rbconfig.rb:214:**

which means that there are some lines intended using the tab key. Let’s us convert it into spaces by selecting all the content in our sass file using Cmd+A option, click the Spaces (available at the right bottom corner in Sublime) and select Convert Indentation to Spaces.

Now you can beautify your code successfully.

Let’s us configure furthermore to automatically convert our SASS file into CSS file on save.

Open a new terminal and inside your root directory, give the following command and press enter key.

$ sudo sass --watch src/styles/:public/stylesheets/

Now you see your Sass if waiting for changes and once you press alt+w you could your sass file is intended, saved and converted into CSS file in public/stylesheets/style.css.

Now open the index.html file in the public folder and add the below link tag to refer your converted css file.

<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%/stylesheets/style.css">

You have configured SASS successfully.

Upload our code in GitHub

There are several steps to be followed during your initial setup. So, let’s start with creating an SSH key to authenticate to your GitHub account from your local machine.

Totally, there are two types of authentication called SSH and HTTPS.

This is the one time process and we don’t want to use HTTPS option to authenticate because we need to provide our credentials everytime whenever we pull, push or commit from your machine.

SSH Authentication mechanism goes below.

  1. Generating a new SSH key.
  2. Add your SSH key to the ssh-agent
  3. Add the SSH key to your GitHub account

Step 1: Generating a new SSH key.

Open Terminal and navigate to default ssh folder location.

$ cd ~/.ssh/ #To navigate to your default SSH key location.

Paste the text below, substituting in your GitHub email address.

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

This creates a new ssh key, using the provided email as a label.

When you’re prompted to “Enter a file in which to save the key,” press Enter. This accepts the default file location.

Enter a file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]

At the prompt, press enter twice without entering any password as of now. That’s it, you have created your SSH key successfully called id_rsa.

Step 2: Add your SSH key to the ssh-agent

Start the ssh-agent in the background.

$ eval "$(ssh-agent -s)"

Add your SSH private key to the ssh-agent.

$ ssh-add -K ~/.ssh/id_rsa

Step 3: Adding a new SSH key to your GitHub account

Copy the SSH key to your clipboard.

$ pbcopy < ~/.ssh/id_rsa.pub# Copies the contents of the id_rsa.pub file to your clipboard

If you don’t have pbcopy, you can use any of your editors to open this file and copy its whole content. I use sublime and if you want to open the above file in a sublime editor, issue the following command.

$ subl ~/.ssh/id_rsa.pub# Either issue this or above command. Don't execute both.

Copy the text.

Now, let’s go to our GitHub account and paste the key. Navigate to your GitHub account settings and click the SSH and GPG keys. (Refer the image).

Note the Highlighted text.

Click the New SSH key button at the top left corner and add your ssh key.

Give Title as per your wish and paste the copied text in the key section and add the key.

That’s it. Now, you are authenticated to perform actions in your GitHub account from your terminal. Let’s push our code and later deploy it in EC2.

Let’s create a repository for our app in GitHub.

Go to create repository in your GitHub account or click this URL to navigate to the repo creation page. It looks like below.

GitHub repo creation page.

Give your Repository name, description, repo access and you can avoid README, .gitignore options since you have already had those in your project when you create your app using create-react-app.

It’s time to link this repository with our local project. Go to your repo page and copy the text in the highlighted box (refer image below) by clicking the box at the right.

Copy the highlighted text.

Now go to your local repo directory and execute the following commands one by one to init, commit and push your code to GitHub.

$ git init$ 

Your code is now on your remote repository. Check your code at GitHub.

Configure SSH access in EC2 instance

Repeat some of the steps above in your remote instance to allow your server to pull code from your GitHub repo using SSH access when we deploy our app using PM2.

You need to connect to your remote instance before following below steps. If you are not aware of this connection, kindly refer to this link before proceeding.

Issue the following commands in your remote terminal.

$ cd ~/.ssh/ #To navigate to your default SSH key location.$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

When you’re prompted to “Enter a file in which to save the key,” press Enter. This accepts the default file location.

Enter a file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]

At the prompt, press enter twice without entering any password as of now. That’s it, you have created your SSH key successfully called id_rsa.

$ eval "$(ssh-agent -s)"$ ssh-add -K ~/.ssh/id_rsa$ pbcopy < ~/.ssh/id_rsa.pub # (or - cat ~/.ssh/id_rsa.pub) and copy

Go to your GitHub account settings and add the SSH key as you did above.

PM2 configuration

Let us configure PM2 in our local repository which will actually do our deployment works.

Basically, PM2 is specifically designed for Node.js and not for client applications. But here, we are going to automate our deployment with the help of PM2 so that, we are using it to pull our code from GitHub and run in our remote server (EC2 instance).

Note: The app is not going to run in the PM2 process.

If you are aware of Amazon EC2 instance and know how to configure and work on it, you don’t need to do anything.

However, if you aren’t aware of it, you can go through the below link and set up your remote instance ready which is required to host your Node.js server.

Make your Amazon EC2 instance up and running._In this part, we will be creating an Amazon account, EC2 instance and connect to that instance via SSH._medium.com

Note: You need a server(EC2 instance) to deploy your production ready React application.

Issue the following command to install PM2 in your root directory.

$ sudo npm i pm2 --save-dev

In your root directory, create a file called ecosystem.config.js and add the below content to it.

module.exports = {apps: [{name: "react-sass-pm2-production-app",env: {PORT: 3000,NODE_ENV: "production"}}],deploy: {production: {user: "ubuntu",host: "ec2-xx-xxx-xxx-xx.us-east-2.compute.amazonaws.com",key: "~/.ssh/AWS-EC2-INSTANCE-LIVE.pem",ref: "origin/master",repo: "git@github.com:BalasubramaniM/react-sass-pm2-production-app.git",path: "/home/ubuntu/react-app","post-deploy":"npm install && npm run build && sudo cp -r build/* /var/www/react-sass-pm2-production-app.in/"}}};

Here, In apps we are giving our application name, port and node environments. In deploy section, we are naming the configuration as production and giving user, host, key, ref, repo, path and post-deploy commands.

Remember to replace your host with your Amazon instance host, the PEM key location and update your repo link (Which you have copied earlier — the highlighted text. Hope you remember).

Note the post-deploy command. Later, after configuring Nginx in our remote instance we will learn about these commands.

PM2 has been configured successfully.

EC2 configuration

As you have seen in PM2 configuration, we have given a port number as 3000 so that we need to allow this port on EC2 to run our application on this port.

Click Security Groups under NETWORK & SECURITY in your Amazon console page.

Click Security Groups.

Right click on your security group for your instance and click Edit inbound rules.

Click Add Rule. Add the following configurations as you see in the below image and click Save.

Security group config rule.

Note: Add your port as 3000 here, in which the React app is running and add port 443 for SSL access.

DNS configuration

Required: It would be more awesome to run our react app in the custom domain (eg: https://tamilakam.in). So, you can get one @ GoDaddy or through any other domain registrar and a domain name is mandatory to complete the remaining steps.

From now on, I am going to use my site tamilakam.in for reference below for your understanding. Kindly replace tamilakam.in with your domain name.

Provide your Amazon EC2 IPv4 Public IP address in your Internet Domain Registrar DNS settings.

Get the IPv4 Public IP address from your Amazon console. It would be like 18.xxx.xxx.15

Add two A type records with values as follows in your DNS provider settings page. Refer the image below for more info.

First A record.

Type: AName: www. // Sub domain so we can access it like www.tamilakam.inValue: 18.xxx.xxx.15 // IPv4 Public IPTTL: 600 seconds

Second A record.

Type: AName: @ // To access our site with tamilakam.inValue: 18.xxx.xxx.15 // IPv4 Public IPTTL: 600 seconds

DNS Management page — Add Records.

Here, I have added three A type records. I will explain those below.

  1. The first record is to load the page when the user types just domain name.com. Eg. tamilakam.in. (Required).
  2. The second record is to load the Node.js API server. You can refer this link and this link where I have worked on hosting my Node.js application and load it using subdomain called api.tamilakam.in. (Optional).
  3. The third record is to load the page when the user types www.tamilakam.in. (Required).

We have configured our DNS successfully. Wait for 5 minutes for changes to be reflected as you have given TTL value as 600 seconds.

Nginx configuration

Let’s connect to our remote instance first using the below command from a terminal. (Replace your EC2 URL in required place)

$ ssh -i ~/.ssh/AWS-EC2-INSTANCE-LIVE.pem ubuntu@ec2-xx-xxx-xx-xx.us-east-2.compute.amazonaws.com

Install Nginx and configure in your remote server.

Ubuntu comes with its own package manager, apt-get. Using apt-get, we can install nginx in one command.

$ sudo apt-get install nginx

apt-get runs nginx automatically after install so you should now have it running on port 80, check by entering your public DNS URL into a browser.

Nginx welcome page.

If this doesn’t work, you might need to start it manually.

$ sudo /etc/init.d/nginx start

Now let’s configure our Nginx to run our Node.js server.

How are nginx configs set up? Configs are stored in plain text files in sites-available with any name. Linking them into the sites-enabled folder will cause them to be read and used when nginx starts. All of the configs are combined together by nginx.

You can take a look at this config using cat.

$ cat /etc/nginx/sites-available/default

Let’s first remove the default config from sites-enabled, we will leave it in sites-available for reference.

$ sudo rm /etc/nginx/sites-enabled/default

Let’s create a config file in sites-available with the domain name.

$ sudo nano /etc/nginx/sites-available/tamilakam.in

And add the following contents to it, press Ctrl+x, type yes and hit enter to save it.

server {listen 80;server_name tamilakam.in www.tamilakam.in;location / {root /var/www/tamilakam.in;index index.html;try_files $uri /index.html;}}

Link the config file in sites-enabled (this will make it seem like the file is actually copied insites-enabled).

$ sudo ln -s /etc/nginx/sites-available/tamilakam.in /etc/nginx/sites-enabled/tamilakam.in

Read more about symbolic links here if they are unfamiliar.

In the above code block, we are listening to the default port which is 80 and provided our server name in both the formats. We have also provided location, which will be served when the server name is hit with the root and default index file option.

As you can see the root option, we have given it as /var/www/tamilakam.in. This location acts as a source for our application. So let’s add our React app minified (production) version code in that location.

Navigate to that location and create a file called tamilakam.in.

$ cd /var/www$ sudo nano tamilakam.in

Now let’s go back to our post-deploy command in our PM2 configuration file. There you have given a command as follows.

"post-deploy":"npm install && npm run build && sudo cp -r build/* /var/www/tamilakam.in/"

Let me tell you what it does. After downloading your code from GitHub, it will do npm install first, and then run npm run build for production optimised build and finally copy this optimised build to the location we have created just now to the location /var/www/tamilakam.in.

Restart nginx for the new config to take effect.

$ sudo service nginx restart

You are done. Let’s run few commands from our local terminal so that we will deploy our React app to production in seconds.

To check whether the configurations provided by you are correct, issue the following command.

$ sudo nginx -t

If you face any error, you need to work on your server blocks (which you have created in the sites-available folder. Let me know in the comments so that we can try to solve it.

Deploy your application

From your application root directory in your local machine, issue the below command to set up our application in the remote server.

$ sudo pm2 deploy ecosystem.config.js production setup

This will configure our application in the EC2 instance.

Finally, issue the below command to host and run your application using PM2 on your remote server.

$ sudo pm2 deploy ecosystem.config.js production

Hurray!!! Your React application is now in your production server and ready to use.

Visit https://tamilakam.in to check your application.

Add SSL certificate using Let’s Encrypt

It’s time to secure our site using Secured Socket Layer.

Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free TLS/SSL certificates, thereby enabling encrypted HTTPS on web servers.

Here, you will use Certbot to obtain a free SSL certificate for Nginx on Ubuntu 16.04 and set up your certificate to renew automatically.

Connect to your remote instance and type the following commands in your EC2 terminal.

First, add the repository.

$ sudo add-apt-repository ppa:certbot/certbot

You’ll need to press ENTER to accept. Then, update the package list to pick up the new repository's package information.

$ sudo apt-get update

And finally, install Certbot’s Nginx package with apt-get.

$ sudo apt-get install python-certbot-nginx

Certbot is now ready to use, but in order for it to configure SSL for Nginx, we need to verify some of Nginx’s configuration.

Restart Nginx for effects to take place.

$ sudo systemctl reload nginx

Certbot can now find the correct server block and update it.

Next, we’ll update our firewall to allow HTTPS traffic. Issue the set of commands and refer the link in the references section for more info about the commands.

$ sudo ufw status$ sudo ufw allow 'Nginx Full'$ sudo ufw delete allow 'Nginx HTTP'

We’re now ready to run Certbot and fetch our certificates.

Obtaining an SSL Certificate. (Don’t forget to replace your domain name)

$ sudo certbot — nginx -d example.com -d www.example.com

If this is your first time running certbot, you will be prompted to enter an email address and agree to the terms of service. After doing so, certbot will communicate with the Let's Encrypt server, then run a challenge to verify that you control the domain you're requesting a certificate for.

If that’s successful, certbot will ask how you'd like to configure your HTTPS settings.

Output

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.-------------------------------------------------------------------------------1: No redirect - Make no further changes to the webserver configuration.2: Redirect - Make all requests redirect to secure HTTPS access. Choose this fornew sites, or if you're confident your site works on HTTPS. You can undo thischange by editing your web server's configuration.-------------------------------------------------------------------------------Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Select choice 2 (default — to redirect all your request to secure HTTPS access) then hit ENTER. The configuration will be updated, and Nginx will reload to pick up the new settings. certbot will wrap up with a message telling you the process was successful and where your certificates are stored:

Output

IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will   expire on 2017-10-23. To obtain a new or tweaked version of this   certificate in the future, simply run certbot again with the   "certonly" option. To non-interactively renew *all* of your   certificates, run "certbot renew" - Your account credentials have been saved in your Certbot   configuration directory at /etc/letsencrypt. You should make a   secure backup of this folder now. This configuration directory will   also contain certificates and private keys obtained by Certbot so   making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by:   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate   Donating to EFF:                    https://eff.org/donate-le

Your certificates are downloaded, installed, and loaded.

Restart Nginx.

$ sudo systemctl reload nginx

Now, try reloading your website using https:// and notice your browser's security indicator. It should indicate that the site is properly secured, usually with a green lock icon. If you test your server using the SSL Labs Server Test, it will get an A grade.

Let's finish by testing the renewal process.

To test the renewal process, you can do a dry run with certbot:

$ sudo certbot renew — dry-run

If you see no errors, you’re all set. When necessary, Certbot will renew your certificates and reload Nginx to pick up the changes. If the automated renewal process ever fails, Let’s Encrypt will send a message to the email you specified, warning you when your certificate is about to expire.

If you have further questions about using Certbot, their documentation is a good place to start.

We have secured our React application.

If you have any doubts above the above steps, feel free to put it up in the comments section and I will try to respond as soon as possible.

Since it’s quite big, you may face any prob in setting up your project. Kindly check my other tutorials so that you may find any solution to your prob in any of those.

Thank you.

Final application can be found here.

References:

How to run multiple apps on a single EC2 instance with Nginx and map your custom domain?_In this tutorial, we will be hosting a separate React and Node.js app in our EC2 instance and map our custom domain._medium.com

M.E.R.N stack application using Passport for authentication._In this tutorial, we will be integrating Google sign-in for registration or login purpose in our React application…_medium.com

How To Set Up Let's Encrypt with Nginx Server Blocks on Ubuntu 16.04 | DigitalOcean_In this tutorial, you will use Certbot to obtain a free SSL certificate for Nginx on Ubuntu 16.04 and set up your…_www.digitalocean.com


Published by HackerNoon on 2018/06/23