Goodbye Vercel: How I Hosted My Next.js App (Travelliq) on a VPS from Scratch
NextJs VPS hosting comprehensive guide

I specialize in building production-ready web applications using the MERN stack, Next.js, and modern UI frameworks. My work spans full-stack development, dashboard systems, authentication flows, and deployment on VPS environments.
On this blog, I share practical experiences, lessons learned from real projects, and insights into building scalable, user-centric digital products.
The Comfort Zone vs. The Control Zone
When building a Next.js application like Travelliq, the default path is obvious: deploy to Vercel. It’s magical. You push to GitHub, and 30 seconds later, your site is live.
So, why on earth would I choose to manually configure a Linux server, mess around with SSH keys, configure Nginx reverse proxies, and manage my own SSL certificates?
Two reasons: Cost and Control.
As Travelliq grows, serverless functions can become expensive and unpredictable. I wanted a predictable monthly bill. I also needed custom cron jobs and a persistent backend environment that serverless functions struggle to provide.
Here is the exhaustive, step-by-step guide on how I took a raw VPS (Virtual Private Server) and turned it into a production-grade host for a Next.js application.
Phase 1: The Server Setup (The "Naked" Linux Box)
I started by purchasing a basic Ubuntu 22.04 Droplet (you can use DigitalOcean, AWS EC2, Linode, or Hostinger). Once I had the IP address, I logged in.
ssh root@192.168.1.1
1. Security First (Don't Skip This)
Logging in as root is dangerous. If you break something as root, you break the whole server.
First, I created a new user for myself.
adduser uzair
usermod -aG sudo uzair
Then, I set up a simple firewall using UFW (Uncomplicated Firewall). We need to explicitly allow SSH (so we don't lock ourselves out), HTTP, and HTTPS.
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable
Finally, I copied my local SSH public key to the server so I never have to type a password again.
Phase 2: preparing the Environment
A raw server knows nothing about JavaScript. We need to teach it.
1. Installing Node.js (The Right Way)
Never use apt install nodejs. You will get an ancient version. I used NVM (Node Version Manager) to install the specific version my project uses.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc
nvm install 20
nvm use 20
2. Installing PM2 (Process Manager)
If I run npm start, the app dies as soon as I close my SSH window. We need a process manager to keep the app alive 24/7 and restart it if it crashes.
npm install -g pm2
Phase 3: Deploying the Code
Now, getting Travelliq onto the box.
I cloned the repository into the /var/www/travelliq directory (standard convention for web apps).
cd /var/www
git clone https://github.com/uzairalam/travelliq.git
cd travelliq
The Build Step
Next.js applications need to be compiled. This converts all my React code into optimized chunks.
npm install
npm run build
Note: If your server runs out of RAM during the build (common on $5/mo servers), you might need to enable a "Swap File".
Starting the App with PM2
Instead of npm start, I used PM2.
pm2 start npm --name "travelliq" -- start
Now, if I type pm2 list, I see my app running, consuming memory, and waiting for traffic on localhost:3000.
But wait—if I go to my server's IP in the browser, nothing happens. Why? Because the firewall blocks port 3000. We only allowed port 80 (HTTP). We need a Reverse Proxy.
Phase 4: Nginx (The Gatekeeper)
Nginx is the bouncer. It stands at the door (Port 80), takes requests from the outside world, and politely passes them to my Next.js app running inside on Port 3000.
I installed Nginx:
bsudo apt install nginx
Then, I created a configuration file for Travelliq:
sudo nano /etc/nginx/sites-available/travelliq
Here is the exact config I used (save this, it’s gold):
server {
server_name travelliq.com www.travelliq.com;
location / {
proxy_pass http://localhost:3000; # Forward to Next.js
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;
}
}
I enabled the site by creating a symlink:
sudo ln -s /etc/nginx/sites-available/travelliq /etc/nginx/sites-enabled/
sudo nginx -t # Test for syntax errors
sudo systemctl restart nginx
Now, typing http://travelliq.com worked! But it was "Not Secure."
Phase 5: HTTPS & The Green Padlock
In 2026 (and 2024), you cannot run a site without SSL. Google will penalize you, and users won't trust you.
I used Certbot (by Let’s Encrypt) to get a free SSL certificate.
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d travelliq.com -d www.travelliq.com
Certbot is amazing. It automatically detected my Nginx config, asked if I wanted to redirect all HTTP traffic to HTTPS (Yes, please), and updated the configuration file for me.
Phase 6: Automating Deployment (CI/CD)
The only downside to VPS is that you don't get automatic deployments when you push to GitHub. I had to build a simple workaround.
I set up a GitHub Action that SSHs into my server and runs a script whenever I push to the main branch.
The Script (deploy.sh):
cd /var/www/travelliq
git pull origin main
npm install
npm run build
pm2 restart travelliq
Now, the workflow is almost as smooth as Vercel, but I own the infrastructure.
The Verdict
Was it harder than Vercel? Yes.
Is it worth it? Absolutely.
Hosting Travelliq on a VPS gave me:
Lower Latency: I chose a data center physically closer to my target users.
No Cold Starts: The server is always running. The first request is as fast as the 100th.
Cost Cap: I pay $6/month. No matter how many users visit, I won't get a surprise bill for bandwidth overages.
If you are serious about becoming a Full Stack Engineer, stop hiding behind Platform-as-a-Service. Spin up a Linux box and break things until they work.
Thanks for reading!
If you enjoyed this breakdown, you might like my project Travelliq. It’s a travel SaaS platform built with Next.js.
🚀 Check out the Live Demo on my Portfolio at uzairalam.me
👋 Connect with me on Twitter/X or LinkedIn for more updates.



