How to host a Node app on a VPS

Haritha Hasathcharu
7 min readFeb 6, 2023

--

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

  1. Remove Apache and install Nginx
  2. Setup a user for your Node app
  3. Clone your Node app from GitHub repository to the VPS
  4. Installing Node JS
  5. Installing and setting up PM2
  6. 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 🥳.

--

--

Haritha Hasathcharu
Haritha Hasathcharu

No responses yet