Deploying Full Stack App onto Ubuntu/AWS: Postgres, Express, React, Node + SSL Let's Encrypt

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

A while back a made a tutorial on how to make an app using the PERN stack and I wanted to follow up by making another video on how to deploy it. I will walk you through how to deploy this on an Ubuntu machine running on an AWS EC2 instance.

I'll cover how to setup Nginx to server our app as well as how to register a domain and setup SSL with Let's encrypt

I also wrote up a nice readme on the git repo that will walk you through the deployment process step by step(if you prefer text over video format)

git repo: https://github.com/Sanjeev-Thiyagarajan/PERN-STACK-DEPLOYMENT

👍︎︎ 1 👤︎︎ u/sloppy_networks 📅︎︎ Oct 20 2020 🗫︎ replies
Captions
so a little while back i created my pern stack tutorial video and i got a lot of feedback from you guys asking to make a deployment video or a video on how to deploy this full stack application and so that's what this video is going to be for i'm going to show you guys how to deploy this application and we're specifically going to deploy this on a ubuntu server and we're going to deploy the front end the backend and the postgres database on one ubuntu server and i'm going to show you guys how to deploy that ubuntu server on an aws ec2 instance now you will need an aws account but keep in mind that if that's not an option for you if you don't have an aws account or you don't want to make one 99 of the steps that i go over are just going to be specific to setting this up in ubuntu so if you have an ubuntu server on a digitalocean droplet or an azure virtual machine or a gcp virtual machine or even a local ubuntu server you can follow along and do it on there these steps are going to work on any ubuntu machine it doesn't have to run on aws i just chose to use aws because i see a lot of other videos going over how to deploy it on heroku or digitalocean droplet so i just wanted to make one for aws because there just isn't as many videos now for anyone that hasn't seen my pen stack tutorial and wants to actually learn how to make that application i'll make sure to include a link in the description however for this video you don't have to actually go through that that project video that tutorial instead what i've done is i've uploaded all of the finalized code onto this github repo and it's going to be a different one from the one i included in the link of my print stack video i did make a few small changes so um definitely check out the code from this specific repository if you want to follow along the main difference is i've removed the dot env file so i didn't check that in uh that's usually how you would do it uh in an actual application you want to avoid um committing your environment variables into your github repository so that your passwords aren't exposed uh within the repo itself uh but if you take a look at this repo i created a very detailed readme uh and so this is going to actually walk you through step by step on how to uh you know install postgres how to get your code copied over to the server uh how to set up an nginx web server uh and how to deploy everything step by step so you don't even need to watch this video if you like reading you can just follow along and this is going to walk you through it step by step however if you do want to follow along then you know i'm going to walk you through this as well and uh obviously because this is a video format i'm gonna make sure to really go over what each line is doing what each config is doing so that not only are you learning how to deploy um this application you're also learning you know how to work with nginx how to work with ssl how to work with a lot of the other tools that you need to know to actually deploy this application and so i think that's enough of an intro i've set up a few slides uh just to kind of go over how we're going to set up our application and you know that's only gonna take a few minutes and then afterwards you know we can go ahead and log into aws create our virtual machine and get started with deploying this application alright guys so let's go over how our application works in our development environment on our local machine and then we'll take a look at how it's going to operate in our production server and so this diagram right here uh outlines how our application works on our local dev server uh and so basically we've got our react application uh and we know that that's gonna run on local host port 3000 and so you know if you go to that address in your web browser it's going to take us to our react application and when our react application wants to talk to our back end it's going to send an http request either get post um patch whatever method it needs to send it's going to send it to localhost colon 3001 and then you know some route that starts with api if you want um it maybe api v1 restaurants or reviews depending on what data it needs and when it sends that it's going to reach the express server which is listening on localhost port 3001 which is what the request is coming in on and then based off of that it can uh if it needs to it can query the database by going to localhost and then port 5432 because the uh postgres server is going to be running on port 5432 now the important thing to remember is uh because these two are running on different ports uh logically uh the react application and the express application think they're on two different machines and we know it's you know it's on our local host right it's on our local machine but because it's running on a different port it's almost treated as a different machine it would almost be like a different ip address or any something like that so the way it works in development is that logically they're going to act as if it's two different machines sending requests to one another and that's why we needed to set up cores for our development environment uh now once we go to actually deploy our application it's going to operate a little bit differently and so we're going to deploy it on an ubuntu server and what we're going to use is nginx now nginx which is represented by this big orange block right here uh is a web server that you can install on a linux operating system it's a very powerful feature-rich web server however the way everything's going to operate with nginx on this ubuntu server is going to be a little bit different and the first thing i want to point out is um i actually purchased a domain name just to show you guys how to set it up with an actual valid domain name so i bought the domain name sanjeev.xyz and i'll walk you through kind of how to get a domain name and how to set up the dns so that traffic gets redirected to your server i'll cover all of that but the important thing to configure to consider is that react and express when we go to deploy they're going to think that they're actually on the same machine now and that's important because if you go to the slide above remember they're operating on two different ports but when we go to deploy this they're going to think they're on the same machine so that we don't actually have to specify a separate port and that's going to be important because in react when we you know send our api request we're going to have to change the url so instead of sending it to https colon uh localhost 3001 and then slash api v1 we just send it directly to api v1 because it knows it's on the local machine but anyways uh with nginx we're going to configure it so that uh if we get a request for https colon slash and then the domain name that you purchased or i purchased uh with the slash url so just the root url no other path uh it's going to take that and it's going to forward that request to the react application and so it's going to basically return the index.html that the react application creates now if we get a request going to https colon slash sanjeev.xyz and then anything that starts with the slash api so it doesn't matter what comes afterwards if it starts with the slash api we'll configure nginx to forward that directly to our express application and our express application is still technically listening on port 3001 however all of that's extracted away from the client uh so everything's going to be going through nginx nginx will just forward it to the express application and then the express application can then uh obviously uh you know query the database which is also going to be running on the same machine so i'm going to show you guys how to set that up with nginx it's really simple there's just a couple of configs that we got to add um and you'll see that the overall deployment process isn't too bad and once you get the hang of it you'll see that it's pretty easy to deploy and you'll be able to customize it depending on what you're ultimately trying to accomplish with your application and whatever specific you need uh for your app all right so let's head on over to our code uh there's gonna be a few minor changes actually really just one minor change that we have to make to our application to make sure that when we copy our code over to our production server it's going to operate the way we want it to uh and so just to reiterate how our application works we've got our express server our backend running up port 3001 and then we've got our react application i don't know if it's going to tell us in the log but it's running on port 3000 and we can verify that by actually going to localhost port 3000 and we can see the react app being delivered to our web browser and so let's start off by taking a look at our back end so all of our back-end is stored in our server code inside the server directory uh and really there isn't much code so everything's just in the server.js file and if you just take a look at this um let's just make sure that uh there's nothing that we would need to change from a url or path perspective because uh you know it's not going to be running on our local dev server it's going to be running on our production server uh and so one thing you notice right away is that we've kind of already prepared our app to be production ready uh when we set the port right here um we basically said that uh if the environment variable of port is set we're gonna use whatever that value is however if it's not set we'll just default to 3001. and if we go to our environment variable file or the dot env file uh you'll see that we are already setting it to port 3001 so it's going to grab port 3001 and that's what the port that's going to be the port that we're going to use however in production we can choose what port we want to use you can pick whatever port and you'll see the way we set up nginx we can choose to use really any port so when we actually go to deploy we can do 4001 5000 3001 i'm just going to do 3001 because that's just what we've already been doing and uh there's going to be no issues with using port 3001 in production as well um but there's nothing else that really needs to change because if you look at how we access our database the credentials for logging into our database aren't really set anywhere in our code we used environment variables for that so you know you can see here the pg user the pg host the password the database and the postgres port are all set based off of environment variables this is one way of connecting to your database if you take a look at the pg library you know we can statically define it as well but because we chose to use environment variables as long as we set these environment variables uh with the correct values when we go to production everything should work without issues so really so far on our backend we don't need to touch anything we don't need to change anything uh the only changes that we need to make are going to be on our front end react app and it's going to be under the apis folder so if you go to apis this is where we're basically telling react you know what address should we send our api requests to and so you can see here the base url for axios is going to be http colon flash localhost port 3001 slash api slash b1 slash restaurants so all api requests are going to have this url defined as the base url but we're going to change that a bit so what i'm going to do actually is i'm going to create a variable and i'm just going to call this base url as well and i'm going to set that equal to this string right here and i'm going to now reference that url ah that variable right so up to this point we haven't actually changed anything functionality wise exactly the same and you know with javascript when the key and the value are the same we can actually just remove this and that's going to be the equivalent of just putting that in there so once again still nothing has changed now the issue comes when we go to deploy this url is not going to exist because our server isn't going to technically be running um or reachable on localhost port 3001. so if it tries to send an api request to this url it's going to fail and so what we have to do is put in a conditional statement saying that uh if we are in production mode uh then we're going to use a certain url for our api requests and if we're in a development mode or any other mode we're going to use a different url and so i'm going to use a ternary operator but basically the logic behind what i'm trying to do is we're going to use an environment variable to dictate when we're in production mode and it's standard procedure to use an environment variable called node underscore env and so if you when we actually go to deploy our react app you'll find that the node underscore env variable will be set to production when we deploy it so when we actually build all the files right now node env is going to be set to production uh sorry development when we're in development mode um but when we go to production uh you'll see that it's going to be set to production so we can just do a check on what the value of this variable is to determine you know are we in development mode or if we're in production mode and so what we want to say is you know if we are in production then we want to use the base url of slash api v1 and then restaurants right because remember our express server is no longer going to be reachable through local host port 3001 it's going to be reachable through um directly on that same machine so we don't need to go to a separate port so we can just pass in the url and then we can say else base url is going to equal whatever it was before so if we're not in production mode we're going to use the same exact url and so let me comment this line out and we can just say uh const base url equals and then we're gonna use a ternary operator uh so we'll say if process dot env so this is how you grab an environment variable and then dot node underscore env equals equals equals production then we want to set the base url to uh api v1 restaurants however if it's not production then we want to set it back to this all right so hopefully that made sense um but that's all we really need to do uh and that's it uh so for our react front end is now ready for deployment we don't really need to do anything else all right so let's go ahead and log into the aws management console and let's work on getting that ubuntu server deployed within aws uh and so the service that we're using within aws is called ec2 so that's what's going to allow us to basically create a virtual machine in the cloud and all you have to do is just search for ec2 and just select that and before we create our ec2 instance the first thing that we have to do is set up key pairs and so by default when you want to be able to ssh or connect into any of your ec2 instances that you deploy uh aws wants to use uh certificates and so here you want to go under key pairs i've got a few key pairs already created um if you've never created one then this is going to be an empty list and go ahead and just create a new one and give it a name give it a meaningful name and by the way you can reuse the same key pair for all of your servers if you wanted to so i'm going to call this one yelp and i'm going to select pem format and then i'll hit create key pair okay and you'll see that right away your web browser is going to download that pen file and it's important that you store this file someplace that's convenient okay you don't want to lose that file that's how you uh are able to actually ssh to the machine all right so now that we've got our pem file downloaded let's go to instances and let's work on deploying an ec2 instance you'll see that i have two instances right now um one in a stop state one and a running state if you don't have any ec2 instances then you'll just see this section blank so let's hit launch instance and we want to search for ubuntu okay and we're going to deploy this on ubuntu 20.0.4 and the reason i chose that is because you know it's the latest version might as well show you guys how to do it on the latest version keep in mind for a couple of the steps if you guys decide to roll out with 18.04 or 16.04 a couple of steps will be different different i think that's mainly in the ssl portion of things but a majority of the steps should be almost identical but if you do want to just follow along with what i'm doing then make sure you select 20.04 your guarantee did not have any issues we'll select that i'll go ahead and select your instance size i'm going to select the t2 micro because it's free tier eligible so that's going to be one of the cheaper instances and then let's go to configure instance details and i usually leave most of these things as default the only thing i really just want to change is the tags and so this is where we can give our ec2 instance an actual name so you want to give the key to be named with a capital m it's important that you select it with a capital m and then give whatever name you want to give for your ec2 instance so i'm going to call this yelp app and then we can hit review and launch and then hit launch now here you have to select the key pair that you created earlier on uh so choose an existing key pair and then we want to i'm going to select the yelp and then you have to select this acknowledgement and then we'll launch the instance all right and if you select view instances it's going to take us back to the main instances section uh within the ec2 page and so it's going to take maybe a minute or so for the actual ec2 instance to deploy so um we'll give that a second to finish and then uh we'll continue with connecting to that server and um getting our code copied over to the machine all right and so once your ec2 instance has been deployed open up your terminal and it doesn't matter if you're on a windows or a mac machine the command to connect to or ssh to the ec2 instance is going to be the same what you want to do is ssh and then you want to do dash i so the dash i is what's going to allow us to provide a specific pem file that we're going to use to connect to the machine and if you recall this is that pen file that we downloaded and now we need to pass in the uh path towards that pen file so like i said make sure you keep that pen file in a folder that you can reach uh that's in my downloads directory right now so i'll do downloads and then yelp dot pem keep in mind i'm on a windows machine so we use uh i can't remember is that a forward slash or a backwards like that's a backslash um but on linux uh you're gonna use uh forward slash all right so now we have provided the path to our pen file then we want to pass in the username that we want to log in as and by default on ubuntu machines in aws the default username to connect to is always going to be ubuntu and then you do at and then we have to provide the ip address or the public ipa address of the machine and within the aws console you'll see under ipv4 public ip this is going to be the ipi discover machine so we can just take that and copy it and then paste it in there and then hit enter you'll probably get this warning right here just hit yes and there you go so once you see this output it means you've successfully logged into the machine now i don't actually like to use the default terminal for windows so i'm going to open this up in a different terminal functionality wise doesn't change anything i just allows me to use something i'm a little more comfortable with all right so now that we're connected to our ubuntu server it's time to start configuring it so that it can host our application and at this point you know you can take a look at the readme and just follow along with this i'm gonna for the most part uh follow along with the readme however there's gonna be a few instances where i kind of hop around a bit and i'm just gonna do that uh for i guess explanation purposes uh it's gonna help me explain what certain commands and configs do a little bit more uh in this document i tried to make it as descriptive as possible um but ultimately this this readme is just to make sure that you guys can get it up and running as quickly as possible and so my priority wasn't uh uh wasn't explaining things in this is just to give you the commands that you need to set it up all right so uh you know in the fir in the readme the first thing that we're going to do is set up postgres uh and to set up postgres uh we want to make sure that we update our packages and our repository uh so we do a pseudo aft update and a pseudo app upgrade and then we pass in a dash y flag and that's just going to make it so that we don't get a prompt asking if you know we approve uh whatever changes it needs to make so we can just copy this line directly and this is going to take some time as well so if it takes a little while don't worry nothing's broken it's just got to update all of the packages that are already installed all right so once that's complete the next thing we want to do is install postgres and so to install any package you do sudo apt install and then the name of the package so there's going to be two packages we want postgresql as well as postgresql dash contrib and then we can pass in the dash y flag so that we don't get any prompts once again all right so now that we have postgres let's try to connect to it so if i type in psql let's see what happens oh and so you know when we do psql it says it could not connect and that's because there isn't a role called ubuntu defined on postgres so let me quickly explain what that means uh when you try to connect to a postgres database on the the same local machine what happens is by default it makes use of something called peer authentication so it taps into the kernel and figures out what user you're logged in as and tries to connect to the database into postgres using that same username so we're logged in as ubuntu so if you do who am i it's going to tell you the username of the user that you're logged in as and it's also propended at the beginning of the prompt and so it's going to grab this and it's going to try to log into the postgres database using that user now this is a fresh install for a postgres there's no user called ubuntu installed on it postgres by default installs one specific user and that is a user called postgres and not only that uh for authentication uh like i said it uses something called peer authentication uh and so it's once again going to tap into the kernel and use that user to log in to postgres and so what it actually is done when we installed postgres it also created a user on our linux machine on ubuntu so if i type in sudo cat slash etc wd this is going to list all the users that are installed on our local machine not on postgres but on our actual linux operating system right and so you could see the ubuntu user that you know was installed when we set it up within ec2 and it also created a postgres user so we can log into this postgres user so if you type in sudo dash i u and then the user that you want to switch to that's going to be called postgres you're going to see that we've switched to the postgres user and the prompt changes and if i type in who am i it's going to tell us that we are now postgres and so if i type in psql we can now log into our postgres database and we log into a specific database called postgres as well and if we do a slash d whoops not slash d uh l it's going to list out all the databases and so you're always going to have the same three databases that are uh configured by default on a fresh install we're gonna have one called postgres we're gonna have one called template zero and one called template one now the way we're gonna set up everything including our application is uh everything's gonna run through our ubuntu user so our ubuntu user is going to be is going to be the one that ultimately starts our express application and the ubuntu user is going to be the one that's going to try and connect to the database so i want to create a user that's also called ubuntu within the postgres database so that um so that we can log in and connect to it uh so let's exit out of postgres and you can do a slash queue and if we take a look at the documentation uh there's a command called create user dash dash and make sure you're still logged in as the postgres user because if we move back to the ubuntu user he obviously doesn't have access to the postgres database so he can't create a new user for himself and so we'll do create user and then dash dash interactive so this will give us a whole bunch of prompts uh when it comes to setting up this new user uh so we have to give it a name for the user and once again i'm using the term user but within postgres it's called role so i'm going to call this ubuntu to match the name of our actual operating system user uh then do we wanna make him a super user uh and so i'm gonna make him a super user just for simplicity's sake uh this will give him full uh you know unlimited privileges it's almost like being a root user within linux so when you're a super user you know you can create uh delete modify all users you can create modify delete databases you can do anything uh so i'm gonna hit yes however if you wanted to be uh if you wanted to do this really the proper way you probably don't want to make him a super user you probably want to make him a regular user and make sure that you only give him access to the exact uh databases that he needs access to just from a security perspective but i don't want this video to you know go on for too long so just for simplicity's sake just make him a super user and uh let's log back in by typing in psql and if you do a slash du we should see that we should now have two users installed we've got the postgres user and we've got the ubuntu user and you can see he's a super user so he can uh you know create roles uh as well as databases all right so let's exit out of this and let's exit out of the postgres user so if you just type in exit it's going to move us back to the ubuntu user and we can verify that by looking right here but also by typing in who am i and so now confirming we are the ubuntu user and let's try to log into postgres now so if i type in psql let's see what happens looks like we still get an error right but the error is different this time the error says that it could not connect to a database named ubuntu right and so what happens is by default when you just type in psq and you try to connect to postgres uh it postgres automatically tries to uh log you into a database that matches the name of the user so since my username is ubuntu uh it's going to try to log me into a database called ubuntu however there's no database called ubuntu remember there's only these three databases so there's a couple of things we can do we can create a you know a blank database called ubuntu uh when we're logged in as the postgres user obviously because we need access to postgres um but that's a little messy like you know why go through the hassle of creating an empty database just so that we can conveniently log into postgres instead what we can do is we can just type in psql pass in the d flag which is going to allow us to specify a database and if you're wondering where i'm getting all of these extra flags to add to this command you can just do a dash dash help and that's going to show you all the different flags that we can pass in so if you do dash d that's going to tell you what database you want to connect to and so we can do psql-d and then pass in the name of a database that we know exists for effect and we know there's a database called postgres and there you go we're logged in and we're logged in as the ubuntu user and if you want to see the connection information you can type in slash con info i think and this is going to let you know your connected database called postgres as user ubuntu and so on all right so let's exit out of that and i took and you'll notice that there's no actual password that's being asked of us when we log in and that's because of that peer authentication that i mentioned you know when we try to log into our postgres database it's going to tap into the kernel and try to log you in as the user because if you're logged in as that user then you should be able to have access to that user within the postgres database because they match and if you go to slash etsy and then i think postgres and then whatever version that you have installed and do an ls go to main there's a config file where if you don't like that peer authentication behavior you can modify that in this pg underscore hba.conf i'm just going to do a cat so that's going to print out the contents of this file and you're going to need pseudo privilege and you'll see that for local connections uh it uses peer authentication under the method all right so if you don't like that behavior and if you always want to be prompted for a password you can change that to md5 so md5 will prompt you for a password however don't worry about this when we actually go to deploy our application it's not going to be using a local connection it's going to think it's connecting from a different machine or a different ip address because it's coming you know from our express server so it's not actually going to use local authentication and it's going to actually require a password uh so you don't really need to change anything for that but i just did want to but i did want to point out to you guys how to change this if you didn't like that behavior now our user still does not have a password associated with now our user the ubuntu user within postgres still does not have a password so let's go ahead and create a password for the ubuntu user within postgres uh so we're gonna do psql and uh remember we have to pass in the name of a database that exists so that we can actually connect and the command to create or change a password is alter user then the name of the user then the password field and then we pass in the password that we want to use so i'm going to do alter user then the name of the user is going to be ubuntu and then password we're going to change the password field and i'm going to set this to be password123 not very safe but let's keep it simple okay and if you see ultra roll that means it was successful and we can exit out of that so now that we've got postgres installed the next thing that we have to do is we have to recreate our database schema and that includes you know creating the yelp database or the database named yelp um creating the restaurants table creating the reviews table and so you're probably thinking oh man you know did i write down all the commands needed to do that well um i actually don't have the commands saved that that was necessary to create those databases but postgres has a tool called pgdump where you can dump the database schema and then you can import it in another instance of postgres so that you know you can recreate an entire database schema with just a couple commands and not only that we can uh we can dump not only the database schema we can also dump the data within your database as well so if you want to move over all of the restaurants that we have in our local dev server we can move that into our production server as well and that's actually what we're going to do just so that we already have some pre-populated data so now let's move back to our our local dev server so you want to open up the terminal right make sure you're connected to the terminal of your local machine and not to the ubuntu server okay and so go ahead and navigate to you know any directory that you want we're going to have to save a file but the command that we want to run is called pg dump so this is going to dump the contents of either all of your databases or a specific database and so i've provided this command and let me just quickly go over what all of the different flags are so here i pass in the dash u flag and this is going to be the user that we want to log in as so in my local dev server i just have postgres user i didn't create any of the users so we have to specify the specific user we want to log in as or else it's going to try to log in as whatever user we're logged in on the windows machine because it also does pure authentication then the f f is going to say um you know it's going to specify the specific file we want to store this dump into so this is going to create a yelp file called yelp.pgsql and it's going to get stored in this directory and it's going to store the contents of the postgres dump and then pass in the dash c flag which is going to make sure it includes a few extra includes the extra create database command within the schema uh if you don't pass this it doesn't provide that however i found that it doesn't really help we'll still have to manually create the database anyways so you can probably leave that off uh and then the final thing that we have to pass in is the name of the database that we want to dump now this is technically optional um however i don't want to dump all of the databases that i have on my local dev server i've got a lot of different databases so i think it's good to just dump the specific database that you're interested in so i'm gonna dump the database called yelp and if you guys decided to use a different name then make sure to update that with whatever specific name that you use i'm gonna do pg underscore dump dash u that's a capital u and then dash f i'll call this yelp.pgsql dash capital c and then yelp and it's going to ask me for the password to connect so i'm going to pass that in and then after that's done it should create a file so if i uh if you're on a windows you can type in dir if you're on linux type in ls and you can see at the bottom i've got my yelp.pgsql file so now i need to take this file and copy it over to my production server uh and so there's a command called scp and that's going to copy a file to the production server and this could be a little bit of a long command so we do scp and remember our authentication method for sshing uh is using that certificate so we're gonna have to do the same thing that we did for ssh for scp so we passed in the dash i flag and we pass in the path to that yelp.pen file and i think it was in downloads and then yelp.pem that's right and keep in mind right when it comes to specific paths in linux it's going to be a forward slash but i'm on window so it's going to be backslash okay so now the next two arguments that we need to pass is uh the source file and the destination okay so the source file is going to be this yelp.pgsql so i'm going to pass in yelp.pgsql and then the second argument is going to be where do i want to copy it to so this is going to be copied to a remote machine so we have to pick the user of the the username that we want to log in to that machine as so we always log in as ubuntu and then we do at and then we need to grab the ip address of that of that machine and i already forgot what it was but we can always go to aws and grab that info and this is the ip right here okay then you do colon and then now we have to pass in the directory we want to copy the file over to so i'm going to copy it to uh slash home slash ubuntu keep in mind this isn't a actual requirement you can pass it into any directory that you want to all right and then we'll get the same prompt like we normally do and just hit yes okay and if it was successful you should see this uh this line that looks pretty similar to this uh where it says 100 which means you know 100 of the file got copied over uh and everything should be good to go so if we go back to our ssh session where we've logged into the production server go to that directory so slash home slash ubuntu and a shortcut to getting to that specific directory you can also do cd and then pass in the little tilde and that's going to take you to your home directory so if i do ls we can now see the yelp.pgsql file all right so we've got this file in there now let's import it into our database and the first thing that we have to do is first of all we have to manually create the yelp database i was trying to find a way for this file to automatically create the database for for us as well but it just never seemed to work so we'll we'll have to do one thing manually so let's do psql and then pass in you know the postgres database just so we can log into it and uh to create a database we can do create database and then we'll call it yelp and we can do a slash l and we can now see that we have a empty yelp database we'll exit out of that and now the command to import a database is going to be this right here you do psql then the name of the database and then you do this less than sign and then you pass in the path towards this yelp.pgsql file so psql yelp and then it's going to be in slash home slash ubuntu then yelp.pgsql and you should see a whole bunch of output if you scroll up you may see an error or two but uh it should not cause any issues there's just some kind of random thing with this locale name which it's not going to impact anything as long as everything else gets set uh you should be okay but just in case uh let's uh go back into postgres and now we can actually connect directly into our yelp database and we can do a slash d to see all the relations and now we've got our restaurants and our reviews and if we do a select star from restaurants we should see that all of the restaurants from our local dev server got copied over yep and there you go so it looks like the import of the database went just fine all right so that's about all we have to do when it comes to postgres we're actually done with the postgres installation we've set it up so that it will work just fine it's running on the default port of 5432 and that's what we're going to use for our application if you did need to change that you know just feel free to just google it it's not a hard thing to do but i see no reason to have to change that so we're just going to run with the default port all right so now that postgres is installed the next step is going to be to copy our application code onto our production server and so first we need to decide where we want to store our code this is something that doesn't really matter too much just pick a location so what i'm going to do is i'm going to create a folder called apps within my home directory so if you want to figure out where you are within the linux cli you can just type in pwd so i'm in slash home slash ubuntu and so i'm going to type in mkdir to create a new file and i'm going to call it oh sorry create a new directory we'll call it apps and then i'm going to move into that directory by typing cd and then apps right and if you do a pwd you can see that we're now in the home slash ubuntu apps and then within apps i'm going to create a new folder that's going to contain all of our application code so i'm going to do a and then what did i use in the example i called it yelp dash app so i'll do the same thing right so now we have a folder called yelp dash app and i'm going to move into that folder and now uh we're going to copy our code from our repo so let's go back to the repo i'm going to just click that button right there and we can copy the codes if you select this drop down select https and just copy it so now that's copied into our copy buffer i think that's what it's called um and now we can do a git clone let me move on down and we just type in git clone paste the url that was provided and then what we want to do is do a space and then a dot so that's going to copy it to this directory all right and so now if i do an ls we should see the readme uh the client folder and the server folder so we've got our code copied over all right so now that we've got our code copied over um we won't actually be able to do anything with our code because we don't have node installed so logically the next step is going to be installing node and to install node on ubuntu or linux it's going to be a little bit different than when we installed it on mac or windows so let's go to the node website i'm going to show you guys um where to go to actually get these steps for that so if we go and then select other downloads under the current and we want to scroll down to installing node.js via a package manager right and package manager is that apt command that i mentioned earlier that we used to update our packages and then we want to select debian and ubuntu based linux admin uh and here on for debian and ubuntu we have to click on this link and it's going to take us to this github file and so here it's going to show us how to install node on various operating systems like ubuntu so let's go to just keep scrolling down and we're going to install node.js version 14 because that's the latest and on ubuntu there's only two commands that you need to run this command and then this command so we can just copy these directly and we can take this and copy that and once this command is run we'll have node installed all right and just to make sure our installation was successful just type in node version and it should tell you what version of node is installed and keep in mind guys you might have a later or a more recent version of node don't worry that's not going to be an issue okay now that we have node let's go to our yelp app folder all right and this is where all of our code is and let's go to our server directory if i do an ls you'll notice that uh we've got most of the files that we have that were that we had in our uh in our development server or in our you know on our local machine however there's one thing that's missing that's the node modules folder and that's because when i go when i committed all of my code to github i used a dot git ignore file to make sure that we excluded node modules and i guess i don't have it listed here but i also excluded the dot env file so we don't have any of the node modules and that's that's um that's the way you do it because there's no reason in copying over all of the node modules instead what you want to do is in our production server we can just do an npm install and it's going to install all of the node packages that we need there's no need to have to commit all of those into git it would just take an unnecessary amount of time all right so we've got all of those installed and so at this point we can actually text test to see if this works so if i do a node uh and then server.js you should see that you know we've got the console.log it looks like our application's already working fine however keep in mind that in a production environment we never want to run node directly you'll never actually see this in production instead we're going to use a process manager and this is a process manager called pm2 if you want to take a look at the documentation for that just search for pm2 this is the documentation for it but to install pm2 all you have to do is npm install pm2 and then you want to pass in the g flag because we're going to be installing it globally so let's stop this i'm going to do control c and i'm going to do an npm install uh what was it called again pm2-g so pm2 and then dash g and so pm2 is going to be responsible for making sure our our express app is working properly it's going to be responsible for making sure that if our node app uh crashes it's going to restart it for us and it's also going to make sure that you know when our ubuntu server reloads for some reason whether there's a power outage or we needed to upgrade it it automatically starts our application when it reboots and you'll see that i got an error and that's because the command i ran because we're using the g flag we're going to need to do sudo at the beginning we need root privileges to do that all right so now that's installed uh we can use pm2 now uh so let's um i'm gonna go back to my home directory uh and i didn't actually need to change to my home directory but now to start our application our node application using pm2 all you have to do is type in pm2 start and then you need to provide it the path to that server.js file which is what we need to run to start our back end so i'm going to pass in the path so it's going to be um at apps yelp app then it's going to be under the server directory and then it's going to be under server.js all right and so it's going to print out a whole bunch of information and also gives us this nice little output on the current status so you can see it created a process for us with an id of zero it gave it a name of server uh you can see right now it's using no cpu pretty much and only 28.7 uh megabits of memory all right and so that's all you technically need to do to get your back end started however there's a few other commands i want to show you guys with regards to pm2 so if you want to stop a process uh you can do pm2 stop and then you can pass in either the name or the id so i'm just going to give it the id of zero right and so now you can see that it's been stopped and if you ever want to check the status of your processes you can do pm2 status and it's going to print out that same information and keep in mind guys you can spin up as many processes as you want so if you wanted you know 12 different uh you know node backends you can do that with pm2 you just do pm2 start and then you know wherever the first server.js file is or wherever your code is hosted uh then you do pm2 start again with where and point it towards the other project code right so in this example we're only we only have one back end so we're just going to have one process but i just want to make sure you guys understand that you know you can spin up as many processes as you want uh if we want to delete a process we can do pm2 delete and then the id again and there you go it's deleted we've got nothing else but let's go ahead and create that same process again so pm to start and then we gotta pass in the path to that server.js file and this time i'm gonna pass in a new flag i'm gonna pass in the name flag and this is going to allow us to give it a more suitable name for our process because server i don't know what that is so we can call this yelp app and so now when it starts the process it gives it a more meaningful name now this is great and all however if we reboot our ubuntu server you'll see that pm2 will not automatically start our app for us which i mean if our server accidentally reboots for whatever reason we would ideally want it to power up our application as the server comes back online so let's configure it to do that it's really simple and i've got the configs or the commands needed right here in this readme and so all we have to do is do a pm2 start i think it's pm2 startup yep pm2 startup and it's going to print out this command right here so we have to take this command let me make this bigger i hate it when it wraps okay and so i'm just going to copy that and paste it and there you go now pm2 status uh you'll see that you know we've got our application running and we want to take a snapshot of all of the processes that we want uh to get started up on startup so what you do is you enable all of the apps that you want that that you want powered on during boot up and in this case we just have one app we just have this one so as long as it's powered up we then do a pm2 save and it's going to remember all of the processes that are currently powered on and so when we reload our ubuntu server it should automatically power on all of these processes or in this case just this one process and so just for demonstration purposes i'm just going to reboot it and we'll just verify that it's actually doing what we told it to do all right after it's finished rebooting let's connect back to our server and we want to do a pm2 status and we can see that the process was powered up by pm2 and there you go guys so that's how you ensure that your node backend gets powered up automatically after reboot and so that's all we need to do with regards to pm2 and that's all we need to do uh with regards to our back end the next thing that we want to do is prepare our front end code for uh deployment uh and so we copied the source code however when we actually want to deploy a react app we have to run an npm run build to build our code and create the finalized uh html css in javascript files if that'll have been condensed and minified and whatnot uh so let's go to our application folder so if we go to cd apps and then yelp app then we want to go into client so first things first remember the the node modules folder doesn't get copied over into git so we want to do an npm install so we can install all of our necessary dependencies and once that's done we want to run an npm run build okay and once that's complete if you do an ls you'll see that it's created a new build folder with all of our finalized code if you go into build you'll see a couple of different files you'll see all your assets and then you'll also see the final index.html file so this is the file that we want our nginx web server to serve all of our users and so keep in mind this is the path to that file you know you can move uh this finalized code uh anywhere onto you know on this machine you don't have to keep it here i'm just a little lazy so i'm just going to keep it here and just point the nginx configs to this specific path but that's all we have to do for the front end code uh the next step is going to be installing nginx all right so let's install nginx now and we can do that with the sudo apt install nginx and uh once nginx has finished installing the next thing we want to do is make sure that nginx is configured to be powered on automatically whenever the server reboots and we can do that with a sudo system ctl enable nginx and so we'll paste that in and now to verify that actually worked you can do a system ctl status nginx and in this output there's a few things you want to look for so it's letting us know that it's currently running and we want to make sure that it's enabled so that's what that last command did it set it up for enabled and whenever it's enabled that means that whenever this machine gets reloaded and powers on it's automatically going to bring this to bring our nginx server back online all right so now to actually configure and set up our nginx server web server we want to navigate to the slash etsy slash nginx directory here you'll see a couple of different things and the main folder that work that we're concerned with is going to be the sites available directory and i want to make sure you guys don't confuse this with sites enabled they sound very similar but they are two very different folders you want to make sure you go under sites available so let's go under there and if i do an ls you'll see that we have a file called default now nginx is a really feature-rich web server and one of the great things that nginx can do is it can host multiple websites multiple web apps all within one machine so if you have 10 different projects 20 different projects nginx can be configured to host all of those applications and the way it does that is by using something that's that it refers to as server blocks so you can think of a server block as uh the config associated with one specific website or one specific web app it comes with a default server block called default so um traffic any you know http request that gets sent to this nginx server is going to get processed by the default server block and we can actually see this in action so if we go to the ip address of our machine and so go back to aws and we'll grab the ip address and paste it in there you'll actually see this fail and the reason it fails right now is because aws provides us with a built-in firewall that it right now is not configured to allow http traffic so we need to quickly configure that um and this is something we'll have to do anyway so we might as well knock it out now uh and so let me quickly just show you what i just did there uh go back to instances select your instance and then under security groups select the launch wizard one uh yours might be called something different it'll be like launch wizard one or two or three depending on how many ec2 instances you have but this is the default security group that gets created for this specific ec2 instance and we want to modify this so let's select the group id and we want to modify the inbound rules so make sure that's selected and then hit edit inbound rules and you'll see right now there's just one rule and it's the set to allow ssh which is port 22 from any ip address that is what allows us to connect to the box but the we do need to add some extra traffic or extra rules so we want to allow http traffic uh which is port 80 by default and we want to allow it from any ip address and then we also want to allow https which is port 443 and htcps is just a secure version of http and we want to allow this from all ip addresses so let's save that and now we refresh the paste you could see this simple html file that gets served by nginx so this is just letting us know that nginx was installed properly um but that's all being handled by the default server block and uh what i want to do is let's take a look at the server block uh the default server block and i'll explain uh a few things on how it actually works and so there's a lot of there's a lot of config well there actually isn't a lot of configs there's just a lot of comments that don't do anything but they're just there to let you know you know if you need to make any modifications and things like that uh so a server block always starts out with the word server and then an opening and a closing curly brace of the closing curly braces down here uh so what we want to do is we want to tell it what um what port to listen on so for port 80 which is the default http port uh it's going to be listening and then you know for ipv6 it's going to do the same thing it's going to be listening on port 80 so it can handle ipv4 and ipv6 and since this is the default server block it also has this extra flag or this extra option called default underscore server and so basically if you get an http request on this nginx server and it doesn't match any other server block it'll default to this one so that's what makes it the default server block now this route line is going to tell the nginx server what html file we should return to the client so here there's a file under slash var www.html uh and that file in this location is what's being served right here that says welcome to nginx and uh we can actually take a look at it real quick so you go to cd slash bar uh slash ww and then what was it html uh so under there we've got a html file right here and we can do a cat of that file and you can see the html for that so you know it says welcome to nginx so we know that this is the file that's being served um but back to the rest of the configs uh don't worry too much about this line this is just saying the list of files that it's going to look for in this directory for it to serve and so you know this file is called uh what was it called index dot nginx debian.html and so here you can see it's in there so it can serve that file this is just providing a list of different files that it'll look for within that directory but normally it's just going to serve a file called index.html and if you recall when we deployed our react app it did create an index.html file so as long as we have index.html in this list we should be okay the next is going the next line is server underscore name so this is going to be the name of uh the domain names of the applications you want to host so uh if you purchased a domain name um you would put it here so like let's say if we wanted to create our own google and we owned the you know www.google.com we would put www.google.com here and that's how nginx knows what request is meant to go to what application and that's how it actually hosts multiple applications on one web server it looks for the domain name in the http request right now since this is the default server block it just has an underscore saying it you know it can basically serve that html file for any domain name that reaches this nginx server then we have this location block so this is uh just saying that anything for the root url uh it's going to try and uh serve a file and if it can't it's just going to deploy it's going to send back a 404. so if i try to go to you know slash test or something it should send a 404 so that's what that line is doing right there and then that's about it everything else is commented out so based off of this it's pretty easy uh to figure out what kind of changes we need to make to serve our react application and so let's go ahead and do that but we got to go back to slash etsy nginx sites available and we want to create a new file and we can call this file anything we want however it makes sense to name this file the same name as the domain that you've purchased for your application and i want to show you guys if i go to namesheep uh this is where i purchase my domain name and uh let me log in real quick where is it account dashboard and i've purchased this domain right here i don't know if you guys it's a little small but it's called sanjeev.xyz just something that was just really cheap uh and so i'm going to call this uh the domain name associated with this application that i'm deploying is going to be called sanjeev.xyz um if you purchase the domain name uh it's going to be something else obviously and so i'm going to create a file and i'm going to name it whatever my domain name is so cng.xcyx but once again if you have a different domain name then name it that right it just makes sense to name the file after the domain name just so that you know if you do end up you know hosting multiple applications it's pretty easy to tell which file is associated with which application based off the domain name and so instead of creating in a blank or empty file i'm actually going to copy the default server block because you know 70 of the configs are already there so there's no need to rewrite all of that ourselves and so i'm going to do a cp the cp command is what allows us to copy and we want to copy the default file to a file called sanjeev.xyz and we need sudo and now if i do an ls i have sanjeev.xyz all right so now let's go in and let's change the or let's go ahead and make the changes that we need for that file and so i like to use a uh the text editor called vi if you like using nano feel free to use whichever one you want i'm not going to go over how to use that vi or either the text editors because that would just take too long just google around if you're new to linux it's not too difficult all right so you know once again this looks fairly similar uh to you know what we saw in the default server black well it's exactly the same because we copied it but i'm going to delete all the comments because it just makes things look a little messy and a little more complex than it needs to be all right and so the changes we need to make is uh first things first uh i'm not going to make this the default server block i mean we could right because right now we're only hosting one application so you could um but if you did want to host more than one application you didn't want this to be the default server block then you would want to remove these two options right here and we want to do the same thing for ipv6 okay and so the next thing we want to do is we want to uh we want to pass in the location of our react uh build i think it's called the build folder and so i don't remember exactly where it was but i have it inside this readme um it's where it's that extra folder that was created when we ran an mpm run build uh and so let's go back here and uh it's going to be under home slash ubuntu apps uh yelp app dash client slash build so we can just copy this actually and i'm just gonna delete that line and put it in spacing doesn't technically matter but i like to keep things nice uh and pretty and we want to make sure that it has index.html so it'll look for that file then the next thing that we want to do is we want to make sure we pass in the domain names under server name and so my domain name is sanjeev.xyz and we also want to pass in the www form of that and finally you know if you don't have a domain name that's okay you can always just put in the actual ip address of your machine and so this will allow us to process requests that just go directly to the ip of the server without a specific domain name so if we go back to instances we'll copy this so 54.173 dot eighteen dot one one five all right and um if you actually take a look at this uh readme you'll see the final configs that we need for everything however you know when i go over this section i don't actually want to write out all of these things right now because i want to show you what they actually do so instead i'm going to delete the location block right here and i'll show you what happens when we don't have that right so let's save this now that that's saved we want to actually want to actually deploy those configs so we have to enable the new site that we configured and so we can just copy this line directly however keep in mind if you named your site different something different then you want to update that accordingly and then finally we want to do a pseudo system ctl restart nginx so that the changes can take effect and so now if i go back to here remove the slash test we just want to go directly to the ip address you can see that we get our application now the application doesn't fully work because the back end hasn't been set up uh or nginx hasn't been set up to process the back end but we can see it now works all right so now that we've got the base nginx config set i want to go back to the slide deck that i covered a little bit earlier just to kind of reiterate what we want nginx to do uh and so you know this is what it was hopefully it's big enough for you guys i don't feel like going into full screen um but what we wanted to do is when we get just get the root url just just the slash after the domain name we want nginx to forward this to react and then if we go down to the next slide if you we get any request that goes to the url of slash api we want to forward that to the express api so let's configure that and i'll show you guys how that's done and so what i'm going to do is i'm going to go back to the config file we want to go back into that sanjeev.xyz and before you do anything make sure you do a pseudo beforehand and at this point what we can do is just copy uh the configs from here so this config right here is basically saying that any uh request to this nginx server with a url of slash api you know just like i said here anything with a slash api is going to get proxied so we're going to proxy this to http colon slash local host colon 3000 and that's where our back end's running so that's how we forward these api requests to our back end and then still allow our front end request to go directly to our react app uh and so right now i'm not going to explain what this does yet this is it's kind of doing the same thing right so any request with a slash url um it just has this command um but we'll come back to that in a second i want to set up the back end so that we can actually hit our back end and uh we'll just copy this for now i don't really feel like explaining all of these other ones i mean you know feel free to google that but this is for the most part just a copy and pasting that most people do anyways and i'll paste that in there and it got a little mangled um let's make it a little prettier right and uh we can then exit out of that and we can do a system ctl we'll have to do a pseudo system ctl restart nginx uh and so now it should be able to hit our back end um but it's still not going well uh actually no this is the one we want right here so if i hit refresh it still doesn't work but that's just because our back end uh can't reach our database because we haven't set up our environment variables however before we move on uh there's one minor issue so if we go to actually let's take a look at our development server so if we click on one of these links right it's going to take us to a url called slash restaurants and then the restaurant number or the id and then takes us to the detailed page now in our application if i do the same thing and that's because right now by default if you take a look at the configs from nginx uh we're you know we serve the index.html so it'll only address things that get sent to the slash url just these flash right so it can only process anything that goes to slash and that's why that works fine and then anything to slash api uh will get properly sent to our backend however it doesn't have any config for you know slash restaurants uh and then you know the id of the restaurant there's we haven't provided a config and this is because uh you know react is a single page application uh and so we want technically all requests to get sent to our react app and our react app will handle the routing and so that's what that second location uh config right here is um this line right here is basically saying that uh you know if we can't if we get a request for any other path we want to just send it back to the index.html and let react handle the routing for that so this is something that's specific to react that we actually have to add so let's uh go back into that file and let's add the config for that and we'll do a pseudo system ctl restart nginx and i think now if we do a refresh restaurant slash 2 right we don't get a 404 error nothing loads up onto our screen but that's just because um our our database is is not set up properly our backend can't reach our database but we're not getting a 404 so we know that that extra config that we just added is now working and it's it's passing that request off to react and react can handle the routing but that's all we need to do from an nginx perspective the next thing i want to cover is how to set up our domain name or how to purchase a domain name because i guess that's something that's good to know i don't know if all of you guys know how to do that but i'll kind of walk you through how that's done now to get a domain name this is something that you have to purchase and you have to go to a domain registrar and there's a lot of different domain registrars and there's a lot of ones that you guys are already probably familiar with um you know godaddy is a really popular one just because they slam you with so many commercials so if you wanted to purchase a domain name you can go there you can purchase it from google as well and there's a lot of other domain registrars what i like to use is the one called namecheap so namecheap is the one that i use and basically it's pretty simple process all you do is just think of a name that you want right whatever domain name you want and just search for it so if you want let's say i wanted google.com right you can search for that and it's going to tell us that it is not available right because obviously google owns it um but we can try something else like uh you know if i do sanjeev123hello.com that's obviously going to be available no one wants it and i can purchase it for eight dollars and 88 cents per year uh you know more popular names are gonna cost more um but you have a lot of other options that can make things a little bit cheaper so like if you get like a uh dot dev or something or a dot ai well actually that's more fifty eight dollars a year yeah it's more expensive for some reason i don't know why it is um but you can get a dot org so just search whatever domain that that you want and then just add it uh to your um to your cart and then just purchase it it's a pretty straightforward process like buying anything else you just have to make sure it's available but that's all you have to do for your domain name the one last thing that you have to do with regards to your domain name is set up dns so anytime a user sends traffic to your domain name you have to go to your domain registrar and tell them to forward the request to the ip address of your server uh and so you know my server if i take a look at the ip it's this ip i need to tell namesjeep hey for the domain that i purchased i need you to send that request to this ip address right here and the process on how to configure this is going to be different for every single domain registrar so i can show you how to do it with namecheap but i can't show you how to do it with uh you know with you know google or godaddy because they all have a different ui so let me quickly log you in log in and i'll show you guys how to set it up you'll see that the configs are going to be fairly similar across all of them you may just have to press a few different buttons but there's basically two different dns entries that we need to set up so let me log in where's my account go to dashboard i'm going to select the specific domain which is sanjeev.xyz and we want to go to advanced dns and there's two rules that we have to put in so we have to create two different a records and so you know you can just select it there's a few different types of records we want a records and then for under host we want one to be the at simple and then the other one to be www and they're under value for both of them we want to put the ip address of our ec2 server so i'm going to grab this what happened here i'll just copy it right here all right and then so this is just going to default to 30 minutes for the first one and then automatic for the second one i usually just leave whatever uh the defaults are and then i'll hit save all changes and so at this point um the changes do take a certain amount of time to take effect uh sometimes i see it uh almost instantly but they do report that it could take up to like 24 48 hours for these changes to take effect but uh we can we can test this i'm just gonna go to sanjeev dot x y z and let's see what happens and look at that so now when you go to sanjeev.xyz what happens is that request will go to their dns server the dns server is going to then send the request to this ip which gets sent to our ec2 instance which then goes to our nginx configs and our nginx looks for a server block that matches that and if we do a cat ing dot xyz our nginx sees that we have a server block that's going to handle requests to sanjeev.xyz as well as www.sng.xyz and then it's going to serve that index.html file so that's all that's really happening and that's all we have to do from a domain name and a dns perspective all right so now let's set up our environment variables and uh like i said before when we checked in our code into our github repository we have to make sure that we don't check in our emv file so if we go into our server you can see there's no dot env file because we don't want to expose our credentials into our github repo and in our production server we're not going to import our environment variables in the same way we did on our development server instead what we're going to do is we're going to set it for our specific user or globally across the entire linux operating system so let me walk you through how to set an environment variable it's pretty easy and the way we set an environment variable is by typing the command export and then we pass in the key and value so if we want to create a environment variable called test and we want to set that equal to a certain value of let's say hello right we can hit enter and so at this point that environment variable is set and we can do a print nv and that's going to print out all of our environment variables and you'll see there's actually quite a few environment variables let's see if we can find ours and so there you go it's set right there and obviously if you don't want to look through all of those you can always do a pipe grip and then you can search for test but this is going to be case sensitive so i always like to do a dash i and so yeah you can see this environment variable is set now if we want to remove an environment variable we can use the unset command so we can do unset and then we can just type in the name of the variable so i do unset test and now if i do that print nv command again you'll see it's not there and it's been removed right and if we go back to our code real quick you'll see in our environment file we've got quite a few environment variables right we've got one two three four five six we have six different environment variables uh it would be a little bit of a pain to have to kind of uh you know write each one out um individually like we'd have to do you know export what was it called uh you know port equals and then uh you know 3001 right and then we'd have to do export pg user equals postgres and we got to make sure we wrap it in quotes all right and you can start to see that this is kind of a bit cumbersome right um because we actually don't have that many environment variables in our project but uh you know other applications could have a ton of environment variables and to have to go in manually and type these out is a little bit cumbersome and so instead what we can do is we can create a file and then we can kind of import that file and then load up all the environment variables that are declared in that file and i'll show you guys how to do that so i'm going to go to our home directory and i'm going to create a file called env now the location of where i'm putting this file does not matter and the name of the file does not matter you can name whatever you want i'm just gonna name it dot env because why not right it's pretty clear what it is it's used for the only thing i recommend is um if you're gonna store your environment variables in a file do not put it in the same directory as your application code because you don't want to accidentally check it into github for some reason so it's best to store it someplace outside of your application code that's why i'm putting it in my home directory and so i'm just going to do vi and i'm going to call it dot env so that's going to create a file called dot env and what we can do is just we can just take all of these and just paste it into here and there's going to be a couple of changes that we need to make so we got to put the export at the front and we got to wrap it in quotes and we're going to do this for all of them so just bear with me all right and so now what we can do is i can do source and then the path to the file that we just created so it's going to be in the current directory so i can do source.env and now if i do a print nv and i'm just going to grep for anything that starts pg because all of my environment variables that i declared in that file i'll start with pg and uh you know ignore this massive one right here but you can see we got pg port pg password pg user pg database and pg host so all of them got imported you can see that doing it through a file is a lot more convenient so if you need to make a change you know you just go into the file and make that change however there's one other thing that we can do to make this a little bit easier uh and that is i don't like i don't like how we have to uh you know go in add in export and then put the quotations you know wouldn't it be nice for us to be able to just take the environment variable file that we have in our code and just copy and paste it directly into this file and be done with and you know we can do that and it's pretty easy to do that there's only one modification that we have to make and that is first of all let's let's delete all of this and i'm going to go back to our code and i'm just going to copy this directly show you how much easier this method is and now what we can do is we can run this specific command it's going to be set dash o all export semicolon and then source and then the path to the file semicolon and then set plus o all export and what that'll do is that'll take that environment variable file where we don't have the export or the quotations and it'll automatically add that for us and turn them into environment variables so they were already set uh when we ran it previously but um just just trust me that you know this method will also do the same exact thing and it'll make your life a little bit easier because you don't have to go in and change it and you can just copy it directly from your project code now that's great and all and that's this is going to be the method that we use moving forward however there's one issue these environment variables will not persist a reload so if if our machine for some reason reloaded it would essentially crash our application and i'm going to prove that to you guys so if i do a pseudo reboot a machine machine's going to reload give it a minute or two for it to power back on and then we'll log in and i'll show you guys those environment variables will be gone all right so let's log back in now and uh if i do a print nv type grip minus ipg uh you'll see that none of the variables that we had defined before um remain so it looks like after reboot they get removed just like i said and so what we need to do is to make sure that these environment variables get loaded on loaded up upon reboot first of all let's uh go to do an ls minus la if you do just do an ls minus l that's going to print out all the files but it's not going to print out the hidden file so if we do an ls minus la it's going to print out the hidden files and so here there's two files that we can modify to make it so that those environment variables get loaded upon a reboot and the first one is going to be dot profile and the second one is going to be dash dot bash rc both files do something a little bit differently so i recommend you guys read into it but i'm going to use the dot profile file and so i'm going to do a vi profile dot profile and all we want to do is we want to go to the bottom of the file and we want to add that export statement that i gave you a few minutes ago where is it uh it's gonna be this command right here so you remember set dash o all export then you do source provide the path to the environment variable file uh and then this part at the end so we can just copy this and we'll paste it in here now when you do this method uh technically the current terminal uh this this session that we have uh will not have the environment variables if i do a grip minus ipg not there but all we have to do is just exit out and then just reconnect and now if i do a print nv pipe grip minus ipg you can see all of those environment variables are now set all right and you know if we reboot the machine you'll see that they'll persist they'll get loaded up upon every reboot uh the only other thing that i want to cover is make sure that you know when you guys do this make sure you update the password uh and the and the username uh so yeah we actually want to change this so instead of post rest it's gonna be the ubuntu user although uh technically the postgres user does exist on this so we could use that um we would just need to make sure that we have a password defined for it but i'm just going to change this to be um uh to be the ubuntu user so let me go back into the env file and uh change him to ubuntu and once again those changes won't take effect you'll have to i just like to exit out it's just a little bit easier there is a way to do it on the command line but i'm too lazy to figure out what that command was let's do a print nv type grip minus ipg and uh now it's set to ubuntu so we've got our environment variable set uh there's still a few more things that we have to do we're almost done though all right so the next thing that we want to do is we want to set up the firewall on our ubuntu machine and you might be wondering well didn't we do that in aws right if we remember that security group that we modified uh when we clicked on this and now it has those extra rules remember this is the firewall within aws so this determines what traffic is even allowed to our ec2 instance but as an extra layer of security it's also recommended to set up a firewall on our ubuntu server so that if for some reason if maybe you don't deploy this on ec2 you deploy it on like a digital ocean droplet and they don't have firewall services you want to make sure that this box or the the operating system doesn't handle traffic it doesn't need to so you want to make sure that we only allow three types of traffic and it's gonna be the same three types of traffic that we allowed here we want ssh traffic so that we can obviously connect to it we want to allow http traffic as well as https traffic uh and so to work with a firewall you use a service called ufw so if i do a pseudo ufw status you'll see that it's inactive which makes sense that's the default behavior and we want to enable certain uh firewall rules and to do that you do sudo ufw allow uh and then you pass in the rules that you want so if you want to allow ssh all you have to do is just type in ssh they make it really easy for you then we also want to do sudo ufw allow http traffic as well as sudo ufw allow https and there you go the last thing that we have to do is enable it so you do sudo ufw enable and then just hit y so it's enabled and so if you do a pseudo ufw status to see the status now you see it's active and you'll see all the rules that are in place so it's going to allow port 22 and you can see the action is allow and from any ip address there's obviously a lot of configuration changes and customizations that you can do this firewall you can say like oh i only want to allow tcp traffic on port 22 but only from my house's ip address so that no one else can even try to access it right but we're just going to keep things simple and just to go over some of the other lines this is http it's going to allow http traffic it's going gonna allow https and then we have the ipv6 version of those first three so whether it's ipv4 traffic or ipv6 the firewall can handle it all right guys so we're almost done the final step is to set up ssl and if you take a look at our app right now uh you can see that chrome automatically uh declares it as not secure so it's using http which is port 80. it's not secure it's not encrypted and so we don't get that nice uh green lock or padlock and so we'll set up ssl it's very simple us let's encrypt does it all for you there's like two commands that you have to run but once we do that it'll only use https and it's great because even if a user explicitly sends traffic using port 80 with with http it'll automatically redirect it to https so it's going to make our site secure that's how most websites run nowadays anyways but if we go back to the readme there's a step-by-step procedure uh on their website so you can just click on this link and what's great is um it actually configures nginx for us so we did the basic nginx configuration but normally when you generate certificates for ssl uh there's a lot of extra configs that you'd have to put in place within nginx and then to set up the redirects you'd have to do all of that manually um but certbot and let's encrypt these guys have made it so that it automatically configures it for us so here just make sure that you've set up nginx if you're running a different web server like apache you can select that and then select what ubuntu version you're running and all we need to do is we'll start off by installing certbot so we can just copy this line right here all right and then you know we're just going to go down the list just copy the commands and then this is going to be the last command that you need to run the pseudostart bot dash dash nginx it's going to be an interactive prompt and let me clear this so we can get to the top all right so first thing it's going to ask for is your email address so you want to put a valid one all right you have to agree to the terms and then uh this is just asking uh what is it asking you like to send you email no don't send me email all right and what's great is it looks through our nginx configs and it looks for all the domains that we would potentially want to set up ssl for so we've got two domains we've got the cng.xoc and then the www version but if you configured extra server blocks it would also list those out because it parses through all your nginx configs and so you can just go in and select which specific ones you want just by typing in the number um and then you can do a comma and then like two if you want one and two if there's like a fourth and a fifth one you can just add those um if you leave it whoops oh what happened here i'm gonna cancel out of that and we'll run that again and so if i leave this blank it's going to automatically select one and two so i'll just leave it blank and it's going to generate the ssl certificates and it's going to do some verification so it actually wants to make sure that you own both of those domain names so if you haven't already pointed the dns to your server this part would fail so make sure you set up dns before you do this step and then you'll see that it's successful now so if i now go to my react app let's go back to our root and it looks like we've run into an issue uh let's make sure well that shouldn't matter um ufw status that's right so after we set up ssl we can only use our domain name so if i go to sanjeev.xyz you can see that it now takes us to our website and you see that we have the green padlock so the connection secures using https and if i force it to go to http the great part is it'll automatically redirect it to https so now our website is secure um the last thing is it looks like there's still an issue with um accessing the database so let's tackle that in the next step um but actually before we do that i want to quickly just go over what were the config changes that um let's encrypt actually made to nginx so if we go to slash etsy nginx sites available you'll see a decent amount of config changes so if we do a cat sanjeev xyz um so you remember the listen statements on port 80 at the top those are gone um they moved it down here but instead of listening on port 80 remember this is going to be handling https traffic and the default port for that is 443. so this is just saying listen we're going to only listen on um port 443 and then these are the ssl certificates and their locations uh and so uh it uh let's encrypt creates those ssl um certificates it stores them in those locations then we just gotta tell nginx how to reach them and then don't worry too much about the other configs the last thing is i think this is where the redirect happens uh and so it just basically says you know if uh traffic uh gets sent to you know sanjiv.xyz you want to make sure that you redirect it to https version of that and so that's all uh yeah you can see it's listening on port 80. so if you've received any traffic on port 80 redirect it and send it to https on port 443 so those were all the changes in the next section let's tackle why we can't access our database all right so you know if we take a look we can see that um you know we're not loading the restaurant data so it looks like there's an issue with accessing our database and if we go to inspect and then go into network and then just hit refresh um you'll see that we send a api request and we don't really get a response back and so that's our issue with our backend it's most likely because it can access the database an easy way to check the logs if you do a pm2 logs uh it's going to print out any logs that your node app is printing out and you can see that there's a it gives us a little snippet of that and we can see an authentication failure for um for connecting to our database uh and so let's just double check that our environment variables actually got set we do print nv pipe grip minus i pg uh we do see all of them set let's just double check so pg port 5432 password123 and ubuntu yelp localhost and i'm wondering if we have to do a pm2 restart so if we do pm2 status i'm wondering if we have to restart the process so that the environment variables can be you know associated with the node app so if i do pm2 restart zero uh let's see if that works now yep that was it so we just had to do a pm to restart after we made those changes to the environment variable and so now this works let's click on a restaurant looks like it works and here an important thing is when you go to another route let's do a refresh directly to that page just to make sure that nginx is working and it is so there you have it guys we have now successfully deployed a full stack per an application now i do want you guys to keep in mind that there's obviously a lot more things that we can do when it comes to preparing this server there's a lot of security vulnerabilities that we could address i just wanted to cover the basics of how to set up nginx how to set up the backend the front end and a few other things like that but there are certain things like you know i think anyone can directly access the database right now as it is so you would want to make it so that only you know your application can access the database and no one else there's a lot of other things especially from a postgres perspective that you guys can do to make um you know this production environment more secure more hardened uh and less vulnerable to attacks but i think this is a good starting point for you guys and hopefully uh you guys um now have a basic understanding of how to deploy applications and um if you guys in the future need to make any modifications it's just you know a few google searches and you'll see that there's only going to be some minor changes that you'll probably have to make and hopefully you guys enjoyed this video and if you guys like these deployment videos i'm more than happy to do a few other ones you know this one was a full stack app on you know ubuntu machine but if you guys want me to do videos on deploying to like netliffy heroku um github pages uh you know maybe aws s3 um i think a lot of those videos you know those they wouldn't take too long and if you guys think those would be helpful i'm more than happy to make some videos on those topics as well just leave a comment let me know uh and if any topic is popular enough i'll be more than happy to make a video
Info
Channel: Sanjeev Thiyagarajan
Views: 14,041
Rating: undefined out of 5
Keywords: deployment, aws, ubuntu, postgres, express, react, node, programming, tutorial, linux, firewall, full, stack
Id: NjYsXuSBZ5U
Channel Id: undefined
Length: 102min 40sec (6160 seconds)
Published: Tue Oct 20 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.