I enjoy self-hosting a variety of services, including my photo collection, document management system, smart home setup, and password manager. To access these services securely from outside my home, I use WireGuard VPN.
While this works well for my own devices, inviting others to use my systems can be quite a hassle.
The main reason I invite friends to join my home VPN is to play on our Factorio server, which I also host locally. This requires me to share the WireGuard client installer, guide them through the setup, distribute configuration files, and help with the connection process.
Therefore, I wanted a simple solution that anyone could use without requiring technical knowledge. My idea was to build a lightweight Windows GUI that comes preloaded with the necessary configuration files and includes only the most essential features.
I explored several ways to control WireGuard from my own Windows application. The simplest method I found was using the command-line interface provided by wireguard.exe
:

Using the information from this output together with some own research, I was able to implement a custom interface to Wireguard in C++:
void MainWindow::slotSetup()
{
runWireguardWithAction("/installmanagerservice");
}
void MainWindow::slotConnect()
{
runWireguardWithAction(
std::format("/installtunnelservice \"{}\\autoconnect.conf\"",
std::filesystem::current_path().string()));
}
void MainWindow::slotDisconnect()
{
runWireguardWithAction("/uninstalltunnelservice autoconnect");
}
What took me the most time to figure out was that the /installtunnelservice
command requires an absolute path to the configuration file.
I built a simple GUI using Qt6 with some convenient features—such as disabling buttons based on the service status.
void MainWindow::updateUI()
{
// windowsServiceExists: Small custom method based on the Windows API
const auto managerServiceExists = windowsServiceExists("WireGuardManager");
const auto tunnelServiceExists = windowsServiceExists("WireGuardTunnel$autoconnect");
m_pMainWindow->buttonSetup->setEnabled(!managerServiceExists);
m_pMainWindow->buttonConnect->setEnabled(!tunnelServiceExists);
m_pMainWindow->buttonDisconnect->setEnabled(tunnelServiceExists);
}
The Result
The result is a small program that I can distribute along with WireGuard, a configuration file, and a few DLLs in a compact ZIP file. Now, my friends can easily connect to my home network without needing to install or configure anything.
Many thanks to Flo for his hard work as a beta-Tester.