Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungLINQ GroupBy: The Operator Everyone Uses Wrong(23.09.2026 um 09:41 Uhr)
Sichere ProgrammierungIT Heard About the Acquisition Nine Days Before It Closed(23.09.2026 um 09:45 Uhr)
Sichere ProgrammierungThe Story Behind Building NuvyntraLabs(23.09.2026 um 09:45 Uhr)
Sichere ProgrammierungFive dashboards nobody was opening(23.09.2026 um 09:46 Uhr)
Sichere ProgrammierungThe Shift from AI Insights to AI Actions in Finance(23.09.2026 um 09:47 Uhr)
Sichere ProgrammierungGo WebAssembly Meets WebForms Core 2.1(23.09.2026 um 09:49 Uhr)
Sichere ProgrammierungJust One More Round: Scope Creep in the Age of AI Agents(23.09.2026 um 09:50 Uhr)
Sichere ProgrammierungThe Calls That Reach Us Now Are the Ones the Model Could Not Answer(23.09.2026 um 09:50 Uhr)
Sichere ProgrammierungOne Loop Made Four Hundred Round Trips(23.09.2026 um 09:52 Uhr)
Sichere ProgrammierungThe order was committed and nothing else ever heard about it(23.09.2026 um 09:53 Uhr)
Sichere ProgrammierungLINQ GroupBy: The Operator Everyone Uses Wrong(23.09.2026 um 09:41 Uhr)
Sichere ProgrammierungIT Heard About the Acquisition Nine Days Before It Closed(23.09.2026 um 09:45 Uhr)
Sichere ProgrammierungThe Story Behind Building NuvyntraLabs(23.09.2026 um 09:45 Uhr)
Sichere ProgrammierungFive dashboards nobody was opening(23.09.2026 um 09:46 Uhr)
Sichere ProgrammierungThe Shift from AI Insights to AI Actions in Finance(23.09.2026 um 09:47 Uhr)
Sichere ProgrammierungGo WebAssembly Meets WebForms Core 2.1(23.09.2026 um 09:49 Uhr)
Sichere ProgrammierungJust One More Round: Scope Creep in the Age of AI Agents(23.09.2026 um 09:50 Uhr)
Sichere ProgrammierungThe Calls That Reach Us Now Are the Ones the Model Could Not Answer(23.09.2026 um 09:50 Uhr)
Sichere ProgrammierungOne Loop Made Four Hundred Round Trips(23.09.2026 um 09:52 Uhr)
Sichere ProgrammierungThe order was committed and nothing else ever heard about it(23.09.2026 um 09:53 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

WireGuard at scale: setup is solved, operations aren't

Setting up a WireGuard server in 2026 is trivial. AI writes the wg0.conf, docker compose up and wg-easy is running in a minute, generating peers takes one click. The hard part hasn't been setup for years. The hard part is what happens…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Setting up a WireGuard server in 2026 is trivial. AI writes the wg0.conf, docker compose up and wg-easy is running in a minute, generating peers takes one click. The hard part hasn't been setup for years.



The hard part is what happens after the second server.



The moment you have two, the friction shifts. It's no longer about commands or configs. The questions change. Who has access to what? When was this peer issued? Whose pubkey lives where? How do I revoke a contractor in one place? Setup is solved. Operations are not.



By the time my "one server" had quietly turned into several, I was managing them through separate dashboards with credentials in separate password manager entries. The fleet just... happened. Not because anything was hard. Each addition was a 30-minute task that made local sense, and the tools around WireGuard kept treating "one server" as the unit of operation.



Multiple servers, multiple teams, no shared state. No central place to answer the basic question: who has access to what.



Below: where every WireGuard admin tool falls off the cliff at server 2, and what I ended up building when nothing existing scaled.






TL;DR




  • Most WG admin UIs (wg-easy, wg-portal, WireGuard-UI) work great for one server. Past that, you have N independent dashboards and no shared state.

  • The platforms that do scale (Tailscale, NetBird, Firezone post-1.0) solve a different problem (mesh/ZTNA), not classic publicly addressable WG fleets.

  • Nobody's solving the gap I was sitting in: many hub-and-spoke WG servers, central operator UI, REST API on each box.

  • I split it into a Console (central source of truth) and a Node (per-server REST agent). Two-node walkthrough below.






How a bastion becomes a fleet



I've heard versions of this story from enough people now that I'm pretty sure the path is universal. It starts the way mine did: one VPN server, because it beats exposing SSH or internal APIs to the public internet. Then something forces a second, and the trigger is almost never architectural. It's stuff like:




  • Staging is reachable by all engineers; prod-write only by SRE. Two networks, two policies, two servers.

  • Compliance carved off a data-VPC, and that one needs its own access controls because the auditor will ask.

  • An acquisition or partnership brings somebody else's networks into the picture, and now you're keeping their VPN running too.



None of these felt like a project. Each one was a 30-minute task. That's the trap: my unit of operation was "one server," and every tool around WireGuard was designed around that same unit. New container in two commands. Peer generated through the UI in a click. Config sent to the user via Slack DM or 1Password share, whichever's lying around. Done. Move on.



For me, the moment I realized I was in a fleet wasn't about the count. It was a Tuesday in January when a contractor's project wrapped and I had to revoke her access. Her pubkey was scattered across multiple wg0.conf files, two Ansible inventories, and one wg-easy database. There was no clean way to find every place it lived, let alone log what actually got removed. After that, "one server at a time" stopped looking like a strategy. It looked like technical debt I'd built on purpose, and was now stuck maintaining.



That's where the existing tools start cracking.






What I tried, and why each one cracked



Writing my own thing was the last option, not the first. I went through everything else I could find. Table for skimmers, longer breakdown after.




































Tool Where it broke for me
wg-easy, wg-portal, WireGuard-UI Single-server UIs. Past server #2, you have N independent dashboards with no shared state
Firezone (1.0+) Pivoted to a full ZTNA platform. Heavier than the problem deserved
Tailscale, Headscale Mesh, not hub-and-spoke. Solves a different problem
NetBird, Defguard Same family as Tailscale, same answer
pfSense / OPNsense WG inside a firewall appliance. Not viable for cloud VMs
Ansible / Terraform Operator UX is a PR pipeline, not a UI


wg-easy. It's great for what it is. One server, one Docker container, one web UI. I ran it for months on a single box and was happy. Adding a second node gave me two completely independent dashboards with no shared state. Issuing a peer now meant deciding which dashboard, remembering its admin password, and tracking the assignment somewhere outside the tool. Three nodes in, my "somewhere outside the tool" was a Notion page that lied to me twice a week.



wg-portal, WireGuard-UI, and friends. Same architectural shape. Single-server UIs, some prettier than others. None of them are control planes. They're admin panels.



Firezone. I was excited about Firezone for a stretch. Somewhere around their 1.0, though, it pivoted from "nice WireGuard admin panel" to a full ZTNA platform: identity providers, policy engine, gateway model, deeper Kubernetes integration. Probably the right direction for them as a company. But my mental model is still "I have these WG boxes, please let me edit their peers from one screen," and Firezone got too heavy for that.



Tailscale and Headscale. Completely different model. Mesh, not hub-and-spoke. Every node knows every node, NAT traversal happens through DERP relays, and the "exit node" abstraction replaces the idea of a regional egress server. I use Tailscale for my own devices and it's lovely for "connect my laptop to my home server." But once the requirement becomes "user traffic has to egress from a known public IP in country X," or "give a contractor access to a specific VPC without installing a Tailscale agent on their machine," the mesh model is solving a problem I don't have. My nodes are already publicly addressable. That isn't a constraint I'm trying to work around.



NetBird, Defguard. Same family as Tailscale. Overlay networks with identity baked in. Same answer for the same reason.



pfSense / OPNsense. WireGuard is a feature of the firewall. Lovely if your edge is already pfSense. If it isn't, putting pfSense on every cloud VM just to get a UI is not the move.



Ansible / Terraform. They work, in the sense that I can make YAML or HCL do almost anything if I'm stubborn enough. But turning "create a peer" into a pull request with a 30-second pipeline is not the operator UX I want, and git log is not an audit trail I want to read at 2 a.m.



What I noticed after going through all of them: each tool either solves a smaller version of my problem (one server) or a structurally different one (mesh/ZTNA). The gap I was sitting in (classic hub-and-spoke WireGuard servers, several of them, with one place to manage peers) just wasn't anybody's target.






The pattern that worked



After the third time I almost wrote a wg-easy fork that supported multiple backends, I split the system properly. Two services:





  • Console. Central control plane. Web UI, database, and the only thing I touch as an operator. Holds the inventory of nodes, peers, and who got issued what and when.


  • Node. Runs on each WG server. Owns the local wg interface and the address pool. Exposes a REST API that the Console calls over an API key.



Diagram



A few things this split bought me that a single binary couldn't:





  1. Console outage doesn't kill the VPN. Nodes keep serving existing peers. They can optionally persist their peer store on disk, so they survive a reboot even with the Console offline.


  2. One pane of glass without tight coupling. Adding a node is running another container and pasting its API endpoint and key into the UI. No shared database, no orchestrator dependency, no service mesh.


  3. The API is the API. Anything the UI does, a script can do. No part of operations requires SSH-ing into a box to run wg set.


  4. Node upgrades don't lose peer state. Peer store is decoupled from the binary version.



It's the same control-plane pattern Kubernetes and friends have used for years. The reason it doesn't show up in small infra tools is simple: nobody's first server needs it, and by the time the second one shows up, you've already started building the wrong way.






A two-node minimal setup



Here's what that looks like end-to-end. Console on one machine, two Nodes on two others. This is WGKeeper, the thing I ended up building: AGPL-3.0, Docker images on GHCR, full walkthrough in the Quick start docs. What's below is the compressed version, just enough to convey the shape.



Console — anywhere reachable from your browser; your laptop works for a first try.



First, generate a secret key for session signing (keep it stable across restarts — rotating it invalidates all sessions):




openssl rand -hex 32






Then drop the output into SECRET_KEY below:




# docker-compose.yaml
services:
wgkeeper-console:
image: ghcr.io/wgkeeper/console:latest
container_name: wgkeeper-console
ports:
- "8000:8000"
environment:
PORT: 8000
DATABASE_URL: file:/app/data/wgkeeper-console.db
SECRET_KEY: REPLACE_WITH_OUTPUT_OF_openssl_rand_hex_32
BOOTSTRAP_ADMIN_PASSWORD: change-me-now
COOKIE_SECURE: "false"
volumes:
- wgkeeper-console-data:/app/data
restart: unless-stopped
volumes:
wgkeeper-console-data:






Node runs on each WireGuard server. Let's call them de-1 and nl-1. Each one needs its own config — and its own API key. Generate one per node with the same command:




openssl rand -hex 32






Then put it into config.yaml:




# config.yaml
server:
port: 51821
auth:
api_key: "REPLACE_WITH_OUTPUT_OF_openssl_rand_hex_32"
wireguard:
interface: "wg0"
subnet: "10.10.0.0/24" # different /24 per node
server_ip: "10.10.0.1"
listen_port: 51820
routing:
wan_interface: "eth0" # check with `ip route` — varies by cloud









# docker-compose.yaml
services:
wireguard:
image: ghcr.io/wgkeeper/node:latest
cap_add: [NET_ADMIN, SYS_MODULE]
volumes:
- ./config.yaml:/app/config.yaml:ro
- ./wireguard:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821"
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv4.ip_forward=1
restart: always






Bring up the Console, then both Nodes. In the Console UI, click Nodes → Add node twice. Paste each Node's API endpoint and its API key, click Check node to verify connectivity, then Save node. Both should flip to online within seconds.



The Nodes list is the main operator view. Every connected node shows its status, running version, and whether an update is available. Same UI handles two nodes or twenty. You see what's running, what's stale, what's unreachable, in a single screen.



WGKeeper console



Click any node to drill into it. The Peers tab is where most operational work lives: issuing access, revoking it, checking who's actually connected versus who just has a config sitting around. Every peer shows its allowed IPs, public key, status, last handshake, creation date, and expiry. Revocation is one click. This is the audit trail that was missing the day I had to chase that contractor's pubkey across multiple files and databases.



WGKeeper console peers



To create a peer on de-1: the Console allocates an IP from de-1's 10.10.0.0/24, generates the keypair, and hands you a wg-quick-compatible config to deliver to the user. Same flow on nl-1 produces a config in a different subnet. One operator UI, two regions, no SSH involved anywhere.



For anything past a tinker setup (TLS in front of the Console, HTTPS for the Node API, wireguard.peer_store_file so peers survive reboots, the per-node Prometheus endpoint feeding the bundled Grafana dashboard), see the docs.






What WGKeeper is not



A few things to be direct about, because it saves time:





  • No SaaS. You self-host both Console and Nodes.


  • Not a Tailscale clone. No mesh, no NAT traversal, no DERP relays. Nodes need to be publicly reachable on UDP. Clients are plain hub-and-spoke peers using the standard WireGuard client.


  • Not a ZTNA platform. No identity providers, no per-app policies, no device posture. If those are hard requirements, Firezone or Defguard fit better.


  • Not a firewall. It manages WireGuard. The nftables rules around it are still on you.


  • No magic. The Node uses wireguard-tools under the hood. You still need to understand WireGuard.



If any of those are dealbreakers, good. You saved an evening.






Where it fits



WGKeeper is for people whose problem reduces to: "I run multiple publicly addressable WireGuard servers and I want one place to manage their peers."



The shapes I see most often:





  • Cloud bastions across regions. Separate VPCs in eu-central-1, us-east-1, and friends, each with its own access list.


  • Per-environment isolation. Separate WG networks for prod, staging, dev, or for compliance-isolated data VPCs that have their own audit requirements.


  • MSPs and agencies running per-client isolated WireGuard environments across providers.


  • Homelab fleets with regional egress nodes for streaming, latency-sensitive games, or country-locked APIs.


  • Self-hosters sharing access with family or friends across multiple boxes, plus anyone who outgrew per-server wg-easy installs as the fleet grew past one or two.



Where it doesn't fit: single-server setups, where wg-easy is straight-up better since it's less to run. Anything mesh-shaped (use Tailscale or NetBird). And anywhere identity-aware policy is the hard requirement (Firezone, Defguard).






Why AGPL?



AGPL-3.0, because I want the project to stay open. If you're self-hosting WGKeeper, or running it on company infrastructure, the AGPL part doesn't really apply to you. It behaves like the GPL: nothing new to worry about. What the AGPL actually targets is anyone tempted to wrap WGKeeper into a hosted SaaS without contributing back. Modifications have to come upstream. That keeps the door open for the project to grow as a community thing instead of as someone's closed fork.






State of the project



WGKeeper lives at wgkeeper/wgkeeper on GitHub. That's the umbrella repo, with links to the Console and Node component repos. Docs are at wgkeeper.github.io: install guides, configuration reference, the Grafana dashboard, the API reference. Docker images on GHCR.



Honestly: this is a side project. Built and maintained in spare time. No startup behind it, no roadmap deck, no investor narrative. The GitHub org isn't bigger than it looks. I'm posting this because for a project like this to find the people it could actually help, those people have to randomly read about it, and that's not happening on its own.



It's early. There are rough edges I know about, and probably some I don't. If the problem I described matches yours, I'd love issues, feedback, and especially "this is the part I expected to work and it didn't" reports. PRs welcome too. Review can take a while since the team is small, but the bar isn't high and the codebase isn't scary.






Project links



Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten WireGuard at scale: setup is solved, operations aren't

Thematisch verwandte Begriffe: WireGuard, scale, setup, solved · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-96258 | A vulnerability has been found in onSite internet GmbH Auktion NG Auktio…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick