Wake-on-LAN (remote power-on)¶
Sysadmin question: can I power this box on over the network instead of walking to it and pressing the button?
This page documents the wake CLI + wakeonlan (the active / sender side)
and the wake_on_lan ansible role (chezmoi prompt installWakeOnLan, the
passive / receiver side). It is the flip side of
random-hard-poweroff.md — that one is
"why did this box power off by itself"; this one is "power it back on".
Wired Ethernet only. WoL over Wi-Fi needs WoWLAN + AP cooperation and is out of scope. The receiver side is Linux only; the sender runs anywhere (the
wakeCLI is pure-stdlib Python, works on macOS too).
How it works (30 seconds)¶
- A magic packet is
6×0xFFfollowed by the target MAC repeated 16×, sent as a UDP broadcast to port 9. - The target NIC, kept alive on standby power, watches every frame for that pattern and, on a match, pulls the board out of sleep (S3) or off (S5).
- Two independent things must both be true, and they fail independently:
- the NIC is armed in the OS —
ethtool -s <if> wol g(does not persist across reboots on its own → we install a systemd unit); - firmware keeps the NIC on standby power and honours the wake — a BIOS setting, not something the OS can do.
Active side — send the packet (any machine)¶
The in-house wake CLI resolves a host name to a MAC and broadcasts:
wake david-ubuntu # look up MAC in ~/.config/wake/hosts.toml, send
wake de:ad:be:ef:12:34 # a raw MAC works with no config entry
wake --list # show configured hosts
wake host -b 10.0.0.255 # override the broadcast address
wake host -c 5 # 5 packets instead of the default 3
Hosts live in ~/.config/wake/hosts.toml (seeded once by chezmoi, mode 0600;
real MACs stay in this private file, never in the repo):
[hosts.david-ubuntu]
mac = "de:ad:be:ef:12:34" # target NIC MAC (`ip link` / `ethtool -P eno1`)
broadcast = "192.168.31.255" # optional; your LAN's directed broadcast
# port = 9 # optional (default 9)
wake always hits 255.255.255.255 and the host's directed broadcast
(some networks drop one or the other). It is pure stdlib — no dependency on the
wakeonlan binary — so it works on a fresh box. The upstream wakeonlan
(installed by networking_tools) is the equivalent primitive:
Passive side — make a box wakeable (Linux)¶
Turn on the chezmoi prompt installWakeOnLan (or the server-linux
bundle). The wake_on_lan role then, on chezmoi apply:
- installs ethtool;
- drops a templated
wol@.servicesystemd unit; - auto-detects every wired NIC that advertises magic-packet support and
enables
wol@<iface>.servicefor it — soethtool -s <if> wol gis re-applied on every boot (the arming is otherwise lost on reboot).
Do it by hand on a one-off box:
sudo apt install -y ethtool
sudo tee /etc/systemd/system/wol@.service >/dev/null <<'UNIT'
[Unit]
Description=Enable Wake-on-LAN (magic packet) on %i
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ethtool -s %i wol g
[Install]
WantedBy=sys-subsystem-net-devices-%i.device
UNIT
sudo systemctl daemon-reload
sudo systemctl enable --now wol@eno1.service # your wired NIC
Verify the NIC is armed (this is the single most useful check):
sudo ethtool eno1 | grep -i wake-on
# Supports Wake-on: pumbg ← must contain 'g' (magic packet)
# Wake-on: g ← must be 'g', not 'd' (disabled)
If Supports Wake-on has no g, the NIC/driver can't do magic-packet WoL and
no amount of config will help.
BIOS / firmware — required for wake-from-OFF (S5)¶
Waking from a full shutdown needs the board to keep NIC standby power after power-off. In BIOS (ASUS shown; names vary by vendor):
| Setting | Value | Why |
|---|---|---|
| Power On By PCI-E / PCI | Enabled | lets the NIC's PME signal power the board on |
| ErP Ready / EuP | Disabled | ErP cuts NIC standby power in S4/S5 — the #1 cause of "works from suspend, dead from shutdown" |
| Deep Sleep / Deep S5 | Disabled | same idea, another name |
A BIOS update resets these — re-apply them after flashing. Firmware can't be set from Ansible, which is why this stays a manual checklist.
Suspend (S3) vs full shutdown (S5)¶
Isolate the variable when testing: S3 (suspend) wakes with just the OS arming (no BIOS change), because the NIC never loses standby power. S5 (full off) additionally needs the BIOS settings above. So:
# prove the OS/NIC/packet path first, no BIOS needed:
ssh box 'sudo systemctl suspend' # then, from another host: wake box
# then, after the BIOS checklist, test the real thing:
ssh box 'sudo poweroff' # then: wake box
A cold-boot wake takes ~30–70 s to answer ping (POST + boot) — that's normal.
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
Wake-on: d after reboot |
arming didn't persist | enable wol@<iface>.service (or the role) |
Supports Wake-on lacks g |
NIC/driver can't do magic packet | different NIC, or check driver |
| Wakes from suspend but not shutdown | BIOS ErP Ready enabled | disable ErP / Deep Sleep |
| Nothing wakes it | Wi-Fi (not wired), or firewall drops broadcast, or box on a different L2 | use wired NIC; send to the subnet's directed broadcast; be on the same LAN |
| Wakes then immediately powers off | that's not WoL — see random-hard-poweroff.md | run crash-blackbox |
Files¶
- Sender:
dot_dotfiles/bin/executable_wake· config~/.config/wake/hosts.toml(templatedot_config/wake/create_private_hosts.toml) - Receiver:
dot_ansible/roles/wake_on_lan/(promptinstallWakeOnLan) →/etc/systemd/system/wol@.service - Package:
wakeonlanvianetworking_tools;ethtoolviawake_on_lan - Sibling: random hard power-offs ·
crash-blackbox