ngrok's free tier now gives you one endpoint, 1 GB a month, a random domain, and an interstitial warning page your visitors must click through. A persistent domain starts at $8 a month, real edge configuration at $20, and custom domains cost extra on top. For a tool whose whole job is showing localhost to someone else for ten minutes, that is a lot of meter — so developers keep building the escape hatch themselves. The latest entry is Proxly, an MIT-licensed, self-hosted tunnel with a one-line pitch: like ngrok, but on your own domain.
Here is the verdict first, because everything below is just the evidence for it: Proxly moves the tunnel to infrastructure you own, but the compute still lives on your laptop. That is a genuine win for local-dev sharing — your subdomain, your TLS, no third-party edge in the path — and it is structurally not a deployment. The moment the demo has to survive your laptop lid closing, you need a platform that runs the process, not a relay that forwards to it.
How Proxly actually works, end to end
The architecture is a classic relay with two halves. On your VPS runs the relay server (packages/server), sitting behind Nginx, which owns TLS termination. On your laptop runs the proxly CLI (packages/client), which opens one WebSocket per tunnel to the relay and reconnects automatically with exponential backoff if the relay restarts. A request travels this path:
Browser
| https://myapp.yourdomain.com/path
v
Nginx on your VPS (TLS termination)
| http://127.0.0.1:3100
v
Relay server
| wss://yourdomain.com/_proxly/tunnel?secret=...&name=myapp
v
proxly CLI on your laptop
| http://localhost:3000/path
v
Your local dev serverNothing here is magic, and that is the point. The relay never runs your app; it only shuttles bytes between the public internet and a socket your laptop opened outbound — which is why it works behind NAT with no port forwarding, the same trick every reverse tunnel since ngrokd has used.
The "your own domain" half is wildcard DNS plus a wildcard certificate. Setup needs two records:
A yourdomain.com -> <VPS_IP>
A *.yourdomain.com -> <VPS_IP>Each tunnel name becomes a subdomain (myapp becomes myapp.yourdomain.com), and the relay routes by name. TLS comes from a Let's Encrypt wildcard certificate obtained through a DNS-01 challenge — the Docker setup walks you through adding the _acme-challenge TXT record on first run.
Two operational details worth knowing before you adopt it. First, wildcard certs expire after 90 days, and renewal repeats the manual DNS step unless you wire up a DNS-provider plugin like certbot-dns-cloudflare. Second, every tunnel on every project shares one secret (PROXLY_SECRET), so the auth model is "one token per relay," not per tunnel or per user.
The wire protocol is JSON over WebSocket, documented in the README: requests and responses carry base64-encoded bodies with an id for multiplexing, proxied WebSocket traffic gets its own ws-open / ws-message / ws-close frame types (so hot-reload and socket.io-style dev servers work through the tunnel), and ping / pong frames keep idle connections alive. Tunnel targets accept either a port shorthand or a full URL, including self-signed HTTPS backends. Requirements are modest: a VPS with a public IP, a domain with wildcard DNS support, and Node.js 18+ on both ends.
What the model gets right
Start with the money, because the tunnel market in 2026 is priced to annoy exactly this user. ngrok's free tier allows a single endpoint on a random ngrok-free.app domain behind a warning interstitial; the commonly cited 2026 tiers are $8/month for one persistent domain and $20/month before edge configuration enters the picture. A self-hosted relay replaces the meter with flat costs you already pay:
| Setup | Recurring cost | Domain story |
|---|---|---|
| ngrok free | $0, 1 GB/mo | Random domain, interstitial page |
| ngrok Personal | ~$8/mo | One persistent domain |
| ngrok Pro | ~$20/mo | Edge config, still metered bandwidth |
| Proxly on a small VPS | ~$5–6/mo VPS + ~$10–15/yr domain | Unlimited subdomains on your own domain |
The VPS number is not exotic: the going rate for a small instance running a relay plus Nginx is a few dollars a month, and the relay itself is a lightweight Node process. Past that floor, every additional tunnel, subdomain, and gigabyte is free — there is no per-endpoint or per-domain upsell because there is no vendor. For a freelancer sharing client demos weekly, the payback period against ngrok Personal is under a month.
Cost is the least interesting win, though. The best reason to self-host a tunnel is the TLS path: with Proxly, encryption terminates on a VPS you control, and the bytes between relay and laptop travel over a WebSocket you authenticated. No third-party edge ever sees plaintext request bodies, which matters the moment the thing behind the tunnel is a staging API with production-like data, an OAuth callback carrying real tokens, or a webhook receiver echoing customer payloads. Hosted tunnels can promise the same path only by policy; a self-hosted relay gives it to you by construction.
And the developer experience details are right for the job. Subdomains are stable (myapi.yourdomain.com today is myapi.yourdomain.com next sprint), so webhook registrations, OAuth redirect URIs, and mobile-app API base URLs stop churning every time the tunnel restarts. The interactive CLI — project picker, add / delete / reset — is shaped like the ten-minute task it serves: expose this port, share the link, tear it down. Proxly is far from the only tool in this space — Cloudflare Tunnel is free but routes through Cloudflare's edge, and the self-hosted end has years of options from frp and rathole to bore, zrok, and Tunnelmole — but the wildcard-DNS-plus-relay shape it picked is the simplest one that still ends the random-URL churn.
What it structurally isn't
Now the other half of the verdict. Every strength above survives a careful reading of that request-path diagram — and so does the limitation, which is the last two lines of it. Your app runs on your laptop. Close the lid, lose the café Wi-Fi, let the OS sleep, and every public URL goes dark at once.
The relay will faithfully hold its side open and the CLI will faithfully reconnect with backoff, but there is nothing to reconnect to until the laptop and the dev server come back. A tunnel makes your machine reachable; it does not make it reliable.
That single fact cascades into everything a git-push PaaS does that a relay never will:
| Capability | Proxly-style tunnel | Git-push PaaS |
|---|---|---|
| Where the process runs | Your laptop | Platform-operated servers |
| Survives lid close / sleep / roaming Wi-Fi | No | Yes |
| Builds from git | No — you run the dev server | Yes |
| Restarts crashed processes | No | Yes, with health checks |
| Persistent data | No — localhost only | Volumes / managed datastores |
| Scales beyond one machine | No | Horizontal scaling, load balancing |
| Multi-user auth / teams | One shared relay secret | Per-user identity, RBAC, audit |
| TLS | Wildcard cert you renew | Fully managed issuance + renewal |
None of these rows is a criticism of Proxly's engineering. They are category boundaries. A relay has no build pipeline because it never sees your code; it has no health checks because "healthy" is a property of a process on someone else's laptop it cannot restart; it has one shared secret because it was built for one developer sharing with a client, not for a team with joiners, leavers, and an audit trail. Asking a tunnel for zero-downtime deploys is like asking a telephone for voicemail in 1985 — adjacent-shaped, entirely different machine.
The failure mode to internalize is the demo that works perfectly and teaches the wrong lesson. myapp.yourdomain.com looks, behaves, and TLS-locks exactly like a deployed app right up until the laptop sleeps — and because the URL is stable and professional, everyone with the link assumes it is one. The tunnel's polish is what makes the confusion possible. Stable subdomains on your own domain are a feature for sharing and a footgun for anything with an uptime expectation.
When to reach for each
The decision rule fits on an index card: if the thing behind the URL must outlive your laptop being open, deploy it; if the whole point is that it runs on your laptop right now, tunnel it.
Reach for Proxly (or any self-hosted tunnel) when:
- Receiving webhooks during development — Stripe, GitHub, and Twilio callbacks need a stable public URL pointed at code you are actively editing, not a redeploy per change.
- Sharing a live demo or staging preview with a client or teammate for minutes to hours, where "look at what I just changed" beats any deploy pipeline's latency.
- Testing from a real mobile device or another machine on a different network, where
localhostis unreachable and LAN IPs fight firewalls. - Keeping request payloads off third-party infrastructure while still needing public ingress — the self-hosted TLS path is the feature.
Deploy instead when:
- Anyone will open the URL while your laptop is closed, asleep, or offline — which includes every user, every uptime monitor, and every scheduled job.
- The app keeps state: sessions, uploads, a database, or anything that must survive a process restart.
- More than one human operates it, and you need to revoke one person's access without rotating a single shared secret for everyone.
- You need builds, rollbacks, health checks, log retention, or autoscaling — the platform half of the stack a relay deliberately omits.
There is also a legitimate middle path worth naming: tunnel for the dev loop, deploy for everything with a URL that outlives the workday. The two tools compose rather than compete — webhook iteration through Proxly in the afternoon, merged and deployed to always-on infrastructure by evening. The mistake is only ever using one where the other belongs.
Different problems, same subdomain shape
Proxly earns its place in the crowded tunnel market by picking the right simplifications: one relay, one WebSocket per tunnel, wildcard DNS, stable subdomains, and a TLS path that ends on hardware you rent. For local-dev sharing it removes every tax that pushed developers off hosted tunnels — the random domains, the interstitial pages, the per-endpoint meters, the third-party edge in the middle of your request path. What it cannot do is keep running without you, because the computer doing the work is yours.
That is the sentence to carry into every "can we just use a tunnel for this?" conversation: a tunnel puts your laptop on your domain, while a platform puts your app on its own infrastructure. Same URL shape, same padlock icon, opposite promises about what happens when you close the lid. Choose by the promise you need to keep.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



