easywireguard (ewg)
Canonical: gitlab.com/safteinzz/easywireguard · Mirror: github.com/safteinzz/easywireguard
Mesh, minus the mess. 🕸️
A tabbed, human-readable TUI and a flag-driven CLI for scripts, in one small binary.
Manage live interfaces, describe a whole hub-and-spoke or full mesh in a single
manifest, and onboard a phone by scanning a QR. Pure Rust, so no wg binary is
needed for keys or config generation.
Manage every interface
Legend: ● up running · ○ down stopped · ⏻ boot starts on boot
Bare ewg opens on the interface manager: every .conf across the dirs you
registered, with its live state. ↵ toggles one up or down, c creates one in
your $EDITOR (paste a provider config and it is validated before it lands), e
edits, d deletes it keeping a .bak, b flips start-on-boot, and i inspects
it with a live wg show when it is up.

See the whole mesh
Describe each node once and ewg lays them out hub-and-spoke, spokes nested under
the hub they dial. A hub has an endpoint and meshes with every other hub; a spoke
has none and lists only its hub, so phones never get useless peer blocks for each
other. Each node's .conf is then generated as exactly the peers it should reach.

By default a node advertises just its own /32. Set allowed-ips to 0.0.0.0/0
to make a hub a full-tunnel exit, or to a LAN subnet for site-to-site.
Create a node without touching a key
c opens a wizard (or e to edit an existing node): pick Spoke or Hub,
fill a couple of fields, and ewg generates the keypair for you. Choose store
to keep the private key in the manifest so you can re-export a working config
later, or redact so it lives only in the QR and file handed out at create -
nothing secret left at rest.

Onboard a phone by scanning
↵ on a node renders its config as a real black-on-white QR that scans on any
terminal theme and shrinks to fit the window. Open the WireGuard app, scan, done -
no file transfer. E exports the same config as out/<name>.conf, an install to
/etc/wireguard, a PNG, or an Ansible peer entry.

CLI
The TUI wraps these; call them directly to automate.
# interfaces
| | |
# keys
| |
# mesh: design, then generate each node's config
# QR (onboard a phone)
--hub (repeatable) makes a node a spoke of those hubs; omit it and a spoke
reaches all hubs. --private is optional: omit it for a public-only manifest and
inject keys later.
Notes
- Reading
/etc/wireguardneeds root;ewgauto-elevates withsudo(disable withEWG_NO_SUDO=1). Point elsewhere with--diror$EWG_DIR. mesh.tomlmay hold private keys forstore-mode nodes, so treat it as a secret and gitignore it; a redacted or public-only manifest is safe to commit.mesh list --jsonnever prints private keys.- Start-on-boot uses systemd (
wg-quick@<name>); toggling interfaces shells out to yourwg-quick. Keys and config generation are pure Rust, never a wrapper aroundwg.
License
AGPL-3.0-only.