Skip to content

Repository files navigation

lanwake

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.

Build

cargo build --release

The release profile is tuned for a small deployment binary:

opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
strip = "symbols"

Container image

CI publishes the image to GitHub Container Registry:

podman pull ghcr.io/yeshanjun/lanwake:latest

For a private package, log in first:

podman login ghcr.io

Local build is still available:

podman build -f Containerfile -t lanwake:latest .

The image uses gcr.io/distroless/cc-debian12:nonroot.

Run

cp config.example.toml config.toml
cargo run -- --config config.toml

Open:

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.

systemd

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.target

Install 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.service

For a hardened install, run the service as an unprivileged user.

Rootless Podman Quadlet

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.target

Then 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.service

config.toml

Start 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.

devices.toml

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.

Discover

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.

API

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.

Logs

Set log filtering in config.toml:

[log]
filter = "lanwake=debug,tower_http=debug"

RUST_LOG overrides the config value when set.

Troubleshooting

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.

Check

cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test

License

GPL-3.0. See LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages