I built PeekESP: A physical system-metrics dashboard for remote Linux/Windows machines behind CGNAT (No VPN, No Port Forwarding)
My home server is in my hometown, but I live in Dhaka—a five-hour drive away. For months, answering the simple question "Is it still running?" meant SSHing in when I remembered, seeing everything was fine, and closing the terminal.
The obvious fixes didn't work. The home broadband there is behind CGNAT, so there's no port to forward and nothing can open an inbound connection to that machine. A VPN was the next thought and also wrong: an ESP32 can't join a Tailscale network because it's WireGuard plus a control plane, and none of that has an embedded client.
So I built PeekESP[cite: 1]. It's a tiny ESP32 (LilyGO TTGO T-Display) with a 1.14" display sitting on my desk that shows what my remote machine is doing right now: CPU, RAM, storage, temperature, network throughput, and battery stats[cite: 1].
How It Works
- The Architecture: Both ends dial out to a Cloudflare Worker on the free tier using a Durable Object[cite: 1]. The server pushes, the display polls, and neither needs an inbound port[cite: 1].
-
Zero-Config Pairing: Setup takes one code[cite: 1]. The device shows 10 characters on first boot (e.g.,
K7M2-P4QX-9R), you type them into the desktop app, and the stream ID and auth tokens are derived independently on each side[cite: 1]. The relay never sees it[cite: 1]. No accounts, no ports, no VPNs[cite: 1]. - Multi-Machine Support: One code covers several machines now[cite: 1]. My server and laptop share a single display, and I can just swipe between them using the button[cite: 1].
Behind the Scenes: Two Things That Cost Me a Weekend
- The GPIO 0 Deep Sleep Trap: You can't wake an ESP32 from deep sleep with GPIO 0 because it's a strapping pin[cite: 1]. Held low across a wake reset, the chip boots into the serial bootloader instead of your firmware, making the board look completely dead[cite: 1].
-
Silent Python Failures: My temperature reading was broken for weeks and I blamed Windows[cite: 1]. It was actually a missing import throwing an error into a bare
except, coming back as "this machine has no sensor"[cite: 1]. Bare excepts hide exactly the bugs you'd most want to see[cite: 1].
Tech Stack
- Microcontroller: ESP32 (LilyGO TTGO T-Display)[cite: 1]
- UI & Firmware: Arduino IDE / PlatformIO, LVGL 8.3[cite: 1]
- Relay: Cloudflare Worker (Free tier)[cite: 1]
- Agents: Dependency-free Python for Linux (DietPi) and Windows[cite: 1]
- License: MIT[cite: 1]
You can check out the source code, flashing scripts, and setup guides here:
👉 github.com/shouravx/PeekESP




Top comments (0)