If you don’t need identity controls (using a fixed node configuration), you can always use vanilla Wireguard without the user management. You don’t get a NAT traversing mesh, but if your nodes are visible to the net, you do get direct node to node networking. If you only have one node directly visible, you can also use that as a gateway.

I like these more traditional VPN style use tools for Wireguard, but you can always use the lower level version itself, if you’re comfortable with the configuration limitations.

vanilla Wireguard without the user management

That is how I use Tinc today. I briefly tried Wireguard but it works very much like OpenVPN and Strongswan in that it does not have dynamic mesh routing. Privacy advantages aside, the dynamic mesh routing I get from Tinc works around internet outages, albeit slower than I would like but a 2 minute routing outage is still better than {n} time it takes for ISP's to manually work around fiber breaks and datacenter network changes gone-wrong. But that is just my preference, it certainly isn't for everyone. I could probably accomplish this in Wireguard using weighted routing table rules but that gets complicated and messy very fast and I just lazy enough to avoid this. Perhaps someone has created an Ansible playbook that calculates all the routing rules and weights for this setup but I have not actually looked for it.

That said I can layer things on top of Wireguard, OpenVPN and Strongswan that accomplish similar goals such as using HAproxy but then protocol support is limited whereas a dynamic mesh in Tinc allows all TCP/UDP for my needs.

You may be interested in Innernet

https://github.com/tonarino/innernet