Managed serverless platforms are great until your Next.js app starts pulling real traffic and the billing alerts roll in. Bandwidth overages and execution limits add up fast. You don’t need a $100/month hosting bill for SSR and edge caching. A cheap Hostinger KVM VPS, Namecheap for DNS, and StackPath CDN in front give you the exact same global performance for pennies on the dollar.
People often write off Hostinger as just shared WordPress hosting. Their shared hPanel plans won’t work here since you can’t run persistent Node daemons, but a Hostinger KVM VPS gives you full root access on Ubuntu 22.04. Add an Nginx reverse proxy, PM2 for process monitoring, and StackPath to soak up static traffic at the edge, and you get sub-100ms load times worldwide.

The Architecture: Hostinger, Namecheap, and StackPath
Before jumping into the terminal, here is how the request path actually works. Visitors never connect directly to your Node process:
- Authoritative DNS (Namecheap): Handles your nameservers and sends traffic for your apex and subdomains straight to StackPath edge IPs.
- Edge CDN (StackPath): Terminates public SSL, serves static chunks (
/_next/static/*) directly from edge cache, and proxies dynamic SSR calls to your origin. - Origin Server (Hostinger VPS): Runs Ubuntu 22.04 LTS with an Nginx reverse proxy on ports 80/443, forwarding dynamic hits to Next.js on an internal port like 3000.
We used a similar setup when looking at how to deploy a React SPA on Hostinger with StackPath CDN and Namecheap DNS, but running dynamic server-side rendering takes a bit more server-side wiring.
Step 1: Prepare the Next.js Standalone Build
If you deploy raw Next.js source code and run npm install on a 1GB or 2GB VPS, you’ll probably trigger the OOM killer during the build. Don’t do that. Build locally or in CI using Next.js standalone output mode, which bundles only the required production files and dependencies into a lean directory.
Open your local next.config.js or next.config.mjs and enable the standalone target:
/** @type {import('next').NextConfig} */
const nextConfig = { output: 'standalone', reactStrictMode: true, poweredByHeader: false,
}; module.exports = nextConfig;Run your production build locally:
npm run buildLook inside your project root and you’ll see a generated .next/standalone folder with a minimal server.js. That standalone folder is what we ship to the VPS.
Step 2: Provision Node.js and PM2 on Hostinger VPS
Grab your Hostinger VPS IP address from the dashboard (say, 185.193.65.120) and SSH in as root or your sudo user:
ssh root@185.193.65.120Pull in Node.js 20 LTS from the official NodeSource repo and install build basics:
sudo apt-get update && sudo apt-get install -y ca-certificates curl gnupg
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs nginx
sudo npm install -g pm2Verify both binaries installed cleanly:
node -v
pm2 -vYou should see v20.x.x and the PM2 banner. Now make a directory for the app:
sudo mkdir -p /var/www/nextapp
sudo chown -R $USER:$USER /var/www/nextappStep 3: Transfer Files and Configure PM2
Back on your local machine, rsync your standalone build, static assets, and public directory over to the server:
rsync -avz --exclude 'node_modules' .next/standalone/ root@185.193.65.120:/var/www/nextapp/
rsync -avz .next/static/ root@185.193.65.120:/var/www/nextapp/.next/static/
rsync -avz public/ root@185.193.65.120:/var/www/nextapp/public/Pay close attention to copying .next/static and public. The standalone output does not copy static assets by default. If you skip this, your app will load raw unstyled HTML and spit 404s for every CSS and JS chunk in the browser console.
Now jump back to your VPS terminal and drop an ecosystem.config.js file into the app root so PM2 knows how to run the app:
// /var/www/nextapp/ecosystem.config.js
module.exports = { apps: [ { name: 'nextapp', script: 'server.js', cwd: '/var/www/nextapp', instances: 'max', exec_mode: 'cluster', env: { NODE_ENV: 'production', PORT: 3000, HOSTNAME: '127.0.0.1' } } ]
};Fire up the process and save the PM2 state so it boots back up automatically after a server reboot:
cd /var/www/nextapp
pm2 start ecosystem.config.js
pm2 save
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u root --hp /rootQuick sanity check: run curl http://127.0.0.1:3000. If you get HTML back, your Node app is alive on loopback.
Step 4: Configure Nginx as a Reverse Proxy
Never point public traffic straight at port 3000. Nginx handles connection drops, buffers requests, strips headers, and handles local routing far better than Node ever will.
Create a config file at /etc/nginx/sites-available/nextapp:
# /etc/nginx/sites-available/nextapp
server { listen 80; listen [::]:80; server_name example.com www.example.com; # Security headers server_tokens off; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; # Static files routing directly via Nginx location /_next/static/ { alias /var/www/nextapp/.next/static/; expires 365d; access_log off; add_header Cache-Control "public, max-age=31536000, immutable"; } location /public/ { alias /var/www/nextapp/public/; expires 30d; access_log off; } # Reverse proxy for dynamic SSR and routes 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_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; proxy_cache_bypass $http_upgrade; }
}Link the config into sites-enabled and test the syntax before reloading:
sudo ln -s /etc/nginx/sites-available/nextapp /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginxIf you want full origin encryption before hooking up StackPath, follow our guide on how to configure end-to-end SSL across Namecheap, StackPath, and Hostinger with Certbot.
Step 5: Set Up the Origin Site in StackPath CDN
StackPath will sit between your visitors and your Hostinger server, catching all the repetitive asset traffic. Head to your StackPath control panel and create a new CDN site.
- Set the service type to CDN and type your domain (e.g.,
example.com). - Select IP Address under Origin Type.
- Enter your Hostinger VPS IP (e.g.,
185.193.65.120). - Set the Origin Port to
80(or443if you set up Let’s Encrypt directly on Hostinger).
StackPath will hand you an edge hostname (like c7.hwcdn.net or a custom edge endpoint) or edge Anycast IPs. Hang onto those—you need them for Namecheap.
Now jump into StackPath’s Edge Rules to set caching policies that won’t break Next.js:
- Static Chunks: Match URL path
/_next/static/*. Choose Override Origin Cache Headers and set the TTL to 1 Year (31536000s). Next.js fingerprints these with content hashes, so they are completely safe to cache forever. - Optimized Images: Match
/_next/image*and set TTL to 7 days so you aren’t constantly resizing images on your VPS. - Dynamic Pages: Keep standard pages on pass-through so SSR runs dynamically and respects origin cache headers.
If you expect huge traffic bursts, you can also configure Origin Shield in StackPath CDN to consolidate edge requests and keep your VPS from choking on cache misses.
Step 6: Configure DNS Records in Namecheap
Now tell the world to route through StackPath. Log into Namecheap, hit Domain List, click Manage next to your domain, and open the Advanced DNS tab.
Make sure your nameservers are set to Namecheap BasicDNS. Clear out any old parking records and add these:
- CNAME for WWW:
- Host:
www - Target:
your-site-id.stackpathdns.com(your edge hostname) - TTL: Automatic (or 5 min)
- Host:
- Apex (@ Record):
- If StackPath gave you Anycast IPs, add an A Record with Host
@pointing to those IPs. - If you’re using a CNAME/hostname on the root domain, use an ALIAS record. Check our walkthrough on how to point an apex domain to a CNAME in Namecheap DNS with ALIAS records.
- If StackPath gave you Anycast IPs, add an A Record with Host
Your records should look like this:
Type Host Value TTL
A Record @ 151.139.128.10 5 min
A Record @ 151.139.128.11 5 min
CNAME Record www example.stackpathdns.com. 5 minDNS propagation usually settles within 10 to 15 minutes. Check it locally using dig:
dig +short example.com
dig +short www.example.comGotcha: CORS and Custom Fonts on Next.js
Here’s a bug that caught me off guard: if your app uses custom web fonts or loads font files via CSS through the CDN hostname, modern browsers will block them on cross-origin grounds. You’ll see missing icon fonts and this error in your dev tools:
Access to font at 'https://example.com/_next/static/media/font.woff2' from origin 'https://www.example.com' has been blocked by CORS policy.The fix is to tell Nginx to serve permissive CORS headers on font extensions. Add this block to your Nginx configuration on Hostinger:
# Inside /etc/nginx/sites-available/nextapp
location ~* .(woff|woff2|ttf|eot|svg|otf)$ { alias /var/www/nextapp/.next/static/; add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, OPTIONS"; add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range"; expires 365d; access_log off;
}Reload Nginx with sudo systemctl reload nginx and hard-refresh. If you’re still seeing asset delivery snags, check out our guide to fix CORS font errors when serving static assets via CDN.
Testing and Verifying Cache Hits
Once DNS points to StackPath, confirm that your static assets are caching at the edge and SSR hits are reaching your VPS. Run a curl against a CSS chunk:
curl -I https://example.com/_next/static/css/app.cssLook at the response headers:
HTTP/2 200
date: Wed, 24 Oct 2024 14:15:22 GMT
content-type: text/css; charset=UTF-8
cache-control: public, max-age=31536000, immutable
x-cache: HIT
x-hw: 1698156922.d02.sp.amsThat x-cache: HIT tells you StackPath served the file directly from edge RAM without touching your VPS. If you curl an SSR route, you’ll get x-cache: MISS on the first call, followed by fast origin rendering.
Frequently Asked Questions
Can I deploy Next.js on Hostinger shared hPanel hosting instead of VPS?
Only if you run a purely static export (output: ‘export’ in next.config.js). Shared hosting doesn’t let you run persistent Node processes, bind internal ports, or manage PM2 instances. For dynamic SSR, Server Actions, or API routes, you need the KVM VPS.
How do I update the Next.js app without downtime?
Build your new release locally or in CI, rsync the standalone folder to a temporary directory on the server, swap the folder symlink, and run pm2 reload ecosystem.config.js --update-env. PM2 will cycle the worker processes one by one with zero downtime.
Do I need an SSL certificate on the Hostinger VPS if StackPath handles SSL?
Yes. If you skip origin SSL, the traffic between StackPath’s edge and your Hostinger VPS travels over plain HTTP in clear text. Run Certbot on Nginx to get a free Let’s Encrypt cert, then configure StackPath to pull from your origin over HTTPS on port 443.
How does this compare to deploying an Astro site on the same stack?
Astro compiles down to pure static HTML and assets by default, so you don’t even need Node or PM2 running on the server—Nginx serves files straight from disk. See our guide on how to deploy an Astro site on Hostinger with Namecheap and StackPath for that setup.
Next Steps
Keep an eye on PM2 using pm2 monit over the first couple of days to make sure memory stays stable. If you manage multiple sites or want an isolated environment before pushing changes to your production VPS, check out our guide on how to set up staging environments on Hostinger.

