Easily Deploy Full Stack Node.js Apps on AWS EC2 | Step-by-Step Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I've made this node application that I have running on my local machine it's running on Local Host Port 3000 it's connected to a postgress database that I also have running on my local machine and I need to take this entire web application and host it on the internet so I'm going to do this by running it on an ec2 instance on AWS so I'm going to head over to the AWS console and I'm going to select ec2 and I'm going to select launch instance this is going to let me set up a virtual machine that runs in the cloud where essentially I'll have to install the node runtime I'll install the postgress database and everything else that I need I'll install on this virtual machine and then I'll be able to access it over the internet from anywhere so I'm going to start by giving this a name I'll call this my web app and then next I need to select the base image so this is going to include the operating system that the application is going to run on and the easiest one to get started with is probably Ubuntu cuz it's the most common uh we're just going to leave this as the most recent version 64-bit x86 is great here then we can select the instance type and it defaults to T2 micro and this is great because if you're still in the free tier of AWS still in that first year you won't have to pay if you have one of these running after the free tier ends you'll end up having to pay uh 1.38 cents per hour to run this which is not too bad you can get this Cheaper by purchasing reserved instances but we're just going to leave this as the default setting for now then we're going to come to Keir login and we're going to access this virtual machine over the internet using SSH from our local machine so we need to set up a key so that we can actually connect to the thing over the internet and we're going to create a new key pair right now so I'm going to name this well it's specific to the region I'm running this in California and I'm running this from my MacBook Pro so I just call this California Sam MacBook Pro and then I'll create this keypad and then immediately it will want to download this key pair so I will download that into my downloads folder and I'll deal with that in a moment then we go to network settings where we basically set up the firewall for this virtual machine where we're going to allow traffic to come from so I want to be able to log into the instance that's this SSH stuff right here and I only want to be able to log in from my laptop so I am just going to select my IP address here but if you wanted to be able to log into the instance install software modify code things like that from anywhere you could leave this as 0.0.0.0 but I'm going to select my IP address just to make it a little bit more secure and then we are going to allow https and HTTP traffic from anywhere since this is running a web app we want people to be able to access this thing that's good for the security group but I am going to click edit here to give this a better name so I'm going to call this my web app Security Group uh and I'll probably just use that for the description too just so it's not launch wizard I can scroll down and I could create more rules here if I want wanted to create different TCP rules but we're going to leave this alone right now that's good the default storage is fine we can leave that alone with those settings we can click launch instance and this is going to set up that virtual machine for us then the very next thing we want to do is actually connect to that instance I want to log in from my laptop so that I can start installing software and configuring this virtual machine so I'm going to click connect to instance to get instructions here and I'm going to go to SSH client and it gives me instructions on how to connect over SSH so if I'm on a Mac or a Linux machine this is just going to work if you're on a Windows machine you're probably better off using WSL or at the very least use git bash and things should just work for you there so I'm going to copy this command to connect to the instance and in order to log into that instance I need to use that key that I downloaded which is currently in my downloads folder so I can just run this command from my downloads folder since it's looking for that key here but the first thing I'm going to do is actually move that key so California uh into my SSH folder that I have set up in my home directory here that's where I put all my SSH Keys it's a pretty standard place to put those so I suggest putting it into that folder I can run that command from my SSH folder or I can just run this from anywhere really as long as I specify the full path so do SSH SL that key so we're going to use SSH to log into the remote instance that's this instance right here this is their IP address for the instance that was set up and the default user for the Ubuntu instance is going to be Ubuntu so log in using that username using this key and hopefully this all works so this just saying are you sure you want to connect yes I am and it didn't work right because I missed a step here we're actually supposed to change the permissions of that key just copy and paste that in and then this should work so let's see I'm just going to copy that SSH thing again and this time there we go it connected so you can see my terminal changed I'm actually on Ubuntu and this is the private IP address of that auntu instance so anything I run in here if I run Echo hello this is actually running on the instance that is in California this isn't running on my laptop anymore if I open a new tab on Terminal this is my laptop this is running in my home anything I run here is actually running on that virtual machine one of the first things that you want to do when you set up a virtual machine and I have some snippets on another page here one of the first things you want to do is actually just update and upgrade the packages on the machine to make sure you're using the most recent versions of things and this includes any security patches that might have recently come out and when it asks you to continue just hit enter and this might take a couple of minutes but once it's done you can start configuring everything else on the ec2 instance and one of the last steps here is asking which applications should restart and I'm just going to select all of them so I'm just using the space bar to make sure they're all selected here and then I'll select okay just by hitting enter it will restart those things they'll all will be using the most upto-date versions of all the packages on the system so that was a quick update of everything running on obuntu now I want to start running my application code that's one of the first things I really want to do so I'm going to install node right now because that's how I run a node application I have to install node and then use that to run the JavaScript code but if you're running a different type of application you would just install whatever you need for that runtime so now I can pseudo app install nodejs and now I should have node version 20 yep that's there and I could test this out I could open up a node reppel I could console log hey and that should all work fine like I said this is a complete Linux machine so you can install whatever you need to for your application so for example if you wanted to deploy a bun App instead you could just install that instead of no let's see it needs unzip so I'd have to install maybe a dependency P sudo app install unzip and then I could rerun that command to install bun and now I should have bun installed so I could use bun instead of node if I wanted to oh actually I'll probably have to open up a new B shell but now I do have bun okay so you can really install whatever you want you can run whichever commands you need to we're going to be running a node app but it would be very simple to run a bun app for example so I'm going to clear this out and the next thing I really want to do is get my code that I have for my application and put it onto this ec2 instance so we can actually run it on this instance instead of my laptop so I have my source code over here it's a basic node application I'm using hono node server which is kind of an alternative to express but it's very similar to express one big thing here though is that I'm using typescript instead of JavaScript so I will have to build that into JavaScript but I'll get to that in a moment the first thing I need to do is get all of this source code onto my server and then I can run the code to do that we can use SSH there's a command called SCP that will copy everything and I should do this from my local instance I'm going to stop running it on Local Host and what I would want to do is copy every single file to my remote ec2 instance but instead of using SCP there is a slightly nicer command I have it here and I will share the link to all these Snippets in the video description so what I want to do is use a command called rsync and this is Handy for sending my code files to my ec2 instance because it will only send files that have changed so if I'm in here and I send all my code for the first time it's going to send everything but if I just made a change to app. Ts for example it would only send that if I ran the command again so this is a much nicer command to run uh we're going to exclude node modules we don't want to send that to the server we don't want to send the uh git directory uh we're going to leave out environment variable files but this command will be good to send all the code there's two things I need to to change and they are the SSH details that we used before to connect to the instance so I'm going to specify what my SSH key is right here in this part so it's in my SSH directory this is the file I'm using and then I want to connect to Ubuntu at this address so let's see I'll paste that in here and I'm just using VSS code to edit this a little bit nicer so this command basically says uh we want to send everything in the current directory that's the dot right here this last Line's the important part everything in the current directory to my remote ec2 instance and we're going to put it into a directory on that instance called app that's just in the home directory uh we're going to use the SSH key that's the only thing that allows us to actually connect to the instance and we're going to ignore certain directories and files so before I paste this in here I am just going to double check that I have nothing in the home directory so on my auntu instance there's nothing that exists there right now then I'm inside my application this is where my source code is or my typescript code is and I'm going to run that Ry sync command to send everything from my local machine up to that ec2 instance so it sent all of those files all the typescript files and if I check on my remote instance now I should see that I have an app directory because that's what I specified and if I CD into there I should see that I have all of my code files there so now that those are on my remote instance I want to see that I can run this node application so there's always going to be two steps to this or three I guess if you have to compile your typescript the first thing you need to do is install dependencies so I have node installed which means mpm is my package manager I just need to install those dependencies because they'll install differently on a Linux machine than they will locally on my Mac so I'm going to install those here then once that's done running If This Were A JavaScript application if it were an Express app I might just run node app.js but if it's a typescript project so I have a typescript hono project this could be a nextjs app or any typescript app there's going to be a build step and I can just check the package.json for that so the start script is usually for production and then building happens before I can actually start and this would be identical if I was using a nextjs app so for me the first step is going to be mpm run build and this might take a moment because it has to compile all the typescript into JavaScript and I have a frontend react tap and it's also going to run the build command that app too but once that is finished running I should have a bunch of JavaScript files that I can run with node and now that's finished I should be able to see that I have in my disc directory a bunch of JavaScript files so it's compiled everything into JavaScript which is great so now I should be able to run this with node source index.js and it says module not all right yeah I meant node dis index.js so this is is just the entry point of the application and actually you should probably have a start script that does this for you so I'm going to run mpm start and this is running my server on Port 3000 great okay so this is running now on the auntu instance which means that I should be able to access this over the Internet so I'll show you if we go back into the ec2 dashboard over here this is the instance I have and if I go to networking I can see that it has a public ipv4 address so I can just copy this and put this into the browser and I'm going to specify Port 3,000 so instead of Local Host I now have a remote IP address that anyone could visit but if I hit enter this isn't going to work it's going to lag uh it tells me it's not secure cuz I'm in Brave and it doesn't like that there is an https but even if I continue to the site it still won't work and that's because when I set up the instance so let's go back here to security we set up the security group and this is the firewall for the instance so it's not allowing traffic to come over Port 3000 and you wouldn't want this in an application that you deploy you wouldn't want people to access it over Port 3,000 you wanted them to access it over Port 80 or more likely 443 over https but just to test this out just for the moment I'm going to add a rule I'm going to allow traffic to come over Port 3,000 and since this is just a basic test I'm only going to allow from my IP address but I'm going to save that and then immediately I should be able to see that my node application is running so that's my expense tracker and if I wanted to share this with people I could adjust the security group and allow anyone to visit this and anyone could potentially now visit my web application but if you notice on the homepage and the other pages I will get an error I'll just wait for that to come back up there it is an error has occurred something went wrong it doesn't actually tell me what went wrong if I go back onto the ec2 instance error logs it's giving me these errors here error connection refused it can't connect to Local Host Port 5432 and the reason it's giving me this error is because my node application expects to connect to a postgress database if I go back to the source code and I check my environment variables I have this environment variable to connect to a postgress database running on my local machine and the code is set up to connect to a postgress database but I don't have that database set up in the cloud on the internet on my ec2 instance so the next thing I'm going to do is I'm going to stop this application from running and I'm going to install postgress on this ec2 instance so that my application can actually connect to a database so for that again I'm to go to my Snippets here and I have instructions for both my SQL and postgress and the steps are pretty much the same uh and feel free to use whichever database you want I just happen to be using postgress here so I am going to run this first command to install postgress and yeah I have to confirm that I want to install that then once that's done installing I'm going to start and enable postgress and that will make sure that postgress is always running even if I restart my ec2 instance once this is finished paste in that to start start up postgress and then I'm going to actually access the database here and what I want to do is create a new database called my app I'd call it whatever makes sense for the application I'm going to create a new role called my app roll with this password choose better names better passwords uh but this will be fine for the demo and then I'm going to Grant all privileges on that app to that user so let's paste this in here and create command not found that's not good all right cuz I'm not actually using postgress so I should start using postgress okay and then I can paste in those SQL commands okay great so I now should have that database and that role set up so that's going to mean that for my local instance uh I think actually use the same thing for my Local Host instance my application just needs to know the role the password and the database that it should use and I think I I use the exact same thing here and if I had the SQL to set set up the database the schema ready I could just paste this in now and be done with it but I actually have a migration system in my application so I need to run my mpm run migrate which is going to run those sqls for me but before I can do that I do need to give it that environment variable so I'm going to paste in that environment variable the database URL running on Local Host and then run mpm run migrate so it says the migrations were successful and I could just test that out quickly I'm going to try running psql with that URL to connect to that local database and I should be able to see that my database has a single expenses table that's all I have in this database but the migration is successful that database is set up on the instance so I should now be able to run my web app and everything should work so mpm start and it should run on local hose 3000 actually I need to give it the environment variable first and then run mpm start always got to make sure the environment variable is there uh and now my application hopefully will work so total spent now should be zero if it can connect to the database but something's failed let's see what did I do wrong here and now it's working I guess I just pasted that in wrong before okay so now it is working just tried it again and everything looks good now so I should even be able to create a new expense uh a thing for $10 submit that there it's appearing from the database if I go to the homepage there it is so this is all working working and I have it set up that I can see the SQL statements as they're coming out too so this is all working it's connected to that postgress database and this is now a web application that's ready to start being used one of the big issues is that it's running on Port 3000 and it doesn't have a domain name so now we need to fix those issues but actually before we fix those issues there's one more thing we need to address here and that's that we're currently running this application inside an active terminal so if I was to close this window or just contrl C out of this my entire web application would go down so I need a way of running my node application in the background so that it's always running no matter what I do so to do that I'm going to use system D which is a really common way of running things in the background and the nice thing about systemd is it's going to work on any Linux machine for any application that you want to run it's not specific to node so the first thing I'm going to do is actually create a file to store all the environment variables and that's going to be in/ Etsy slapp Dov so I'm going to create that file there and I'm going to put in the only environment variable that I have right now but this contains some sensitive information so I want to make sure that this is kind of Hidden Away from the rest of my application and the script that runs it so I'm going to put that there and then I'm going to save this file and then I am going to change the permissions on this file so that it can only be read by Ubuntu when it's running this application so I'll run those commands that's good and then we're going to create this system file so this is the actual system D part we create a service file in this location and this file is going to contain the instructions needed to run the node app or any app that you're running so I'm going to copy this code in and then we can modify it as needed this is the description you would change that to be whatever you want to be for your application you can leave this part alone the user is going to be your bunto in this case uh I happen to have put the application in the home directory so that's slome Ubuntu slapp so we're going to leave that alone because we want this to run in that directory then because this is a node app using npm we're going to run mpm start that's going to be the launch script if anything goes wrong if the app crashes or if we restart the server we always want this application to restart so we're going to tell it always restart if anything happens uh we're going to set the node environment to be production point it to that environment variable file where we store the database URL then we have all the error logs and output logs going to CIS log and this is pretty standard this means that the way you access any of the console logs or console errors is in a standard way on the system and this is the identifier I would actually change this to be something more meaningful uh my expense Tracker app it will just make searching through the logs easier later on if you need to um but that's it for this F so we can save this and then we need to run the application as a service so we just run these three lines of code we have to reload because we made a new file and then my app. service is how we're going to reference this particular service so I'm going to paste all three lines of code in there and if everything went to plan I should be able to access Local Host 3000 and see my web app running yeah okay so this app is now always running so if I go back here and refresh I will always be able to see my application no matter if I close that terminal window or do anything else so that's really nice and then if I did make an update to my application for whatever reason let's say I just added uh a route here let's say app.get uh Slash test is going to respond with uh yeah why not hello world uh so I make a small update to my application I would rerun the code to send that to the server so that's the rsync command and it sends that file up and then on the back end I would need to run pseudo system CTL restart app. service and then that would and I didn't call it app. service what did I call it uh my app okay so I'll just restart my app. service and that should now have any updates applied so if I'm here on my auntu instance and I go to slash test I think I called it then that doesn't exist why are you not working I'm an idiot I have to obviously mpm run build because this is typescript code that needs to be compiled and then I would need to restart the service okay let's do that my goodness and now I should be able to pseudo system CTL restart my app. service and now I can't remember if it's API test or if it's slash test there we go okay so now that works and this is probably a good time to mention that all of these steps are obviously very manual there's room for a lot of error there as you've seen and eventually you get to a point where you automate a lot of these tasks but in order to get to that point where you can automate things and scale things well you have to understand the foundational stuff and be able to set up ec2 instances from scratch it might seem very manual at this point but eventually you'll get to a point where you automate a lot of these things the next thing I want to do is is allow this to be accessed over HTTP so I don't need that Port 3000 there and then we'll add a domain name and an SSL certificate first we are going to need a reverse proxy here because we don't want to allow our node application that's running here to allow traffic on Port 80 because that's a privileged port and we also don't want the node application to have to deal with things like SSL certificates and we might not want our application to deal with CES and other HTTP facing things like that so instead we can install a reverse proxy and a really common one that I've used in the past has been engine X but something that I've started using recently that I really like is caddy because it is really really simple to get started with so this is going to be our reverse proxy it's going to be the thing that accepts HTTP requests and then forwards it onto the node application so I'm just going to click on install here and it should have an abunto instruction there we go so I can copy and paste this in here and this will install the caddy web server which will allow connections on Port 80 so while that's installing I'm actually going to go back over to the security group section here and I'm going to edit those rules again to get rid of that custom 3000 rule cuz we're not going to need that anymore we're going to allow HTTP and https over the public internet and that's it so I'll save those rules and then that has installed so I think I should be able to run systemctl start caddy and I need for that and now if I curl Local Host so no Port just local hosts Port 80 it should give me yeah the caddy homepage and if I visit that in a browser so if I get rid of that 3,000 it will give me the standard caddy homepage Okay cool so I don't want that what I want is to forward traffic to my application so I'm going to come down here and I'm going to edit the caddy file so that's SL Etsy caddy caddy file so let's do that and here there's mainly comments a few bits of configuration we don't need most of these though so I'm going to comment that out comment that out and come down to this reverse proxy section which I'm going to uncomment and I need to go to the end here and change port 8080 to 3,000 and all this is going to do is accept traffic on Port 80 and forward that traffic to the application running on Local Host 3000 so if I save this now and then restart caddy so restart I should should now see my node application there we go okay so now I don't need that Port 3000 this just works over Port 80 now the next thing I want to do is actually have my own custom domain name there and for this you need to set up a domain on Route 53 and I have a quick 7 Minute video on how to do that so I'm going to assume you've already done that or you can go ahead and do that right now but once you have that you can go back into the AWS console and head over to Route 53 and set up a a custom domain for this ec2 instance so I have a couple of hosted zones here I'm going to use this smw WTF domain and I'm going to create a subdomain for this ec2 instance so I want simple routing or if you're in quick create you can just do it like this I'm going to switch to the wizard though I like the simple routing click next Define a simple record and this subdomain uh expenses that's probably good actually that's my application we're going to do a route for this one and the endpoint is going to be an IP address and I'm going to go back over here and go to my instance that's running and make sure that I select the public IP address right here so just that IP address so I'm going to copy that put that in here and Define the simple record and then I can create that record so once that has been created it can take a while for that to actually come into effect but from experience this usually always works for me so if I come in here and I try to visit that domain again my browser is upset that it is an HT H gtps but if I continue to site it does take me to my ec2 instance so that's really cool so now what I need is for this to be https because right now this is using HTTP and what I want is if someone goes to http like this expenses. smw WTF I want that to be forwarded to https and if they go to https then that should just work it should have an SSL certificate already set up and the way you do this with caddy is really awesome it's so simple go back into that caddy file and modify it and I'm going to go to this section here and what I need to do is just put in my domain name so I had expenses. smw WTF I'm actually just going to verify expenses. smw WTF yep okay so if I save this file now and restart caddy that's all I need to do so now I just need to go and visit that domain name again and the first time it might fell no it didn't all right that was instant this time okay so now I'm visiting on https it set up that SSL certificate it's going to manage renewing that certificate if it expires and if I go to http it's going to forward me over to https so now that is a complete web app I have https set up with a custom domain name it forwards traffic to my node application that's running on the instance that's using a postgress database that's also installed on that instance and this works for demoing applications or for very small scale applications but if you get to a point where you need to manage lots of users or have lots of processing power on your web server you will need to change how this works you'll need to set up your applications for horizontal scaling you'll need to set up your database for scaling and do database backups and manage a load balancer and a whole bunch of other things but this is foundational this is the stepping stone to get to those things so you need to be able to practice this and be able to deploy web apps like this to then get to the point where you can manage these things at scale I think that's it I think that's the end okay bye
Info
Channel: Sam Meech-Ward
Views: 21,582
Rating: undefined out of 5
Keywords: amazon web services, nodejs, aws, cloud computing, aws cloud, deploy nextjs app, deploy next js, deploy nodejs app, deploy bun app, deploy full stack react app to aws, install mysql on ubuntu, caddy web server tutorial, aws ec2 tutorial, aws ec2 tutorial for beginners, aws ec2 instance creation
Id: nQdyiK7-VlQ
Channel Id: undefined
Length: 28min 59sec (1739 seconds)
Published: Mon Jan 22 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.