Lightweight Wake-on-LAN web panel for a trusted LAN or VPN.
phone / laptop -> http://lanwake.local:8080 -> Wake -> UDP magic packet
No database. No Docker requirement. No built-in TLS. One binary plus small TOML files.
cargo build --releaseThe release profile is tuned for a small deployment binary:
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
strip = "symbols"CI publishes the image to GitHub Container Registry:
podman pull ghcr.io/yeshanjun/lanwake:latestFor a private package, log in first:
podman login ghcr.ioLocal build is still available:
podman build -f Containerfile -t lanwake:latest .The image uses gcr.io/distroless/cc-debian12:nonroot.
cp config.example.toml config.toml
cargo run -- --config config.tomlOpen:
http://127.0.0.1:8080
For LAN access, set bind in config.toml to the host LAN address, for
example:
bind = "192.168.1.2:8080"Do not expose this service directly to the public Internet. Use WireGuard, Tailscale, ZeroTier, or a reverse proxy with proper auth/TLS.
A simple system service can run the release binary directly:
[Unit]
Description=lanwake Wake-on-LAN dashboard
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/lanwake
ExecStart=/opt/lanwake/lanwake --config /opt/lanwake/config.toml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetInstall example:
sudo mkdir -p /opt/lanwake
sudo cp target/release/lanwake /opt/lanwake/
sudo cp config.example.toml /opt/lanwake/config.toml
sudo cp lanwake.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now lanwake.serviceFor a hardened install, run the service as an unprivileged user.
If you prefer a user service with Podman, create
~/.config/containers/systemd/lanwake.container:
[Unit]
Description=lanwake Wake-on-LAN dashboard
After=network-online.target
[Container]
Image=ghcr.io/yeshanjun/lanwake:latest
ContainerName=lanwake
Network=host
Volume=%h/.config/lanwake/config.toml:/config.toml:ro
Volume=%h/.config/lanwake/devices.toml:/devices.toml:rw
Exec=--config /config.toml
[Service]
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.targetThen start it:
mkdir -p ~/.config/containers/systemd ~/.config/lanwake
cp config.example.toml ~/.config/lanwake/config.toml
systemctl --user daemon-reload
systemctl --user enable --now lanwake.serviceStart from config.example.toml and adjust it for the host.
bind = "127.0.0.1:8080"
broadcast = "192.168.1.255"
auth_token = ""
[paths]
devices = "./devices.toml"
[wol]
port = 9
repeat = 3
repeat_delay_ms = 200
[log]
filter = "lanwake=info,tower_http=info"If auth_token is non-empty, API requests must include:
Authorization: Bearer <token>Invalid config fails at startup: unknown fields are rejected, whitespace-only
tokens are invalid, and [wol].port / [wol].repeat must be greater than zero.
Binding to 0.0.0.0 or [::] without auth logs a safety warning.
lanwake creates this file on first startup if it is missing. Devices can be added from the UI.
[[devices]]
id = "gaming-pc"
name = "Gaming PC"
ip = "192.168.1.50"
mac = "AA:BB:CC:DD:EE:FF"
wol_port = 9
group = "desktop"
favorite = true
notes = "Main PC"mac is required for WOL. It must be one of AA:BB:CC:DD:EE:FF,
AA-BB-CC-DD-EE-FF, or AABBCCDDEEFF. ip is optional and not used to wake
the device. id and mac must be unique; ids may contain ASCII letters,
digits, _, -, and ., but not . or .. alone.
wol_port is optional and must be greater than zero; when omitted,
[wol].port is used. wol_repeat can override [wol].repeat per device.
lanwake can read local DHCP and ARP tables on demand:
[discover]
dhcp_leases = "/tmp/dhcp.leases"
arp_table = "/proc/net/arp"Set either value to "" to disable that source. Discovery is a snapshot from local tables; it is not a live online check.
Incomplete ARP rows are skipped, saved MAC addresses are filtered out, and DHCP
plus ARP entries are merged by MAC.
GET /api/devices
POST /api/devices
PUT /api/devices/{id}
DELETE /api/devices/{id}
POST /api/devices/{id}/wake
POST /api/discover
POST /api/devices may omit id; the server derives one from name. Errors
use a small JSON shape:
{"error":"invalid_mac","message":"MAC address must contain 12 hex digits"}Common codes include unauthorized, invalid_payload, invalid_mac,
device_not_found, device_already_exists, discover_failed, and
wol_failed.
Set log filtering in config.toml:
[log]
filter = "lanwake=debug,tower_http=debug"RUST_LOG overrides the config value when set.
If Wake does nothing, verify WOL is enabled in BIOS/UEFI and the OS network
adapter settings, then try the other common WOL port (7 or 9) and confirm
broadcast matches the LAN. Powered-off devices often do not appear in
discovery; keep their MAC saved in devices.toml.
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo testGPL-3.0. See LICENSE.