A lightweight, async network manager daemon written in Rust. It reads a single JSON configuration file at startup and applies network settings through pluggable, feature-gated modules. Once configured it runs as a background daemon with no further intervention required.
- IPv4 / IPv6 — assigns addresses and default gateways to interfaces via netlink (rtnetlink)
- MACsec (802.1AE) — creates encrypted or authentication-only MACsec interfaces on top of a physical parent
- Zeroconf / mDNS — sets the host's mDNS-visible name through Avahi
- WPA supplicant — starts and manages
wpa_supplicantinstances for Wi-Fi authentication - D-Bus interface — optional control plane for querying module state at runtime
- Dynamic plugins — load additional modules as shared libraries (
.so) from a directory at runtime - Dry-run mode — validate configuration without applying any changes to the system
Every module is opt-in at compile time through Cargo feature flags, so unused modules add zero binary size.
- Rust 1.70+ (edition 2021)
- Linux kernel with netlink support
avahi-daemon(for thezeroconffeature)wpa_supplicant(for thewpa_supplicantfeature)- System
libdbusdevelopment headers (for thedbus_ifacefeature)
# Default build — includes ipv4, ipv6, dbus_iface, dynamic_plugins
cargo build --release
# Minimal build — IP configuration only, no D-Bus, no plugin loader
cargo build --release --no-default-features --features ipv4,ipv6
# All modules
cargo build --release --features ipv4,ipv6,macsec,zeroconf,wpa_supplicant,dbus_iface,dynamic_plugins# Run in the foreground (useful for testing / systemd ExecStart)
rustynetd --foreground /etc/rustynetd/config.json
# Daemonize (double-fork, stdio → /dev/null)
rustynetd /etc/rustynetd/config.json
# Default config path when none is supplied
rustynetd # reads /etc/rustynetd/config.jsonLog verbosity is controlled with the RUST_LOG environment variable (e.g. RUST_LOG=debug).
Configuration is a single JSON file. Every section is optional — omit sections for modules you don't need. See config.example.json for a full example.
{
"dry_run": false,
"plugin_dir": "./plugins",
"modules": {
"ip": true,
"macsec": false,
"zeroconf": true,
"wpa_supplicant": true
},
"ip": [
{
"interface": "eth0",
"ipv4_addresses": ["192.168.1.10/24"],
"ipv4_gateway": "192.168.1.1",
"ipv6_addresses": ["2001:db8::10/64"],
"ipv6_gateway": "fe80::1"
}
],
"macsec": [
{
"name": "macsec0",
"parent": "eth0",
"sci": "1122334455667788",
"key": "00112233445566778899aabbccddeeff",
"key_id": "0102030405060708090a0b0c0d0e0f10",
"replay_window": 64,
"encrypt": true
}
],
"zeroconf": { "name": "my-device" },
"wpa_supplicant": [
{
"interface": "wlan0",
"config_file": "/etc/wpa_supplicant/wpa_supplicant-wlan0.conf",
"driver": "nl80211"
}
]
}| Field | Type | Description |
|---|---|---|
dry_run |
bool | Log intended actions without making system calls |
plugin_dir |
string | Directory scanned for dynamic plugin .so files |
modules.<name> |
bool | Enable or disable a compiled-in module at runtime |
ip[].interface |
string | Interface name (e.g. eth0) |
ip[].ipv4_addresses |
string[] | CIDR addresses to assign |
ip[].ipv4_gateway |
string | Default IPv4 gateway |
macsec[].sci |
string | 64-bit Secure Channel Identifier (hex) |
macsec[].key |
string | AES-128 (16 B) or AES-256 (32 B) key (hex) |
macsec[].encrypt |
bool | Encryption (true) or authentication-only (false) |
zeroconf.name |
string | mDNS hostname without the .local suffix |
wpa_supplicant[].config_file |
string | Path to wpa_supplicant.conf for this interface |
Place compiled plugin shared libraries in the directory specified by plugin_dir. Each plugin implements the NetworkModule trait and is loaded at startup. The built-in plugins (ip, macsec, zeroconf, wpa_supplicant) are also available as standalone crates under plugins/.
This project is licensed under the MIT License.