Why I Didn’t Build a Custom VPN App: What WireGuard Gave Me and Where the Real Problems Started
Lessons from building a small VPN service around standard WireGuard clients instead of a proprietary app When you look at a commercial VPN product, the app seems to be the product: a polished interface, a country list, and a large Connect button. I chose the opposite approach. Instead of building another VPN client, I decided to give users a standard WireGuard configuration that they could import into an existing client. That decision removed a lot of client-side work — but it also exposed where the real complexity of a VPN service actually lives. Why build another app if WireGuard already has one? The usual commercial VPN flow is straightforward: install the vendor's app, sign in, choose a location, and connect. A proprietary client can manage server selection, subscriptions, kill switches, automatic reconnects, diagnostics, updates, and support in one place. But for a small service with one or a few locations, I had to ask a more basic question: do I really need to build and maintain a separate Windows, macOS, Android, and iOS client just to establish a WireGuard tunnel? WireGuard already has mature clients across the major desktop and mobile platforms. A user can import a configuration file or scan a QR code and get a normal VPN toggle. On paper, that looked like a very attractive tradeoff: less client code, fewer update mechanisms, fewer installers, and a smaller attack surface to maintain. What I underestimated was that the app was never going to be the hardest part. A .conf file is not just a settings file The first architectural lesson was simple but important: a WireGuard configuration is effectively a credential. It contains the client's private key. A QR code that represents the same configuration contains the same sensitive material in another form. That immediately creates product problems that have nothing to do with the tunnel itself. How do you show the configuration safely? What happens if the user loses it? Can you issue a replacement without leavin