Because sometimes, the real challenge isn’t writing the code, it’s finding the perfect balance between portability and productivity.
The Real-World Setup
As a software engineer, I split my workflow across two worlds:
- MacBook Pro → my portable dev machine, where all my codebases live.
- Windows desktop → my home lab powerhouse, complete with multiple screens and a ton of processing muscle.
When I’m out, the Mac keeps me agile; I can code anywhere.
When I’m home, the Windows setup gives me that speed boost and screen-estate to research, debug, and test faster.
But there was a catch.
The Problem
The app I run on my Mac is only accessible at:
http://localhost:3000
To test it from my Windows workstation (on the same Wi-Fi network), I expose it to my local network by binding it to the Mac’s LAN IP:
http://192.168.x.x:3000
That way, I can open the app from any device connected to my home network, including my Windows PC.
Now here’s the twist:
I already had Ngrok installed on my Windows machine, not the Mac. I didn’t want to clutter my Mac’s environment with another dependency just to share or tunnel my dev app.
So the goal became:
Use Ngrok on my Windows PC to expose my Mac’s running app, via its LAN IP.
That meant tunnelling the local network address, not the localhost one.
Here is how!
Step 1 — Make Sure the App Listens on the LAN Interface
If you’re running a dev server, by default, it probably listens only on 127.0.0.1, meaning no one else (not even your Windows machine) can see it.
Check it
On your Mac terminal:
sudo lsof -i :3000
If it says:
TCP 127.0.0.1:3000 (LISTEN)
…that’s localhost-only.
Fix it
Start your app bound to 0.0.0.0 (all interfaces):
# Node.js
npm run dev -- --host 0.0.0.0
# Python
python3 -m http.server 3000 --bind 0.0.0.0
# Flask
flask run --host=0.0.0.0
Now it’s reachable both locally and across your home network:
http://localhost:3000
http://192.168.x.x:3000
Step 2 — Tunnel That LAN IP from Windows
With your Mac app accessible over LAN, move to your Windows machine (same Wi-Fi).
Open PowerShell or CMD and run:
ngrok http 192.168.x.x:3000
Ngrok creates a secure tunnel from your Windows machine to the app running on your Mac.
You’ll instantly get a public HTTPS link like:
Forwarding https://randomstring.ngrok.io -> http://192.168.x.x:3000
From there:
- You can test mobile webhooks.
- Preview your app remotely.
- Share it with teammates or clients.
All without installing anything on your Mac.
Why This Setup Works So Well
This approach merges two workflows perfectly:
| Role | Device | Benefit |
|---|---|---|
| Portable coding | Mac | Keeps your environment lightweight, codebases intact |
| Performance testing | Windows | Leverages better screens and CPU for analysis |
| Public exposure | Ngrok on Windows | No duplication of setup or tokens |
It’s the best of both worlds: portable dev, stable network tunnelling.
Bonus: Make Ngrok Persistent
If you expose the same service frequently, automate it with a config file on your Windows system:
~/.config/ngrok/ngrok.yml
version: "2"
authtoken: YOUR_NGROK_AUTH_TOKEN
tunnels:
mac-app:
addr: 192.168.x.x:3000
proto: http
Then start it anytime:
ngrok start mac-app
If you’re on Ngrok Pro, set:
subdomain: mymacapp
to get a stable URL like:
https://mymacapp.ngrok.io
Common Pitfalls
| Symptom | Cause | Fix |
|---|---|---|
connection refused |
App bound to 127.0.0.1 only | Restart app with --host 0.0.0.0
|
| “Tunnel established” but blank page | Wrong LAN IP | Run ipconfig (Windows) or ifconfig (Mac) to confirm |
| Firewall blocked | macOS firewall restrictions | Allow incoming connections for your dev app |
| Ngrok error: “connection timed out” | IP mismatch or wrong port | Double-check your local IP and port |
Lessons Learned
The beauty of this setup is subtle but powerful:
It’s not about Ngrok or the tunnel; it’s about designing a workflow architecture that fits your real life.
- Keep your Mac portable.
- Keep your Windows setup powerful.
- Let Ngrok bridge the two worlds.
When your workflow mirrors your lifestyle, productivity stops feeling forced; it starts flowing naturally.
This little hack gave me full access to my dev environment anywhere, while keeping my core setup lightweight and efficient.
It’s also a reminder that dev ops doesn’t always need to be “cloud-native” — sometimes, it’s just about connecting two good machines smartly.
I’m Elijah Haastrup, a software engineer who loves blending practicality with clean architecture.
If you enjoyed this write-up, let me know if you have any suggestions or questions in the comments.
You can reach me on LinkedIn and Twitter: killcodeNG. I share stories and systems that make software development simpler, faster, and saner.
Top comments (0)