why?

Mafuposts

Projects

Posts

How to run your NodeJS application on a VPS

Tue Aug 05 2025

You will need

  • A domain name
  • A Ubuntu(or similar) VPS with:
    • NodeJS
    • Nginx
    • Certbot for https(optional)

/!\ When you clone your applications on the VPS, make sure they are setup to run on different ports

Step 1: Run the application(s) with PM2

First make sure that pm2 is installed with:

pm2 -v

If not install with:

sudo npm install -g pm2

Now navigate to your application's directory and assuming your app name is "my-app" run:

pm2 start index.js --name my-app

Or if using npm start:

pm2 start npm --name my-app -- start

You can check the list of running apps with:

pm2 list

Now to make the applications list consistent across machine restarts run (If you didn't do it before):

pm2 startup

And copy/paste the displayed command onto the terminal Lastly to save the current list of processes run:

pm2 save

More information on PM2 here: PM2 Docs

Step 2: Configure Nginx to reverse proxy to your application

Check nginx installation:

sudo systemctl status nginx

If its not installed, run:

sudo apt update
sudo apt install nginx

Add a config file to /etc/nginx/sites-available with the name of your app:

sudo vim /etc/nginx/sites-available/myapp

Paste this:

server {
    listen 80;
    server_name mydomain.com www.mydomain.com;

    location / {
        proxy_pass http://localhost:3000;
        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;
    }
}

Enable the site by symlinking the config file to /etc/nginx/sites-enabled/ Make sure that you use absolute paths:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-ebabled/

Check for syntax errors with:

sudo nginx -t

If it's okay, reload nginx:

sudo systemctl reload nginx

Note:

At this point you can already point your domain to your VPS with an A record, if your security rules allows it...

Step 3: Enable https with Certbot

Check certbot installation:

certbot --version

Check certbot nginx plugin installation:

certbot plugins

If not already installed, install certbot and the nginx plugin with:

sudo apt install certbot python3-certbot-nginx

Run certbot to generate a certificate for your app:

sudo certbot --nginx -d mydomain.com -d www.mydomain.com

That will automatically modify the config files in /etc/nginx/sites-enabled and /etc/nginx/sites-available

And you should be live!

If it doesn't directly work, try reloading nginx:

sudo systemctl reload nginx

Bonus: Setup Github Actions to deploy the changes automatically on your production branch

First go on your github reposiroty in Settings>Secrets and variables>Actions and add three repository secrets:

  • VPS_HOST: With the VPS IP address
  • VPS_SSH_KEY: With the private key you use to connect
  • VPS_USER: With the username

Then in the Actions tab add a new workflow with this:

name: Deploy to VPS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/id_rsa
          chmod 600 ~/.ssh/id_rsa
          ssh-keyscan -p ${{ secrets.VPS_PORT || 22 }} ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts

      - name: Deploy to VPS
        run: |
          ssh -p ${{ secrets.VPS_PORT || 22 }} ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} << 'EOF'
            export NVM_DIR="$HOME/.nvm"
            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
            cd /path/to/myapp
            git pull origin main
            npm install
            pm2 restart myappname
          EOF

Commit the changes and it should deploy when you push to the main branch.

That's all.

- Mafupa