Exposing Local Development Servers Securely with Tailscale Serve
As developers, we often need to expose local services to other devices—whether that’s for testing on a phone, sharing work-in-progress with a teammate, or running an integration test across machines. Tools like ngrok have been the go-to solution, but there’s a simpler, more secure option if you already use Tailscale: Tailscale Serve.
In this post, I’ll walk through how you can use Tailscale Serve to make a local Dockerized Rails + Ember setup available from your laptop, without editing your docker-compose.yml
.
The Problem: Ports Bound to 127.0.0.1
Take this example docker-compose.yml
snippet:
Both services are bound to localhost only. That means they’re accessible from the host machine, but not from your LAN or other devices on your Tailnet. Changing to 0.0.0.0:3000
would solve that—but sometimes you don’t want to (or can’t) touch your compose files.
The Tailscale Serve Solution
Tailscale Serve lets you proxy a port from your machine to the rest of your Tailnet, without changing your app’s binding. Think of it as a built-in, self-hosted ngrok.
Step 1: Install and log into Tailscale
On your dev machine (e.g., Arch Linux host):
Do the same on your macOS laptop (download from tailscale.com/download).
Step 2: Serve your local services
Forward your Rails app running on localhost:3000:
|
|
And your Ember app on port 4200:
|
|
Step 3: Access from another device
On your Mac (or any device logged into the same tailnet):
- Use the Tailscale IP:
http://100.x.x.x:3000
- Or, if you’ve enabled MagicDNS, use the hostname:
http://archmachine.tailnet-name.ts.net:3000
That’s it. No config changes, no firewall rules, no router port forwards.
Going Further: TLS & Public Sharing
- Want HTTPS? Tailscale can terminate TLS for you:sudo tailscale serve –tls-terminated-tcp 443 tcp://localhost:3000
Now you can visit
https://archmachine.tailnet-name.ts.net/
with a valid cert. - Want to share outside your tailnet? Tailscale’s Funnel feature lets you route traffic from the public internet to your local service, securely and with ACLs.
Why Use Tailscale Serve Instead of ngrok?
- No extra accounts: You already use Tailscale for secure networking.
- End-to-end encrypted: Traffic stays inside your Tailnet.
- Custom hostnames: MagicDNS gives you stable names.
- Multi-device by default: Works across all machines in your tailnet, no tunnels to spin up.
It’s like having a private, secure ngrok alternative baked into your VPN.