Wake-on-LAN Automation: Powering Servers On and Off with Home Assistant
Let the power-hungry box sleep until something actually needs it

I have a beefy machine in the cupboard that exists to do exactly one thing: transcode media and crunch the occasional batch job. It pulls something like 90 watts at idle, which over a year is a meaningful slice of the electricity bill for a box that’s genuinely busy maybe two hours a day. For ages I left it running because the alternative — getting up and pressing the power button when I wanted to watch something — was worse. Then I wired it into Home Assistant, and now it sleeps until it’s needed and shuts itself down when it’s idle. The savings paid for the effort in a couple of months.
Wake-on-LAN (WoL) is the magic that makes this possible. A network card, even when the machine is “off” (technically in S5 soft-off), keeps listening for a special “magic packet” addressed to its MAC. Receive that packet, and the board powers on. Home Assistant can send it on a schedule, on a button press, or — the good bit — automatically when something on the network tries to reach the sleeping server.
1 Step one: actually enable WoL on the hardware
This is where most people fail, so do it first. Two places need to agree:
- The BIOS/UEFI. Find the setting usually called “Wake on LAN”, “Power On by PCI-E”, or “ErP” (which you want disabled — ErP/EuP energy-saving mode cuts power to the NIC and kills WoL). Enable wake, disable ErP.
- The OS. On Linux, the network driver often disables WoL on shutdown. Check and set it with
ethtool:
$ sudo ethtool eno1 | grep Wake
Supports Wake-on: pumbg
Wake-on: d # 'd' = disabled, this is the problem
$ sudo ethtool -s eno1 wol g # 'g' = wake on magic packet
$ sudo ethtool eno1 | grep Wake-on
Wake-on: g
Because that resets on reboot, persist it with a systemd unit:
# /etc/systemd/system/wol.service
[Unit]
Description=Enable Wake-on-LAN
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool -s eno1 wol g
[Install]
WantedBy=multi-user.targetThen sudo systemctl enable --now wol.service. Note the MAC of eno1 — you’ll need it.
2 Step two: the Home Assistant side
Add the Wake-on-LAN integration and define a switch in configuration.yaml. The clever part is giving the switch a turn-off action too — Home Assistant can’t magic-packet a machine off, so we SSH in and tell it to suspend or shut down:
switch:
- platform: wake_on_lan
name: Transcode Box
mac: "a4:bb:6d:11:22:33"
host: 192.168.1.50 # used to ping for on/off state
turn_off:
service: shell_command.suspend_transcode_box
shell_command:
suspend_transcode_box: >
ssh -i /config/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new
[email protected] 'sudo systemctl suspend'The host field lets Home Assistant ping the box to know whether it’s actually up, so the switch reflects real state rather than just “I sent a packet and hoped”. Give the ha-control user a tightly scoped sudoers entry — only systemctl suspend, nothing else — so a compromised Home Assistant can’t do more than nap your server.
3 Step three: wake it automatically when something needs it
A button is fine, but the real prize is making the box wake itself when demand appears, with no human in the loop. The pattern I use: a proxy that, on receiving a request for a service on the sleeping box, wakes it, waits for it to come up, then forwards the request. For a media server, you can approximate this entirely in Home Assistant with an automation triggered by, say, your TV turning on:
automation:
- alias: "Wake transcode box when the living room TV turns on"
trigger:
- platform: state
entity_id: media_player.living_room_tv
to: "on"
condition:
- condition: state
entity_id: switch.transcode_box
state: "off"
action:
- service: switch.turn_on
target:
entity_id: switch.transcode_box
- alias: "Sleep transcode box if idle for an hour"
trigger:
- platform: state
entity_id: binary_sensor.transcode_box_active
to: "off"
for: "01:00:00"
action:
- service: switch.turn_off
target:
entity_id: switch.transcode_boxThat binary_sensor.transcode_box_active is whatever signals “real work is happening” — an active Jellyfin session, a command-line job, CPU above a threshold. I derive mine from the media server’s API. When it’s been quiet for an hour, the box suspends itself. When the telly comes on, it’s awake by the time the app finishes loading.
4 The gotchas worth knowing
WoL packets are layer-2 broadcasts, so they don’t cross subnets or VLANs without help — keep Home Assistant and the target on the same broadcast domain, or configure a directed broadcast. Some switches and Wi-Fi setups also drop the packet; wired is far more reliable. And if the machine wakes but the OS doesn’t come up, it’s almost always the ethtool setting reverting on the previous shutdown — the systemd unit above is what fixes that for good.
5 Verdict
Worth it? If you have a high-draw machine that’s idle most of the day, absolutely — this is one of the few homelab projects with a tangible, recurring payoff in pounds off the bill, not just satisfaction. The setup is an evening, the hardware-enablement is the only fiddly part, and once it works it’s invisible: the box is simply there when you need it and quietly asleep when you don’t. If your server is genuinely busy around the clock, skip all this — but most homelab boxes aren’t, and they should be sleeping more than they are.



