deploy · tutorial · vps

Cloudflare Tunnel + Next.js: Hackers Find Zero Open Ports

A $5 VPS with Cloudflare Tunnel + Tailscale exposes zero ports yet serves the world. Setup, attack table, tradeoff.

A steam locomotive with a train on tracks leading into the Detroit River railway tunnel, about 1910
A steam locomotive with a train on tracks leading into the Detroit River railway tunnel, about 1910 · Photo: Detroit Publishing Company, public domain, via Wikimedia Commons

"A VPS sounds less safe than Vercel"

Every founder hears it from a friend. Vercel has a security team, SOC 2 reports and engineers who patch at 3 a.m. Your $5 box has you.

So the fear keeps people paying per-request prices long after the math stops working.

The box feels exposed.

Port 22 open to the planet.

SSH brute-forced a thousand times a day.

Some forgotten service listening on the public IP.

That fear was fair in 2015.

With a Cloudflare Tunnel and a private mesh, the premise is gone. There is nothing to scan, because nothing is open.

What attackers actually scan for

Bots do not hack. They knock on doors and walk through open ones. They try ports 22, 80, 443, 3000 and 5432 on every IP, all day.

Attack surface Default VPS Tunnel and mesh VPS Vercel or Railway
SSH open to the world Yes, brute-forced daily Closed, private network only Closed, you never see it
Web ports hit the origin directly Yes, the origin IP is hittable Closed, Cloudflare's edge only Closed, their edge only
App port exposed Often, by accident Local only Never exposed
Database port exposed Sometimes None, SQLite is a file The vendor's network
Who absorbs a flood Your one vCPU Cloudflare first Their edge first

Two details make the default VPS worse than it looks.

SSH on the open internet never sleeps. Even with keys only, the log fills with attempts. One password mistake or one leaked key, and a knock becomes a login.

The origin IP leaks once, forever. Serve traffic direct to the IP a single time and scanners store it.

Platforms solve this by never giving you the box. A tunnel copies the same shape onto hardware you control.

What to do

The server opens zero inbound ports.

It makes two outbound connections.

One to Cloudflare, for visitors.

One to Tailscale, for admins.

Start by denying the world at the firewall.

Deny all incoming.

Allow outgoing.

Allow only your private network interface.

No rule for 22. No rule for 80. No rule for 443.

If the tunnel and the mesh both died, the box would sit silent and unreachable. That is the posture you want.

Next, let visitors in through an outbound-only Cloudflare Tunnel.

The tunnel dials out to Cloudflare's edge and holds the connection open. Visitors hit Cloudflare's network, with its caching, firewall rules and flood absorption. Cloudflare forwards clean requests down your existing outbound pipe.

A port scanner hitting your IP directly gets connection refused. Nothing listens there. Your Next.js app listens only on the machine itself.

Last, let admins in through Tailscale. Never port 22.

SSH travels inside WireGuard encryption to identities on your private network. Lose your phone and you revoke the node in the admin panel.

Pair it with alerts to Telegram or Discord, and a dead tunnel reaches your pocket.

The scan test

Run this from a machine outside your private network, and read the silence.

Check Command Pass looks like
No SSH from the internet nc -vz YOUR_VPS_IP 22 Connection refused, instantly
No HTTP direct to the origin curl -m 5 http://YOUR_VPS_IP Timeout or refused
App alive through the edge curl -sI https://app.example.com A 200, served through Cloudflare
Admin path alive Check the private network status from your phone Server listed, SSH works

Know this first

On a VPS, updates, disk space and backups are yours. A platform handles those for you. Compliance paperwork is not included.

The network shape matches a platform's. The upkeep does not.

Why BoringPush is the way to do this

Nothing open to attack.

BoringPush sets up the firewall, the tunnel and the private network for you.

Visitors reach Cloudflare. You reach the server over a private mesh. Port 22 stays closed.

The kit also takes daily database snapshots, so the upkeep you own is smaller.

FAQ

Is a cloudflare tunnel nextjs setup really as safe as Vercel?

For network exposure, yes: both show the world an edge network and zero origin ports. Scanners find nothing to knock on either way.

What Vercel still wins is everything above the network — managed patching, compliance reports, and someone else's pager. Match the network with the tunnel, then decide if you need the paperwork.

What happens if Cloudflare goes down?

Your site follows it — same as any site behind Cloudflare, including big ones. The VPS keeps running (the app stays up, SQLite keeps writing), and traffic returns when the edge does. If that concentration worries you, keep a direct backup hostname resolved only inside your Tailnet for admin access during edge outages.

Does Tailscale replace fail2ban and key hardening?

It removes the reason they existed: no public SSH means no internet brute force to ban. Keep keys-only auth and per-person identities anyway — defense in depth costs nothing here. Fail2ban on a box with zero public SSH is a locked screen door inside a vault: harmless, unnecessary.

Can scrapers still burn my bandwidth through the tunnel?

They reach Cloudflare, not your origin — and that is the point. Cache static pages and images at the edge, add a WAF rule for the worst bot shapes, and a scraper bill becomes Cloudflare absorbing junk while your $5 box sleeps.

Uncached API routes still cost CPU, so rate-limit them regardless of platform. BoringPush includes a basic rate limiter for API handlers.

Do I still need HTTPS certs on the VPS?

No public certs on the box — the tunnel carries origin traffic and Cloudflare terminates public TLS at the edge. Keep one small thing: the cloudflared service itself authenticates with a tunnel token, so treat /etc/cloudflared/ like a secret and never commit it. Cert renewals, the classic 2am expiry page, simply stop existing.

What breaks most often in this setup?

Tunnel token rotation (fix: re-run cloudflared tunnel login from the server, never from the laptop) and Tailscale key expiry locking you out of admin (fix: disable expiry for prod-box in admin, keep a second admin node). Both take minutes. The scan table above catches either before it matters.

Keep reading

+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)

The Agent-First Shipping Kit

Command from your phone.

Built so autonomous AI agents build what you want without breaking what's already paying you.

$199

Get BoringPush

One-time payment · Lifetime updates · Unlimited projects.

Keep reading