This is the complete guide to deploying Node.js on a Hostinger VPS: architecture decisions, production considerations, security hardening, and long-term maintenance. It covers not just how to deploy, but how to deploy well. If you want the fastest path from zero to a live app, see our quickstart deployment tutorial.
Before you start: what you need
- A Hostinger KVM VPS — KVM 2 (2 vCPU / 8 GB RAM) suits most Node apps; the entry plan works for bots and side projects. Deal pricing: .63% OFF Verified Oct 8, 2026
VPS KVM 2
$8.99/mo$24.49/mo24-month plan, paid upfront
Renews at $14.99/mo
- 2 vCPU + 8 GB RAM
- 100 GB NVMe storage
- 8 TB bandwidth
- Full root access
- n8n one-click template available
- Ubuntu 22.04 or 24.04 LTS selected as the OS when you provision the server.
- A terminal with SSH (macOS/Linux have it built in; Windows users can use Windows Terminal or PuTTY).
- Your app in a Git repository (GitHub, GitLab) — deploying from Git is the only sane workflow.
- A domain name (optional for testing — the server IP works — required for a real launch). Our Hostinger domains guide covers registration.
If you have never touched a VPS before, read Hostinger Node.js hosting first for the “why a VPS” background and the honest comparison with Vercel and Railway. This page is the hands-on companion: every step, in order.
Step 1 — Provision the VPS and connect via SSH
In the Hostinger panel (hPanel), order the VPS, choose Ubuntu 24.04 LTS, set a root password, and pick the data center closest to your users — latency is the one performance factor you cannot fix later. Once the server is running, note its IP address and connect:
ssh root@YOUR_SERVER_IP
Accept the host key on first connect. Immediately update the system and lock down the firewall — a fresh VPS on the public internet gets probed within minutes:
apt update && apt upgrade -yufw allow OpenSSHufw allow 'Nginx Full'ufw enable
Strongly recommended before going further: disable password login and use an SSH key instead (generate with ssh-keygen, copy with ssh-copy-id). Bots brute-force port 22 constantly; key-only auth removes the entire attack class.
Step 2 — Install Node.js (the right version)
Do not install Node from Ubuntu’s default repositories — the packaged version is typically years out of date. Use the official NodeSource setup for the current LTS (Node 22 as of late 2026):
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -apt install -y nodejsnode -v && npm -v
Also install the build tools some native npm packages need: apt install -y build-essential. If your app needs a specific older Node version, install nvm (Node Version Manager) instead so you can pin per-project versions — but for a single-app server, the system-wide NodeSource install is simpler and easier to keep updated.
Step 3 — Get your app on the server
Clone into /var/www (the conventional home for web apps on Ubuntu):
cd /var/wwwgit clone https://github.com/YOU/YOUR-APP.git appcd appnpm ci
Use npm ci, not npm install — it installs exactly what your lockfile pins, which is what you want on a server. Then create your environment file (.env) with secrets and config: database URL, API keys, PORT, NODE_ENV=production. Never commit .env to Git; copy it over SSH or use your host’s secret storage.
If your app has a build step (Next.js, Nuxt, or a TypeScript backend), run it now: npm run build. This is the memory-hungry step — on the entry KVM plan a large Next.js build can run out of RAM. If the build dies, either build in CI and deploy the output, or step up to KVM 2 before blaming your code.
Step 4 — Keep it alive with PM2
Running node server.js in your SSH session dies the moment you disconnect. PM2 is a process manager that keeps your app running, restarts it on crashes, and brings it back after a server reboot:
npm install -g pm2pm2 start npm --name "myapp" -- startpm2 startup (run the command it prints)pm2 save
For a Next.js app, the start command differs: pm2 start npm --name "myapp" -- start -- -p 3000 or point PM2 at the standalone server output. Check status anytime with pm2 status and logs with pm2 logs myapp. PM2 also gives you zero-downtime reloads (pm2 reload myapp) once you are running multiple instances.
Make sure your app listens on localhost (127.0.0.1), not on all interfaces — Nginx will be the only thing talking to it directly, and binding to localhost keeps your app port invisible to the internet even if the firewall is misconfigured.
Step 5 — Nginx reverse proxy and free HTTPS
Nginx faces the internet and forwards requests to your Node app. Install it and create a site config:
apt install -y nginx
Create /etc/nginx/sites-available/myapp with a proxy block pointing at your app’s port (3000 in this example), then enable it:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
proxy_pass http://127.0.0.1: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;
}
}
The Upgrade lines matter if your app uses WebSockets — without them, socket connections silently fail. Enable the site with ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/, test with nginx -t, and reload.
For HTTPS, Certbot automates everything: apt install -y certbot python3-certbot-nginx then certbot --nginx -d yourdomain.com -d www.yourdomain.com. It obtains a free Let’s Encrypt certificate, rewrites your Nginx config, and sets up automatic renewal. Verify renewal works with certbot renew --dry-run — an expired cert is the most embarrassing possible outage.
Step 6 — Point your domain at the server
In your domain’s DNS settings (Hostinger’s DNS zone editor if the domain is there, or wherever you registered it), create two A records pointing at your VPS IP: one for @ (the bare domain) and one for www. DNS propagation typically takes minutes to a few hours. Once it resolves, Certbot’s certificate covers both names and your app is live at https://yourdomain.com.
Step 7 — Deployments without drama
The manual deploy loop is: git pull, npm ci, npm run build if needed, pm2 reload myapp. It works, but automate it the moment the app matters. The simplest solid setup is a GitHub Actions workflow that SSHes into the server and runs those commands on every push to main — about 30 lines of YAML for deploys you never have to think about. Keep database migrations as a separate explicit step in the workflow so a bad migration cannot silently ride along with a code deploy.
Whatever you automate, keep one rule: the server is never the source of truth for code. Everything deploys from Git. If the VPS vanished tomorrow, you should be able to rebuild from the repo plus the .env backup in under an hour.
Ongoing maintenance checklist
- OS updates:
apt update && apt upgrademonthly; enable unattended security upgrades for the rest. - Node updates: re-run the NodeSource setup when a new LTS lands; test on a staging clone first if the app is critical.
- Backups: Hostinger offers VPS snapshots — schedule them, and separately back up your database off-server. A snapshot is not a backup strategy by itself.
- Monitoring: at minimum, an uptime check (UptimeRobot’s free tier, or Better Stack) that pages you when the site goes down. Add disk-space alerts before a full disk takes down the database.
- Logs:
pm2 logsfor app errors;/var/log/nginx/for access and error logs. Rotate them so they do not fill the disk.
Common gotchas (and fixes)
- App works on the server but not in the browser: check UFW is allowing 80/443, and that Nginx is actually proxying to the right port (
curl localhost:3000from the server tells you if Node is listening). - WebSockets connect then drop: the Nginx
Upgradeproxy headers are missing — add them per Step 5. - Build runs out of memory: Next.js builds need RAM; move the build to CI or upgrade the plan.
- “EADDRINUSE” on restart: an old process is still bound to the port —
pm2 delete myappthen start fresh, and check nothing else was started manually. - Certbot renewal fails: usually a firewall or DNS change blocking port 80, or the domain no longer pointing at the server. Fix the underlying issue, then
certbot renewmanually.
Frequently asked questions
Can I deploy Node.js on Hostinger shared hosting?
No. Shared hosting has no Node.js runtime and no persistent processes. Node.js deployment on Hostinger requires a KVM VPS — see why Node.js needs a VPS for the full explanation.
How long does it take to deploy Node.js on a Hostinger VPS?
Expect an afternoon (2–4 hours) for your first full setup: provisioning, SSH hardening, Node install, PM2, Nginx, and SSL. Repeat deployments take minutes, especially once automated with GitHub Actions.
Do I need PM2, or can I use systemd?
Either works. PM2 is simpler to start with (logs, restarts, and clustering in a few commands); systemd is the more “native” Linux approach and what larger teams usually standardize on. Pick PM2 for your first app and revisit later.
How do I host multiple Node apps on one VPS?
Run each app on its own localhost port under PM2, then add one Nginx server block per domain, each proxying to its app’s port. A KVM 2 plan comfortably hosts several small apps this way — just watch total RAM.
Is the Let’s Encrypt SSL certificate really free?
Yes — Let’s Encrypt certificates are free, and Certbot renews them automatically every 90 days. There is no reason to buy a paid certificate for a standard Node app deployment.
What is the cheapest Hostinger VPS for Node.js?
The entry KVM plan handles bots, side projects, and light APIs; most production apps land on KVM 2 (2 vCPU / 8 GB RAM). Current pricing renders live here:
VPS KVM 2
24-month plan, paid upfront
Renews at $14.99/mo
- 2 vCPU + 8 GB RAM
- 100 GB NVMe storage
- 8 TB bandwidth
- Full root access
- n8n one-click template available
