After a decade of relying on laptops, I recently built a desktop PC and transformed it into a dedicated AI server. While equipped with powerful components, including a high-end Nvidia graphics card, I prioritized energy efficiency through power management. I configured the system to suspend when idle and utilize hybrid graphics to minimize power consumption.
This creates a pretty big problem for accessing my local Ollama instance outside my machine. The server machine will be suspended, but I might be trying to access the service.
If you’re going to go down this path, consider only doing this with machines that have good networking cards. (Intel, Realtek, or Killerwireless). I had a Mediatek 7922 included with the motherboard. That proved to be a very error-prone card and required disabling the card in order to suspend. (Which would break WOL) I helped contribute to a script to allow for suspending. The best thing to do in this situation is to replace your wireless card with an Intel version if you plan on using Wi-Fi.
Getting Suspend working
What information will you need before you start
-
MAC Address This can be found with
ip link
. - The IP Address This is needed to identify which network the device is located on.
- Etherwake installed on a machine that isn’t suspended.
How do you setup Wake On Lan in Linux?
The best resource I found for this is the Arch Linux Wiki Wake on LAN Wiki guide.
Additionally, considering enabling wake on lan support on the BIOS. This allows for true suspends from the OS.
Verifying that your machine is working correctly
After setting these values, restart the machine, and then reverify that the Wake on Lan setting was preserved. Do this
with either iw list | grep -i wake
(for wireless cards) or ethtool interface | grep Wake
for ethernet interfaces.
Those outputs should reveal that Wake on Lan is enabled.
The Arch Wiki guide will give more support on how to make this setting persistent if it’s not on your machine.
Now suspend the system. The command systemctl suspend
should do it. (I’ve had a mixed experience with this)
On a separate machine: sudo etherwake -i (local eithernet interface) (MAC address of machine to wake up)
. Root
permissions are needed because this is a direct this special packet onto the network device.
You should see your suspended machine now waking up. If it did: Congratulations! If it didn’t, consider going back to the Arch WoL guide.
Ok, Everything is working, but how do I use the services on the machine?
Being able to wake up a suspended machine from another machine is handy. However, it’s not very useful when you’re accessing resources on your local network.
You’re in luck. Recently a GitHub user named Darksworm created a WOL Web proxy that will kick off a wake command on request, and proxy your request. Additionally, the individual created a dockerized version.
The docker-compose for this is:
services:
go-wol-proxy:
image: ghcr.io/darksworm/go-wol-proxy:latest
# Note: network mode "host" is required for Wake-on-LAN packets to be sent correctly
network_mode: host
restart: unless-stopped
volumes:
- ./config.toml:/app/config.toml
An example of the configuration file is:
port = ":8080" # Port to listen on
timeout = "1m" # How long to wait for server to wake up
poll_interval = "5s" # How often to check health during wake-up
health_check_interval = "30s" # Background health check frequency
health_cache_duration = "10s" # How long to trust cached health status
[[targets]]
name = "service"
hostname = "service.host.com" # The "external" hostname - what this server receives as a Host header
destination = "http://service.local" # The actual url to the server
health_endpoint = "http://service.local/ping" # url to check health
mac_address = "7c:8b:ad:da:be:51" # MAC address for WOL
broadcast_ip = "192.168.0.255" # This is good for all addresses on the 192.168.0.255 network
wol_port = 9
Some things to note:
- Setting the destination hostname, this should be considered for your router inside your local network.
-
Broadcast_ip
is intended to identify which network the wake command will be sent out on. - Remember, hitting your proxy’s endpoint will wake up the machine. It may be a good thing to hide this proxy behind a private network to avoid systems from being woken up by public web scanners.
-
External_hostname
this is the hostname of where the wake service is hosted. -
health_endpoint
– This was a little odd for a bare metal machine, most machines don’t have healthchecks. I used the service that I’m proxying for a response. I got lucky here, some services might return a 403. The service’s GitHub page documents how the proxy can instruct the machine to go back on suspend after a timeout.
In Review
The length of this blog post has been indicative of how long I’ve worked on/considered this problem. I nearly created a service similar to Darkworm’s. Luckily I’ve found the service before I started writing it. This has been a pretty satisfying result to be able to wake up and use a service based on a web request. Now, it’s incredibly transparent to be able to use services without pushing a wake command manually.
What’s next?
Setting up an internal certificate authority, so I can securely host my Ollama instance and use the voice functionality. (Voice functionality works locally, but requires a secure connection to function)