tech · privacy · tutorial3 min

a tunnel of my own

replacing ngrok with frp on my own server, so tunnel 3000 app1 gives me https://app1.frp.jopcmelo.dev, and the plot twist that came right after.

every now and then I need something on my machine to be reachable from the internet: a webhook to test, a demo to share, an app to open on my phone. ngrok does that, and it just works.

what I wanted was my own subdomains, a few tunnels at once, and nothing to pay for a tool I use a few times a month. ngrok's free plan gives you one domain, picked for your account, and no custom ones. so I looked for something to host myself, and found frp: "a fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet."

#how it works

frp comes in two halves. frps, the server, runs somewhere public, like a VPS. frpc, the client, runs on my machine and opens a connection out to the server. when a request comes in for one of my subdomains, the server sends it back down that connection to whatever's running locally. my machine never accepts a connection, it only opens one, which is why it works behind a router or a firewall.

#the server

I deploy things on my VPS with Coolify, so I wrapped frp's Docker image with the config I needed: joaopcm/frp-docker-deployment. it takes three environment variables: FRP_TOKEN, DASHBOARD_USER and DASHBOARD_PWD.

only port 7000, where clients connect, is exposed directly. the subdomains go through Traefik, which Coolify sets up, and that's where the SSL certificates come from.

#the client

I didn't want a config file per tunnel, so I added a tunnel command to my shell. it writes a temporary frp config, pulls the token from 1Password so it's never written down anywhere, and starts frpc:

tunnel 3000 app1

and localhost:3000 is at https://app1.frp.jopcmelo.dev, with SSL. app2 and app3 can run at the same time. it's more setup than ngrok, once, and then every tunnel after that is one command.

#the plot twist

right after I finished writing this, Rehan mentioned he uses Tailscale Funnel. I'd always thought of Tailscale as just a VPN. turns out Funnel routes traffic from the internet to a service on your machine, and creates the HTTPS certificates for you, on a ts.net address. so you probably don't need any of this. the URLs live under your tailnet's name instead of your own domain, and Funnel is still in beta, but for most of what I used ngrok for, it's enough.

but hey, now I know how a reverse tunnel works.