Automatic server suspension and Wake-on-LAN system for home servers managed by an OpenWrt router.
autoSusWol automatically suspends a home server when it's not in use and wakes it up on demand when a client tries to access its services. The system is split between the server and the OpenWrt router, which coordinate via SSH.
- A timer runs
check-traffic.shon the server every 5 minutes - The script checks for active connections to monitored services
- If no activity is detected (and no printer/TV is in use), the server suspends after a 60-second grace period
- The router monitors firewall logs for connection attempts to the server ports
- When a connection attempt is detected, the router sends a WOL magic packet
- The server wakes up and becomes available within ~10 seconds
+-------------------+ +------------------------+
| CLIENT (LAN) | | OPENWRT ROUTER |
| 192.168.8.x |-------->| 192.168.20.1 |
+-------------------+ | |
| wol-monitor.sh |
| watches fw4 logs |
| sends WOL packet |
+------------+-----------+
| br-server (192.168.20.x)
+------------v-----------+
| HOME SERVER |
| 192.168.20.x |
| |
| check-traffic.sh |
| apply-monitor-rules |
| Docker containers: |
| - tvheadend |
| - portainer |
| - klipper |
+------------------------+
| Network | Subnet | Purpose |
|---|---|---|
| LAN | 192.168.8.x | Main network (clients) |
| SERVER | 192.168.20.x | Dedicated server VLAN |
| IoT | 192.168.10.x | Isolated IoT devices |
The server VLAN is configured so that all traffic between LAN and server passes through the router — this is essential for the WOL trigger to work.
- Linux with systemd
nftables,curl,ss(iproute2),ethtoolsmbstatus(samba-common, for Samba activity detection)- WOL enabled in BIOS
- SSH access to the router
- OpenWrt 25.x with firewall4 (fw4)
etherwake(apk add etherwake)- Dedicated bridge interface for the server (
br-server)
| File | Description |
|---|---|
apply-monitor-rules.sh |
Main config script — sets up nft rules on the server and deploys firewall rules + WOL scripts to the router via SSH |
check-traffic.sh |
Checks for active connections and suspends the server if idle |
| File | Description |
|---|---|
monitor-ports.conf |
List of ports to monitor. Use !wol-only to include a port in the WOL trigger but exclude it from local connection checks |
systemd/system/apply-monitor-rules.service |
Runs apply-monitor-rules.sh at boot |
systemd/system/check-traffic.service |
Oneshot service triggered by the timer |
systemd/system/check-traffic.timer |
Runs check-traffic.sh every 5 minutes |
systemd/network/10-wol-eth1.link |
Template — installed as 10-wol-<iface>.link with the actual NIC name |
| File | Description |
|---|---|
tbsecp3-reset.sh |
Stops tvheadend and unloads TBS PCIe DVB tuner drivers before suspend; reloads them and restarts tvheadend after resume. Only needed with TBS PCIe DVB tuner cards. |
| File | Description |
|---|---|
/usr/local/bin/wol-trigger.sh |
Sends WOL magic packet and waits for server to respond |
/usr/local/bin/wol-monitor.sh |
Monitors fw4 logs and calls wol-trigger.sh on demand |
/etc/init.d/wol-monitor |
Init script to start wol-monitor.sh at router boot |
The repository files use {{PLACEHOLDER}} syntax for all machine-specific values. The install.sh script detects and substitutes them automatically — you should not edit the files manually before running install.sh.
| Placeholder | Description | Auto-detected |
|---|---|---|
{{NIC_IFACE}} |
Server NIC interface name (e.g. eth1, enp3s0) |
yes |
{{NIC_MAC}} |
Server NIC MAC address | yes |
{{SERVER_IP}} |
Server IP on the server VLAN | yes |
{{ROUTER_IP}} |
Router IP on the server VLAN | yes (from default gateway) |
{{SERVER_IFACE}} |
Router bridge interface name (e.g. br-server) |
asked (default: br-server) |
{{WOL_TIMEOUT}} |
Max seconds to wait for server after WOL | asked (default: 15) |
{{TVH_USER}} |
tvheadend admin username | asked (optional) |
{{TVH_PASSWORD}} |
tvheadend admin password | asked (optional) |
{{TBS_PCI_1}} |
PCI address of first TBS DVB card | yes via lspci (optional) |
{{TBS_PCI_2}} |
PCI address of second TBS DVB card | yes via lspci (optional) |
# Format: PORT # service_name [!wol-only]
#
# !wol-only: port is monitored by the router for WOL trigger
# but excluded from local active-connection checks.
# Use for services that generate background traffic
# (e.g. tvheadend EPG sync, Samba keepalives).
#
#22 # ssh -- disabled: avoid keeping server awake during admin sessions
80 # http
445 # samba !wol-only -- Samba activity checked via smbstatus instead
7125 # klipper
9000 # portainer
9090 # cockpit
9981 # tvheadend http !wol-only
9982 # tvheadend https !wol-only
Create a dedicated bridge interface for the server VLAN and connect the physical port:
# Remove the server port from the main LAN bridge (adjust lan2 to your port)
uci del_list network.@device[0].ports='lan2'
# Create the server bridge and interface
uci add network device
uci set network.@device[-1].type='bridge'
uci set network.@device[-1].name='br-server'
uci set network.@device[-1].ports='lan2'
uci set network.@device[-1].bridge_empty='1'
uci set network.SERVER=interface
uci set network.SERVER.proto='static'
uci set network.SERVER.device='br-server'
uci set network.SERVER.ipaddr='192.168.20.1'
uci set network.SERVER.netmask='255.255.255.0'
uci set dhcp.SERVER=dhcp
uci set dhcp.SERVER.interface='SERVER'
uci set dhcp.SERVER.start='100'
uci set dhcp.SERVER.limit='10'
uci set dhcp.SERVER.leasetime='12h'
uci add firewall zone
uci set firewall.@zone[-1].name='server'
uci set firewall.@zone[-1].input='ACCEPT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='REJECT'
uci add_list firewall.@zone[-1].network='SERVER'
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='server'
uci set firewall.@forwarding[-1].dest='wan'
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='server'
uci set firewall.@forwarding[-1].dest='lan'
uci add firewall forwarding
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='server'
uci commit network
uci commit dhcp
uci commit firewall
/etc/init.d/network restart
fw4 reloadapk add etherwakegit clone https://github.com/paorie/autoSusWol.git
cd autoSusWol
sudo ./install.shThe script will:
- Auto-detect NIC interface, MAC address, server IP and default gateway
- Ask for confirmation and the few values it cannot detect (router bridge name, tvheadend credentials, TBS card presence)
- Substitute all
{{PLACEHOLDER}}values in the files before copying them - Install the
.linkfile with the correct NIC name (e.g.10-wol-enp3s0.link) - Generate an SSH key and copy it to the router
- Enable WOL on the NIC via ethtool
- Enable and start systemd services
- Run
apply-monitor-rules.shto deploy WOL scripts and firewall rules to the router
After installation, edit /etc/monitor-ports.conf to add or remove monitored ports, then re-run:
sudo /usr/local/bin/apply-monitor-rules.shThis re-deploys the firewall rules and WOL scripts to the router without reinstalling everything.
check-traffic.sh runs every 5 minutes and suspends the server only when ALL of the following are true:
- 3D printer is not printing -- checked via Klipper Moonraker API (
/printer/objects/query?print_stats) - No TV streaming active -- checked via tvheadend API (
streaming: 1in/api/status/connections) - No Samba files open -- checked via
smbstatus --locked(ignores background keepalive connections from SMB clients like KDE Dolphin/KIO) - No active TCP connections on other monitored ports (80, 7125, 9000, 9090)
When all conditions are met, the script waits 60 seconds before suspending (grace period for pending operations).
SMB clients (including KDE Dolphin/KIO) maintain persistent TCP keepalive connections to Samba shares even when no files are in use. Using ss to detect port 445 activity would prevent the server from ever suspending. smbstatus --locked only reports files that are actually open, making it a reliable indicator of real Samba usage.
These services generate continuous background traffic (EPG sync, SMB keepalives) that would prevent suspension even when not actively in use. Marking them !wol-only excludes them from local traffic monitoring while keeping them in the router WOL trigger rules -- so the server still wakes up when a client actually tries to connect.
wol-monitor.sh on the router monitors fw4 firewall logs continuously. When a WOL_ prefixed log entry appears (meaning a client tried to connect to the server), wol-trigger.sh is called which:
- Checks if the server is already reachable (ping) -- exits if yes
- Uses a lockfile to prevent multiple simultaneous wake attempts
- Sends a WOL magic packet via
etherwake - Polls the server every second until it responds (max
WOL_TIMEOUTseconds) - Logs all actions via
logger
If using TBS PCIe DVB tuner cards, tbsecp3-reset.sh is installed by install.sh to handle the driver lifecycle around suspend/resume.
The script is called automatically by systemd-sleep at /usr/lib/systemd/system-sleep/tbsecp3-reset.sh.
Pre-suspend: stops the tvheadend container, removes the TBS PCIe devices from the PCI bus, then unloads the driver modules (tbsecp3, gx1133, tas2101) to prevent i2c timeout errors that can cause the system to freeze during suspend.
Post-resume: rescans the PCI bus to re-detect the cards, reloads the driver modules in the correct dependency order, then restarts the tvheadend container.
The PCI addresses are specific to the hardware -- install.sh detects them automatically via lspci, or asks for them if not found.
Server doesn't suspend
- Run
sudo bash -x /usr/local/bin/check-traffic.shto see which check is blocking - Check Samba file activity:
sudo smbstatus --locked - Check tvheadend connections:
curl -s "http://user:pass@localhost:9981/api/status/connections" - Check other active connections:
ss -tn state established
Server doesn't wake up
- Check router logs:
logread | grep -E "WOL_|wol-trigger" - Verify wol-monitor is running on the router:
ps | grep wol - Start wol-monitor manually:
/etc/init.d/wol-monitor start - Test WOL manually:
etherwake -i br-server <MAC_ADDRESS> - Verify WOL is enabled on the server NIC:
ethtool <iface> | grep Wake
System freezes during suspend (TBS cards)
- Check for i2c timeout errors:
journalctl -b -1 | grep "i2c xfer timeout" - Verify tbsecp3-reset.sh is executable:
ls -la /usr/lib/systemd/system-sleep/tbsecp3-reset.sh - Verify PCI addresses match your hardware:
lspci | grep -i tbs
apply-monitor-rules.sh fails
- Check SSH connectivity:
sudo ssh -i /root/.ssh/id_rsa_router root@<ROUTER_IP> "echo OK" - Check router reachability:
ping <ROUTER_IP> - Run with debug:
sudo bash -x /usr/local/bin/apply-monitor-rules.sh
install.sh -- SSH key copy fails
- Copy manually:
ssh-copy-id -i /root/.ssh/id_rsa_router.pub root@<ROUTER_IP> - Then re-run deploy:
sudo /usr/local/bin/apply-monitor-rules.sh