How to Deploy a Node.js App on a Linux VPS: Complete Beginner's Guide

A Node.js project can run on shared hosting only in limited cases. Once the app needs its own process, custom ports, background work, WebSocket support, or direct control over environment variables, a VPS becomes the more practical option.
This guide shows how to deploy Node.js app on VPS with a clean beginner friendly workflow. You will prepare the Linux server, install Node.js, upload the app, run it with a process manager, place Nginx in front of it, add SSL, and check the live result.
You will also see how to run Node.js on VPS without leaving the app attached to an open terminal. The goal is not just to make the app respond once. The goal is to keep it running after logout, reboot, and normal production traffic.
By the end, you will understand the main parts of a Node.js VPS deployment and know what to check before you send users to the new server.
Prerequisites Before You Start
Before you begin, make sure your app can run locally. It should have a working "package.json", a start script, and a clear list of required environment variables. If the app needs a database, Redis, file storage, or external API keys, prepare those details before deployment.
You also need SSH access to a Linux VPS. Ubuntu or Debian works well for most beginner deployments. A Linux VPS from BlueVPS can be used for this type of setup if you want a server where you control the runtime, Nginx, firewall, and deployment flow.
Prepare these items before you start the Node.js server setup:
- VPS IP address.
- SSH user with sudo access.
- Domain name and DNS access.
- Git repository or archived project files.
- Production environment variables.
- App port, such as '3000'.
- Database access if the app uses one.
- SSL plan with Let's Encrypt or another provider.
You should also decide how the app will start. Most production setups use a process manager such as PM2. PM2 keeps the Node.js process running and can restore it after a server reboot.
This guide uses Nginx as a reverse proxy. Visitors will open "https://example.com", and Nginx will forward requests to the Node.js app on '127.0.0.1:3000'.
How to Deploy a Node.js App on a Linux VPS Step by Step
Step 1. Connect to the VPS and Update the System
Start by connecting to the server through SSH. Replace "root" and "server_ip" with your real login details.
ssh root@server_ip
Update package lists and install the basic tools you will need.
sudo apt update
sudo apt install nginx curl git ufw
Create a separate user for the application. Running app files under a dedicated user keeps the setup cleaner than placing everything under "root".
sudo adduser --disabled-password --gecos "" deploy
sudo mkdir -p /var/www/node-app
sudo chown -R deploy:deploy /var/www/node-app
If your server already has a non root sudo user, you can use that user instead. The important point is simple: the app should have a clear owner, and you should know where its files live.
Step 2. Install Node.js and npm
Use an active LTS version of Node.js for production unless your project requires another supported version. This example uses Node.js 24, which is the current LTS line in 2026.
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install nodejs
node -v
npm -v
The commands "node -v" and "npm -v" confirm that the runtime and package manager are available.
Do not skip the version check. Many deployment problems come from a mismatch between the Node.js version used during development and the version installed on the VPS.
Step 3. Upload or Clone the Application
Move into the app directory as the deployment user.
sudo -iu deploy
cd /var/www/node-app
Clone your repository into the app folder. Replace the repository URL with your real project URL.
git clone https://github.com/your-name/your-app.git .
If you do not use Git, upload the project with SFTP or SCP instead. Keep the same structure that works locally. The server should contain "package.json", the source files, and any files required to build or run the app.
Check that the start script exists.
npm pkg get scripts
The output should include a command such as "start". If your app does not have a start script, add it in the project before deployment.
Step 4. Install Production Dependencies
Install dependencies on the VPS. Use "npm ci" if the project has a lock file. This gives a more predictable install than a fresh dependency resolution.
npm ci --omit=dev
If your project does not have "package-lock.json", use this command instead:
npm install --omit=dev
Some apps need a build step. This is common for frameworks that compile frontend assets or server bundles.
npm run build --if-present
The flag "--if-present" prevents an error when the project has no build script.
Step 5. Add Production Environment Variables
Most Node.js apps need environment variables. Common examples include "NODE_ENV", "PORT", database URLs, session secrets, API keys, and storage settings.
Create a production environment file only if your app expects one.
nano .env
Add the required values for your project. A simple example may look like this:
NODE_ENV=production
PORT=3000
APP_URL=https://example.com
Do not commit real production secrets to Git. Keep them on the server or in a secure deployment system.
After saving the file, confirm that the app directory still belongs to the deployment user.
ls -la
Step 6. Test the App Locally on the VPS
Before you add Nginx or SSL, start the app on its internal port.
PORT=3000 NODE_ENV=production npm start
Open a second SSH session and test the local response from the server.
curl -I http://127.0.0.1:3000
A successful response usually returns "200", "301", "302", or another expected status from your app. If the request fails, check the app logs in the first terminal.
Stop the app with "Ctrl+C" after the test. The next step will run it properly in the background.
Step 7. Run the App with PM2
Install PM2 globally.
sudo npm install pm2@latest -g
Go back to the app directory as the deployment user.
sudo -iu deploy
cd /var/www/node-app
Start the app with PM2.
PORT=3000 NODE_ENV=production pm2 start npm --name node-app -- start
pm2 status
Save the process list.
pm2 save
Create a startup service so PM2 can restore the app after reboot.
pm2 startup systemd
PM2 will print a command that starts with "sudo env". Copy that generated command and run it. Then save the process list again.
pm2 save
At this point, the VPS can host Node.js application processes without keeping your SSH session open.
Step 8. Configure Nginx as a Reverse Proxy
Nginx should receive public web traffic on port 80 and forward it to the Node.js app on port 3000.
Create a new Nginx site file.
sudo nano /etc/nginx/sites-available/node-app
Add this configuration. Replace "example.com" with your real domain.
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable the site and reload Nginx.
sudo ln -sfn /etc/nginx/sites-available/node-app /etc/nginx/sites-enabled/node-app
sudo nginx -t
sudo systemctl reload nginx
The command "sudo nginx -t" must pass before you reload Nginx. If it fails, fix the reported line first.
Step 9. Point the Domain to the VPS
Open your DNS provider and create or update the A record for the domain. Point it to the VPS IP address.
Use one record for "example.com" and another for "www" if the site uses both.
After DNS starts resolving to the new server, test the domain in a browser. You can also check it from the VPS or your local terminal.
curl -I http://example.com
If the domain does not resolve yet, wait and check DNS again. Do not change random server settings while DNS is still updating.
Step 10. Add SSL with Certbot
Install Certbot and the Nginx plugin.
sudo apt install certbot python3-certbot-nginx
Request an SSL certificate for your domain.
sudo certbot --nginx -d example.com -d www.example.com
Certbot will update the Nginx configuration and add HTTPS support. After it finishes, open the site with "https".
Check that the app still works behind Nginx. Test login, forms, redirects, API calls, uploads, and any page that depends on absolute URLs.
Step 11. Review Firewall and Server Access
Allow SSH and web traffic through the firewall.
sudo ufw allow OpenSSH
sudo ufw allow "Nginx Full"
sudo ufw enable
sudo ufw status
Enable the firewall only after SSH access is allowed and tested. Use SSH keys for production access, and disable password login only when you are sure the correct user can connect with a key.
Keep the Node.js app behind Nginx whenever possible. The public site should use ports '80' and '443', while the app itself runs on '127.0.0.1'.
Step 12. Check Logs and Prepare Future Updates
Use PM2 logs to inspect runtime errors.
pm2 logs node-app
Check Nginx logs if the browser shows proxy or gateway errors.
sudo tail -n 100 /var/log/nginx/error.log
Save a simple update routine for future releases. A typical manual update looks like this:
sudo -iu deploy
cd /var/www/node-app
git pull
npm ci --omit=dev
npm run build --if-present
pm2 restart node-app --update-env
pm2 save
This keeps the deployment process repeatable. For a larger project, you can later move this flow into CI, but a clear manual process is enough for a first VPS deployment.
Conclusion
You have now completed the main steps of a Node.js VPS deployment. The server has Node.js, npm, Nginx, PM2, firewall rules, SSL, and a running application behind a reverse proxy.
The key part is the order. Install the runtime first, place the app in a clear directory, verify it on a local port, run it with PM2, then expose it through Nginx and HTTPS. This makes each problem easier to locate.
Now you know how to run Node.js on VPS in a production style setup. You can deploy updates with a repeatable command sequence, check logs when something fails, and keep the app online after logout or reboot.


