111 lines
5.5 KiB
Markdown
111 lines
5.5 KiB
Markdown
# wireguard-admin
|
||
|
||
This repository contains the Rust package, startup boundary, validated settings
|
||
loader, client domain model, a byte-preserving in-memory WireGuard configuration
|
||
editor, and library APIs for encrypted client vaults and read-only client import.
|
||
The library also provides saved-file persistence with recovery, private backups,
|
||
prepared Commit, and previewed full restore. The terminal management interface
|
||
and WireGuard/systemd runtime operations have not been implemented yet.
|
||
|
||
The package requires Rust 1.97.1 or newer and uses the Rust 2024 edition. From
|
||
the repository root, run:
|
||
|
||
```sh
|
||
cargo run -- --help
|
||
cargo run -- --version
|
||
```
|
||
|
||
`--help` and `--version` work without root. Starting with no arguments requires
|
||
root; until the management interface is implemented, startup exits with an
|
||
error and does not read server configuration or vault files.
|
||
|
||
## Settings
|
||
|
||
Settings use TOML in the fixed file `wireguard-admin.toml` beside the
|
||
executable. Start from [`config/wireguard-admin.example.toml`](config/wireguard-admin.example.toml).
|
||
The required fields are:
|
||
|
||
- `interface_name`: existing WireGuard interface name (1–15 ASCII characters).
|
||
- `server_config_path`: path to the existing server configuration.
|
||
- `client_source_directory`: directory containing existing client files.
|
||
- `server_endpoint`: hostname or IPv4 address followed by `:port`, or IPv6 in
|
||
brackets followed by `:port` (for example, `[2001:db8::2]:51820`).
|
||
- `ipv4_allocation_range` and `ipv6_allocation_range`: CIDR ranges of the
|
||
matching address family.
|
||
- `dns_addresses`: non-empty list of IPv4 and/or IPv6 literal addresses.
|
||
- `systemd_unit`: service unit name ending in `.service`.
|
||
- `restart_timeout_seconds`: positive integer.
|
||
|
||
`data_root` is optional. It defaults to `Backup` beside the executable;
|
||
current internal data and the encrypted vault are under `data`, and archives
|
||
are under `archives`. Relative configured paths, including an explicit
|
||
`data_root`, resolve from the executable directory. Absolute paths remain
|
||
absolute. Settings validation checks syntax and values only; it does not
|
||
require the referenced files, directories, or service to exist and does not
|
||
perform DNS lookups.
|
||
|
||
## Library configuration API
|
||
|
||
The library exposes `wireguard_admin::wireguard::ConfigDocument` for UTF-8
|
||
configuration bytes supplied by the caller. It retains the source and renders
|
||
unmodified input byte-for-byte, including line endings and a missing final
|
||
newline. Peer inspection exposes public identities, parsed `AllowedIPs`, spans,
|
||
and redacted issues; arbitrary directive values are not included in the view.
|
||
The edit methods `add_client`, `delete_client`, `rename_client`, and
|
||
`insert_legacy_metadata` return new in-memory documents. They do not read or
|
||
write files, save changes, or alter the running VPN. See
|
||
[`docs/CONFIG_FORMAT.md`](docs/CONFIG_FORMAT.md) for the managed metadata block
|
||
format.
|
||
|
||
Example:
|
||
|
||
```rust,ignore
|
||
use wireguard_admin::wireguard::ConfigDocument;
|
||
|
||
let document = ConfigDocument::parse(config_bytes)?;
|
||
let updated = document.rename_client(&public_key, "office laptop")?;
|
||
let bytes_to_review = updated.render(); // no persistence or VPN operation
|
||
```
|
||
|
||
Management startup still exits with an explicit “not implemented” error after
|
||
its root check. The application library APIs are usable by callers, but are not
|
||
yet connected to a management session or runtime VPN adapter.
|
||
|
||
## Saved state, Commit, and backups
|
||
|
||
wireguard_admin::app::Application opens saved files through
|
||
wireguard_admin::persistence::SavedStore, stages client and vault changes,
|
||
creates manual and mandatory operation backups, and previews/confirms a full
|
||
restore. Commit writes saved files only. Restore also changes saved files only;
|
||
neither operation reloads or restarts WireGuard. The server file is kept at its
|
||
trusted configured path, while internal state and the encrypted vault are kept
|
||
under Backup/data by default. Archives are stored under Backup/archives and
|
||
contain fixed logical members, not source client files or prior archives.
|
||
|
||
The persistence journal recovers interrupted file replacement on reopen and
|
||
returns a recovery error while earlier work remains unresolved. Restoring a
|
||
backup does not restore runtime state: the running interface is unknown until a
|
||
future explicit runtime verification. Pending deleted-client addresses remain
|
||
reserved through Commit, reopen, and restore. See
|
||
[docs/BACKUP_FORMAT.md](docs/BACKUP_FORMAT.md) and
|
||
[docs/PERSISTENCE.md](docs/PERSISTENCE.md) for archive and recovery details.
|
||
|
||
## Vault and existing-client import library
|
||
|
||
`wireguard_admin::vault` provides WireGuard key handling, an encrypted versioned
|
||
vault bundle, caller-buffer client configuration parsing, and reconciliation
|
||
against a supplied server document. The source adapter can prepare an initial
|
||
encrypted bundle or explicitly import candidates into an existing prepared
|
||
bundle. These operations return in-memory data only: they do not install or save
|
||
a vault, edit source files or server configuration, Commit, or touch the VPN.
|
||
|
||
Directory scans use the resolved `client_source_directory` only. A candidate is
|
||
an immediate regular file whose name ends in `.conf` (case-insensitive); the
|
||
adapter does not recurse, follow symlinks, or read files larger than 1 MiB. A
|
||
scan is limited to 4,096 directory entries, 1,024 candidates, and 32 MiB total
|
||
input. Per-file failures are redacted and do not prevent other files from being
|
||
examined. Enumeration, read, or limit failures mark the scan incomplete. The
|
||
original files remain untouched. Adapter examples and behavior are covered with
|
||
synthetic temporary directories in `tests/vault_import.rs`.
|
||
|