ESP32 and VPNs: server, client, or no VPN at all
The usual reason to want a VPN on an ESP32 is simple: reach its web page or its API from somewhere else, safely. There are four ways to get there, and only one of them puts the VPN on the ESP32.
An ESP32 as a VPN server
A VPN server waits for clients to connect to it, so it has to be reachable from the internet: a public IP address and a forwarded port on the router in front of it. That is exactly what an ESP32 behind someone else's router, a 4G modem or carrier-grade NAT does not have. If you can forward a port to the ESP32, you can already reach its web server directly, and the VPN only adds encryption on top. In practice it is not done: the server side belongs on something with more memory, on the edge of the network.
A WireGuard client on the ESP32
The other way round works. The ESP32 connects out to a WireGuard server you run (a small VPS, or your home router), and anyone on that VPN reaches the device by its VPN address. There is a community WireGuard implementation for ESP-IDF; Tailscale and ZeroTier have no official client for the ESP32.
- You run the server: a machine with a public address, kept up and patched.
- You manage keys: one key pair per device, added to the server's configuration, and removed when a device is retired.
- You reach it only from the VPN: your laptop and phone need the VPN too, and so does anyone you want to show the device to.
- Keepalives: behind NAT the tunnel needs a packet every 25 seconds or so to stay open, which matters on metered 4G.
It is a reasonable choice for a handful of devices you own, on networks you know.
The VPN on the router or a Raspberry Pi
If the devices sit on a network you control, put the VPN on the router, or on a Raspberry Pi on the same network acting as a subnet router (Tailscale and WireGuard both do this). The ESP32 runs nothing extra and keeps all its memory, and you reach every device on that network by its local address. This is the best answer at home or in your own building. It does not help with a device on a customer's network, where you cannot install anything next to it.
No VPN: an outbound tunnel
The device opens one outbound connection to a service, and the service gives its web page a public HTTPS address. Nothing is opened on the router, nothing runs next to the device, and nobody needs a VPN client to open the page: a browser is enough, with sign-in or a share link deciding who gets in. This is what Pinscope does. Its connection uses the Noise protocol, the same family of handshake WireGuard is built on, in 9.4 KB of RAM, and the same connection carries the device's logs, crash reports and firmware updates.
Which one
| Works on someone else's network | Runs on the ESP32 | To open the page | |
|---|---|---|---|
| ESP32 as VPN server | No: needs a forwarded port | A VPN server | VPN client |
| WireGuard client on the ESP32 | Yes | WireGuard | VPN client, and a server you run |
| VPN on the router or a Pi | Only where you can add the router or Pi | Nothing | VPN client |
| Outbound tunnel (Pinscope) | Yes | One component | A browser |
For more on the trade-offs between tunnels, see port forwarding, ngrok, Cloudflare Tunnel and Tailscale compared.
Try it
Three devices are free, and no card is needed. Create an account, or read the five-minute guide first.
More
- Remote access to an ESP32 without TLS: what it measured and what it costs
- Reaching an ESP32 web server from outside its network
- Updating ESP32 firmware over the internet, with rollback
- Guru Meditation Error: decoding the backtrace, and crashes from the field
- Remote logging: ESP_LOG without a serial cable
- Heap and stack monitoring in the field
- An ESP32 behind CGNAT, 4G or Starlink
- TLS memory usage on the ESP32, and how to reduce it
- Sharing an ESP32 sensor page with anyone, without port forwarding
- ArduinoOTA over the internet, with a rollback
- ESP32 remote access compared: port forwarding, ngrok, Cloudflare Tunnel, Tailscale
- esp_http_server slow? The 250 ms delay and the fix
- Before the first ESP32 ships: a field support checklist
- ESP32 exception decoder: a Guru Meditation backtrace to lines, in the browser