# easywireguard (`ewg`)
> **Canonical:** [gitlab.com/safteinzz/easywireguard](https://gitlab.com/safteinzz/easywireguard) · **Mirror:** [github.com/safteinzz/easywireguard](https://github.com/safteinzz/easywireguard)
mesh, minus the mess - interfaces, keys and full-mesh configs in one CLI + TUI
```bash
cargo install easywireguard # the command you type is the shorter `ewg`
ewg self update # reinstall the latest release later on
```
## 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.
```bash
# interfaces
# keys
# mesh: design, then generate each node's config
ewg mesh add flint --address 10.10.1.1/24 --pubkey <PUB> \
--endpoint vpn.example.com:51820 --allowed-ips 0.0.0.0/0 # a hub / exit
ewg mesh add phone --address 10.10.1.3/24 --pubkey <PUB> \
--hub flint --dns 192.168.10.250 --keepalive 25 [--private <PRIV>]
ewg mesh # list (-v verbose, --json; never prints private keys)
ewg mesh rm <name>
ewg mesh gen -o out/ # write every node's .conf
# QR (onboard a phone)
ewg qr <node> -m mesh.toml # QR of that node's generated config
ewg qr out/phone.conf -o phone.png # a .conf file, also written as a PNG
```
`--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/wireguard` needs root; `ewg` auto-elevates with `sudo` (disable
with `EWG_NO_SUDO=1`). Point elsewhere with `--dir` or `$EWG_DIR`.
- `mesh.toml` may hold private keys for `store`-mode nodes, so treat it as a
secret and gitignore it; a redacted or public-only manifest is safe to commit.
`mesh list --json` never prints private keys.
- Start-on-boot uses systemd (`wg-quick@<name>`); toggling interfaces shells out
to your `wg-quick`. Keys and config generation are pure Rust, never a wrapper
around `wg`.
## License
AGPL-3.0-only.