I run a humble home lab with Proxmox, Home Assistant, Raspberry Pi, a NAS, and computers. When I’m traveling, I need to SSH into one of those machines. But I don’t want to expose anything to the internet. That’s why I picked an ESP32-S3 to access my home devices from anywhere.
Let me be upfront: this ESP32-based VPN gateway is meant for lightweight functions. It is not a high-speed VPN gateway that can route all the network traffic. With that out of the way, I wanted an always-on, low-power solution that lets me SSH into my home server, Raspberry Pi, or other devices on my LAN. Thanks to MicroLink project on GitHub, it is possible.
With some effort, the $10 ESP32-S3 running Tailscale turned out to be exactly what I needed and the coolest addition to my home lab in a while.
Is Tailscale the safest way to access your home network remotely?
Tailscale is easy to set up, but is that trading off your security?
Why an ESP32 over a Raspberry Pi
Does one job reliably
The idea is to use a single Tailscale device rather than installing the client on every machine on the home network. Anyone can ask: why not use a Raspberry Pi instead of an ESP32?
The Pi can run the official Tailscale client, and takes less than 10 minutes to set up on Linux. But using an SBC like a Pi just to run a Tailscale entry point is overkill. Even a Pi Zero W works. I had an ESP32-S3 lying around and got curious about whether it was up to the task.
The ESP32 draws about 0.5W of power compared to a Pi’s 1.5W. Considering I plan to run an ESP32 as an always-on device, the overall consumption adds up and is still lower than a Pi’s. Also, there’s no Linux or OS to maintain or update.
Unlike the Raspberry Pi, there’s no risk of a microSD card corrupting. The ESP32 boots in two seconds, while a Pi-based system takes at least 30 seconds to boot, even in a headless setup running on an NVMe SSD.
My primary reason for choosing an ESP32 for the task was that it connects to Tailscale and sits quietly on my home network. As a dedicated entry point, it ensures reliability with simplicity, which is much better than running a full Linux environment that is otherwise underutilized.
What makes the ESP32 work as a VPN gateway
Simple resource-efficient project
The MicroLink project on GitHub enables the use of Tailscale on ESP32. It is a Tailscale-compatible VPN client that implements WireGuard encryption, Noise protocol handshake for authentication, Tailscale’s DISCO protocol for discovering peer machines, and HTTP/2 over encrypted transport. It’s a real implementation of all that, running bare metal on FreeRTOS.
Honestly, getting the MicroLink project to work on my ESP32-S3-N16R8 model took a few hours. I cloned the MicroLink project into my project directory as a component. I used a reusable Tailscale Authentication key so the ESP32 can authenticate without an interactive interface.
The major hurdle was ensuring sufficient headroom for TLS handshakes. For that, I enabled PSRAM properly, so that MicroLink had sufficient memory to work with it. Once I sorted that out, the device used Auth keys to register and even had a VPN IP appear in the Tailscale admin console, along with other devices.
Using ESP32 to access and wake up machines
No need to install Tailscale everywhere
Once the ESP32 joins my Tailscale network, I use it as an SSH jump host to reach any machine on my home LAN.
For example, ssh -J tsd samir@192.168.1.5 lets me log into my Raspberry Pi from anywhere. Here, tsd is the ESP32 device name, and the IP is the target machine’s IP address.
When the machines are powered off or in sleep mode, I use Wake-on-LAN to nudge and wake them up. Here’s the command I use to send a magic packet and wake up a machine on my home LAN:
curl "http:///wol?mac=AA:BB:CC:DD:EE:FF"
Since MicroLink lacks an SSH server at the time of writing, I run a lightweight HTTP server on ESP32 instead for Wake-on-LAN functionality.
Living with a few shortcomings
Things to consider
The idea wasn’t to build a high-speed VPN for data transfer or for streaming 4K content. The real-world speeds are only a couple of Mbps. So copying a large file or viewing a camera feed will stress the connection.
Bumping the duration from 3000 milliseconds to 6000 milliseconds to let Tailscale use STUN servers to discover the public IP for peer-to-peer situations helped fix timeout issues. I switched the DISCO socket binding to port 51821 since WireGuard uses port 51820. Finally, I forced the heartbeat to always skip, so that Tailscale stops closing connections every 2 seconds.
The updated code is available on my GitHub page for flashing and further testing.
Stop port forwarding your self-hosted services: Do this instead
Say goodbye to the hassles of port forwarding with this secure, easy-to-use alternative.
Always-on, low-power VPN gateway hardware
Honestly, ESP32 isn’t replacing a full-blown VPN router, and it wasn’t ever meant to. For my use case, I needed a single entry point to SSH into my home lab and wake up my home machines remotely. I managed to do that at a fraction of the power and cost of popular Linux-based alternatives.
The MicroLink project does the heavy lifting of providing a Tailscale client for ESP32, and adding a Wake-on-LAN server would add value to my purpose. If you have an ESP32-S3 lying around, flash this code and turn it into a weekend project for your home lab.