How to host a Node app on a VPS
Hi guys, welcome.
In this article, I am going to go through the steps of setting up a Node app on a Linux VPS that has Ubuntu installed. If you want to get an idea on how to spin up a VPS, please read through this article.
Let’s get an idea on the prerequisites first.
Prerequisites
- A linux server with root terminal access
Now let’s take a look on the basic steps to follow in order to host a node app on VPS with SSL.
Steps
- Remove Apache and install Nginx
- Setup a user for your Node app
- Clone your Node app from GitHub repository to the VPS
- Installing Node JS
- Installing and setting up PM2
- Configure reverse proxy on Nginx
Remove Apache and install Nginx
Nginx is a better server than Apache when it comes to serving your node apps by reverse proxying. It is pretty easy, more cleaner, and more lightweight than Apache.
Therefore, it is recommended to use Nginx as your reverse proxy for hosting node apps.
To remove apache, use these commands one by one on your VPS.
systemctl stop apache2
#stops apache2 if its running
systemctl disable apache2
#disables apache2
apt remove apache2
#removes apache2
apt autoremove
#cleanup dependencies
After that, run a clean install and do an upgrade.
apt clean all && sudo apt update && apt dist-upgrade
Now install Nginx on your server.
apt install nginx
Then to remove the default configurations and the default site generated by Nginx, use these commands one by one.
rm -rf /var/www/html
#removes the default site
rm /etc/nginx/sites-enabled/default
#removes the default sites
rm /etc/nginx/sites-available/default
#removes all the example sites
Set up a user for your Node apps
It is highly recommended to not start any of your node apps using the root user. While it is recommended to run Nginx with root, it is highly advised not to run any of your node apps with root as they can get compromised, and it will be putting your whole VPS in danger.
For simplicity, I will just use the root user for now. If you want to do that now, you can refer this tutorial to learn how to create and manage users on a VPS.
Clone your Node app from GitHub repository to the VPS
Copying and pasting your code from your local machine each time you make changes to your app is a bit tedious. Therefore, I highly recommend you to set up this simple way to pull your app updates from GitHub by cloning your repository to the VPS.
If your repository is public, go ahead and clone your repository using the following command, or just copy the clone command from your GitHub repository page.
Before using the below command, make sure you navigate to the desired folder using the cd
command.
git clone git@<YourAlias>:<YourUserName>/<YourRepoName>.git
If it is private, then the best way is to set up deploy keys for your GitHub repository.
To do that, first go to settings of your repository, then click on deploy keys on the left sidebar.
Then head on to your VPS and generate an ssh key pair for your GitHub repository.
ssh-keygen -t ed25519 -C "<your GitHub account email>"
Give an appropriate name for your key pair, and leave the passphrase empty by hitting enter.
Generating public/private ed25519 key pair.
Enter file in which to save the key (~/.ssh/id_ed25519): ~/.ssh/GitHub
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ~/.ssh/GitHub
Your public key has been saved in ~/.ssh/GitHub.pub
The key fingerprint is:
SHA256:3iGsygZ5XfAY6KTsafloWFPtbZgg/ks4osdfb2sw3dBrRys yourgithubemail@gi.com
The key's randomart image is:
+--[ED25519 256]--+
| o.o+. |
| ..B+ o |
| .++= += |
|. o+.=.o. |
|oo.o+.+. o |
|+.o+o..E = . |
| . oo o + . |
| .oo. |
| .+. |
+----[SHA256]-----+
Then output your public key using this command.
cat ~/.ssh/GitHub.pub
Then copy the output and head on to GitHub deploy keys, click add new key, then just paste the public key and give it an appropriate name.
Then head on to your VPS and paste the below command to reload the new keys.
eval `ssh-agent -s`
Then you need a way to tell your server to use this SSH key when you are cloning your private repository, otherwise it won’t be used by git. To do that, you can create a config file in the .ssh
folder. Remember, you need to create this in your user’s .ssh
folder.
cd ~/.ssh
nano config
Then paste this alias configuration.
Host <YourRepoHost>
HostName github.com
IdentityFile ~/.ssh/<YourRepoHost>
Now you are all set. When you are cloning your repository, remember to use this format. This is very important, otherwise it won’t use the SSH key you created.
git clone git@<YourRepoHost>:<YourUserName>/<YourRepoName>.git
It should clone your repository with no errors.
Installing Node JS
Now it’s time to install Node JS on your VPS. To manage Node versions, it is easier to use the Node Version Manager (NVM). Paste the below commands one by one in order to install NVM.
sudo apt-get update
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh //download NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
source ~/.bashrc
#if your shell is zsh, then use
source ~/.zshrc
#don't use both commands
The source command is used to load the new configuration in to the shell script.
To view all the Node versions available, use this command.
nvm list-remote
To install the latest long term support version (LTS), use the below command.
nvm install --lts
This command can be used to view the currently used Node JS version. This also confirms whether you have installed Node JS correctly.
node -v
Then you can start up your node app by navigating to your repository you cloned in Step 3.
Configure your environment variables by creating a .env
file using the following command.
touch .env
Then you can edit the file using any text editor such as nano. This is only required if your node app uses any environment variables.
nano .env
Then you can build your app using npm install
.
npm install
If the npm install
fails, it might be due to memory limitations on your VPS. If it happens, you can set up a swap file with the below commands.
fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon --show
cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl vm.vfs_cache_pressure=50
echo 'vm.vfs_cache_pressure=50' | sudo tee -a /etc/sysctl.conf
If it still fails, then it might be due to the heap size being too small. You can confirm it using the below command.
node -e 'console.log(v8.getHeapStatistics().heap_size_limit/(1024*1024))'
If it’s too small, then set it to a higher value using the below command.
export NODE_OPTIONS="--max-old-space-size=1024"
If the internet for your VPS is too slow, it may also cause the npm install
to fail. If that is the case, increase the timeout limit by editing the npm config file .npmrc
.
nano ~/.npmrc
Replace these lines with the ones given.
fetch-retry-maxtimeout=6000000
fetch-retry-mintimeout=1000000
You can use the below command to verify
npm config list
Installing and setting up PM2
Process Manager 2 (PM2) let’s you keep node apps running in the background even after closing the shell. Without PM2, it won’t be possible to run your Node app continuously.
To install PM2, use this command.
npm i -g pm2
Now go to the folder where your app is, and run this command. This command assumes that your NPM command to start the app is npm start
.
You can also give it an appropriate name to later identify your app in the PM2 list.
pm2 start npm --name "<YourAppName>" -- start
These are some useful commands for PM2.
pm2 list
#list all pm2 processes
pm2 stop <processName>
#to stop a specific process
pm2 stop all
#to stop all pm2 processes
pm2 delete all
#to delete all pm2 processes
pm2 save
#save the current configuration. this will make pm2 start up the apps automatically when the VPS reboots
Configure reverse proxy on Nginx
Now that your node app is running on http://localhost:portnumber
, you need to reverse proxy it in order to make it accessible to the public. It is not recommended to expose the port that your app runs on to the public. To do that, we can set up reverse proxy on Nginx.
Now it’s time to configure a server. Create a config file for your site using the following command.
touch /etc/nginx/sites-available/yourSite.yourTld.conf
Then open the config file using the nano command.
nano /etc/nginx/sites-available/yourSite.yourTld.conf
Paste the below content.
server {
listen 80;
listen [::]:80;
server_name yourSite.yourTld www.yourSite.yourTld;
location / {
proxy_pass http://localhost:<yourAppPort>/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Now you have to create a symlink to enable the site. Only conf
files in the sites-enabled folder are enabled. Run these two commands while in the sites-available
folder.
cd ../sites-enabled
sudo ln -s ../sites-available/yourConfFileName.conf .
Not you can test your configuration for any syntax errors using the below command.
nginx -t
Now, in order for the changes to take effect, you need to reload Nginx. Use the below command for that.
nginx -s reload
Go ahead and edit your domain’s DNS records to point to your server’s IP address. This can be done via an A Record
. You will need to wait a little while (maximum 48 hours, but usually within minutes) for the new DNS records to propagate across the globe.
Now your node app should be accessible via your domain name. If it doesn’t, make sure your firewall rules allow port 80
.
Phew! That was a lot. If you did all the things above correct, your app should be up and running! Congratulations 🥳
.