Why Reverse Proxy Failed with Vercel + Cloudflare Workers - and How Nginx Fixes It
What Worked, What Failed, and the Architecture That Finally Did
The Goal
I wanted this setup:
https://anandsuthar.dev → Main website (Next.js)
https://anandsuthar.dev/blog → Hashnode blog
Instead of:
blog.anandsuthar.dev
The goal was a clean URL, better branding, and shared SEO authority.
What I Tried (and Why It Failed)
1. Next.js Rewrites (Vercel)
async rewrites() {
return [
{
source: '/blog/:path*',
destination: 'https://blog.anandsuthar.dev/:path*',
},
];
}
❌ Did not work
Why:
Next.js rewrites are not a true reverse proxy
Browser still makes cross-origin requests
Hashnode/Vercel security kicks in
2. Cloudflare Workers as Reverse Proxy
Worker logic:
export default {
async fetch(request) {
return fetch("https://blog.anandsuthar.dev");
}
};
result:
429 Too Many Requests
/.well-known/vercel/security/request-challenge
❌ Blocked
3. Why “WORKER HIT” Worked (Important Insight)
export default {
async fetch() {
return new Response("WORKER HIT");
},
};
✅ This worked because:
Browser → Cloudflare Worker → Response
Vercel was never involved
The moment the Worker tried to fetch Vercel/Hashnode, security kicked in.
The Real Reason It Fails
Vercel Security Model
Vercel:
Detects edge proxies
Detects non-browser requests
Injects JavaScript challenges
Requires real browser execution
Cloudflare Workers:
Are server-side
Cannot execute JS challenges
Cannot solve bot protection
Are detected instantly
You do not have full control on Vercel. This is intentional.
The Only Place Reverse Proxy Truly Works
Self-Hosted Linux + Nginx
Why?
Nginx operates at the network level
No JS challenges
No bot detection
Full header, cookie, and TLS control
Looks like a real origin server
Final Working Architecture (Recommended)
Internet
↓
Cloudflare DNS (optional)
↓
DigitalOcean Droplet (Ubuntu)
↓
Nginx
├── / → Next.js app
└── /blog → Hashnode
Step-by-Step Working Solution (DigitalOcean + Nginx)
1. Create a Droplet
Ubuntu 22.04
Open ports: 80, 443
2. Install Nginx
sudo apt update
sudo apt install nginx -y
3. Install SSL (Let’s Encrypt)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d anandsuthar.dev -d www.anandsuthar.dev
4. Nginx Reverse Proxy Configuration
Edit:
sudo nano /etc/nginx/sites-available/anandsuthar.dev
server {
listen 443 ssl;
server_name anandsuthar.dev www.anandsuthar.dev;
ssl_certificate /etc/letsencrypt/live/anandsuthar.dev/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/anandsuthar.dev/privkey.pem;
# MAIN WEBSITE (Next.js)
location / {
proxy_pass http://localhost: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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# BLOG → HASHNODE (THIS IS THE MAGIC)
location /blog/ {
proxy_pass https://blog.anandsuthar.dev/;
proxy_set_header Host blog.anandsuthar.dev;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_ssl_server_name on;
proxy_redirect https://blog.anandsuthar.dev/ /blog/;
}
}
Enable site:
sudo ln -s /etc/nginx/sites-available/anandsuthar.dev /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Result
| Works | |
anandsuthar.dev | ✅ Next.js |
anandsuthar.dev/blog | ✅ Hashnode |
| JS / CSS / Images | ✅ |
| SEO | ✅ |
| Cookies | ✅ |
| No 429 / No challenge | ✅ |
Why This Works (Final Explanation)
Nginx runs before the browser
Hashnode sees a real origin
No bot detection
No edge fingerprint
Full HTTP control
This is impossible on:
Vercel
Cloudflare Workers
Netlify
Any managed edge platform
Final Takeaway
If you need reverse proxy, you need server control.
Vercel = convenience, not control
Workers = compute, not browsers
Nginx = absolute control