ReactHosting.guide Get Hostinger →
← All guides

Host a React + Node.js app on Hostinger VPS with Nginx

Shared hosting is fine for static React apps, but the moment you add a Node.js backend — an API, authentication, a WebSocket server — you need a real server. Hostinger's VPS plans give you full root access, a public IP, and the freedom to run whatever you want. This guide walks you through the entire setup: provisioning the VPS, installing Node.js, configuring Nginx as a reverse proxy, deploying your React frontend, and keeping everything running with PM2.

What you'll need

  • A Hostinger VPS plan (KVM 1 or higher — KVM 2 recommended for comfortable headroom)
  • A React + Vite (or CRA) frontend
  • A Node.js backend (Express, Fastify, or similar)
  • Basic comfort with the terminal and SSH

Step 1: Provision your VPS

After purchasing a Hostinger VPS:

  1. Log in to hPanel and go to VPS
  2. Choose Ubuntu 22.04 as your OS — it's well supported, has a long support window, and most tutorials online target it
  3. Set a root password or upload an SSH key (SSH key is strongly recommended)
  4. Note your VPS IP address from the dashboard

SSH into your server:

ssh root@YOUR_VPS_IP

First thing — update the system:

apt update && apt upgrade -y

Step 2: Create a non-root user

Running everything as root is a security risk. Create a dedicated user:

adduser deploy
usermod -aG sudo deploy

If you're using SSH keys, copy them to the new user:

rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

From now on, SSH in as deploy instead of root:

ssh deploy@YOUR_VPS_IP

Step 3: Install Node.js

Use NVM to install Node.js — it avoids permission issues and makes version management easy:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 20
nvm use 20
node --version

You should see v20.x.x. Node 20 is the current LTS and what you want for production.

Step 4: Install PM2

PM2 keeps your Node.js process alive after crashes and server restarts:

npm install -g pm2

Step 5: Install Nginx

Nginx will sit in front of your Node.js app, handling HTTPS termination and serving your React frontend's static files:

sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx

Visit your VPS IP in a browser — you should see the Nginx welcome page. That confirms it's running.

Step 6: Upload your app

Clone your repo directly on the server:

cd /var/www
sudo mkdir myapp
sudo chown deploy:deploy myapp
cd myapp
git clone YOUR_REPO_URL .
npm install
npm run build

If your repo has both frontend and backend, the structure might look like:

/var/www/myapp/
  dist/        ← built React frontend
  server/      ← Node.js backend
  package.json

Step 7: Start your Node.js backend with PM2

cd /var/www/myapp
pm2 start server/index.js --name myapp

Make PM2 restart on server reboot:

pm2 startup

PM2 will print a command — copy and run it. Then save the current process list:

pm2 save

Check your app is running:

pm2 status
pm2 logs myapp

Step 8: Configure Nginx

Create a new Nginx config:

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

Paste this configuration (replace YOUR_DOMAIN and adjust the port your Node.js app listens on):

server {
    listen 80;
    server_name YOUR_DOMAIN www.YOUR_DOMAIN;

    root /var/www/myapp/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://localhost:3001;
        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;
    }
}
  • Serves your React dist/ folder for all non-API routes
  • The try_files line handles React Router — unknown paths fall back to index.html
  • Proxies any request starting with /api/ to your Node.js backend on port 3001

Enable the config:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t tests your config for syntax errors before reloading — always run it.

Step 9: Point your domain to the VPS

At your domain registrar (or in Hostinger's DNS settings), create A records:

Type: A  Name: @    Value: YOUR_VPS_IP  TTL: 3600
Type: A  Name: www  Value: YOUR_VPS_IP  TTL: 3600

DNS propagation takes up to 24 hours but is usually faster.

Step 10: Enable HTTPS with Let's Encrypt

Once your domain is pointing at the VPS, install Certbot:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d YOUR_DOMAIN -d www.YOUR_DOMAIN

Certbot will automatically modify your Nginx config to handle HTTPS and set up auto-renewal. Confirm with:

sudo certbot renew --dry-run

Deploying updates

When you push new code, SSH into the server and run:

cd /var/www/myapp
git pull
npm install
npm run build
pm2 restart myapp

You can wrap this in a deploy.sh script and run it with one command. For fully automated deploys, add a GitHub Action that SSHes into the server and runs these commands on every push to main.

Useful PM2 commands

pm2 status          # see all running processes
pm2 logs myapp      # tail logs
pm2 restart myapp   # restart after code changes
pm2 stop myapp      # stop the process
pm2 monit           # live dashboard

Troubleshooting

502 Bad Gateway

Nginx can't reach your Node.js app. Check PM2 status (pm2 status) and make sure the port in your Nginx config matches the port your app listens on.

React Router 404 on refresh

Make sure the try_files $uri $uri/ /index.html line is in your Nginx config. This is the Nginx equivalent of the .htaccess fix on shared hosting.

App crashes after reboot

Run pm2 startup and pm2 save again. Make sure you ran the command PM2 printed after pm2 startup.

SSL certificate fails

Your domain isn't pointing at the VPS yet. Wait for DNS to propagate and try again.

Permission denied on /var/www

Make sure your deploy user owns the app directory: sudo chown -R deploy:deploy /var/www/myapp

Summary

A Hostinger VPS with Nginx and PM2 is a solid, production-ready setup for a React + Node.js app. You get full control, no function timeouts, persistent storage, and a single monthly bill. The setup takes a couple of hours the first time, but once it's done deployments are fast and the stack is easy to maintain.

Plans start from $4.99/mo with full root access and SSD storage.

Get a Hostinger VPS →

Hostinger — fast, affordable hosting for React apps. Starting at $2.99/mo.

Get Hostinger →