My homelab was pulling 220W idle. At my electricity rate that is about $19/month. Not going to bankrupt me, but the fan on the closet was also audible at that load and the summer heat made my closet unpleasant. I spent a weekend profiling and tuning. Got the idle down to 180W. Here is where the wattage was hiding.

Baseline

Kill-A-Watt on the rack’s PDU, measured idle (no active user traffic, Sunday afternoon):

  • NUCs (3x Intel i5 10th gen, 32 GB each): 65 W total
  • Synology DS420+ with 4 HDDs: 45 W
  • 8-port managed PoE switch: 18 W base + 22 W powering two cameras and a WAP = 40 W
  • Raspberry Pi 4 running Pi-hole: 4 W
  • Unraid rebuild box (backup target, not always on): 45 W
  • Modem: 8 W
  • Router (x86 OPNsense): 15 W

Total: 222 W. Matches the PDU number.

The first easy win: killing the Unraid box

The Unraid box served as an occasional backup target. It was always on because I never bothered to schedule its power cycle. I set up Wake-on-LAN and a systemd timer on the NAS:

# /etc/systemd/system/wake-backup.service
[Unit]
Description=Wake backup target for nightly sync
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/wakeonlan aa:bb:cc:dd:ee:ff
ExecStart=/usr/bin/bash -c 'until nc -z 192.168.30.40 22; do sleep 1; done'

And a timer that fires at 02:00 to wake it, waits for ssh, starts the backup, and then issues a shutdown when done. Downtime: 22 hours/day. Savings: ~37 W * 22h = 0.8 kWh/day. About $4/month.

The surprise: a ZFS scrub was always running

I had set up ZFS scrub on a timer months ago, and it was actually running more often than I thought. I hit zpool status on the NAS (which runs a Synology NAS with a btrfs pool, but let me correct: I also have a small test ZFS pool on a spare NUC for experimentation). That NUC was scrubbing a 1 TB pool continuously because my cron was misconfigured and re-triggered the scrub on every minute, and the scrub’s in-progress state lookup was off.

Confirmed with:

zpool status -v tank | grep scan
# scan: scrub in progress since ...

Removed the bad cron, pool went back to idle. NUC’s idle draw dropped from 28 W to 18 W. 10 W savings for doing nothing.

The second win: PoE device consolidation

I had two PoE cameras and a WAP being powered by the switch. The cameras drew 6 W each when idle. I replaced one with a Wi-Fi camera (not PoE) that uses a more efficient 2 W total in standby. Saving: 4 W.

The WAP was drawing 14 W. Checked its power modes; it had a “max” setting that kept all radios at full transmit power even when no clients were on them. Changed to adaptive. Saving: 3 W.

The third win: NUC C-states

I ran turbostat on one of the NUCs:

sudo turbostat --interval 5 --num_iterations 3
# ... columns ...
# CPU%c1=72.3 CPU%c6=1.2 CPU%c7=24.1 ...

C7 is the deepest idle state this CPU supports. It was only there 24% of the time. A healthy idle NUC should be in C7 >90% of the time. Something was waking the CPU frequently.

powertop pointed at two culprits:

  • The NIC was configured for 1 Gbps full duplex even though the switch port was 1 Gbps. Enabling EEE (Energy-Efficient Ethernet) with ethtool -s enp0s31f6 eee on saved a few watts.
  • A userspace agent for monitoring was polling every second with a busy-wait. Replaced with a proper sleep-based loop. Saved most of the rest.

After tuning, C7 residence went to 87%. NUC idle went from 22 W to 17 W. Across three NUCs, that’s 15 W.

The partial win: the switch

I looked at replacing my switch with a newer one rated for higher efficiency. On paper, modern 8-port PoE switches from the current generation would save maybe 3-4 W at idle. Not worth the $150 upfront for a $4/month save, so I kept the one I have. If it dies, I will replace with something newer.

The tally

  • Unraid box on a schedule: 37 W savings (but that’s not strictly “idle”, it runs 2 hours/day; amortized about 33 W savings).
  • ZFS scrub loop fixed: 10 W savings.
  • PoE consolidation: 7 W savings.
  • NUC C-state tuning: 15 W savings.

Total: ~65 W savings in theory, ~40 W in practice measured at the PDU because some of these interact and I did not measure each independently.

New idle: 180 W at the PDU. About 0.9 kWh/day saved. $8/month. Not huge but not nothing.

What I did not do

  • Replace spinning disks with SSDs. SSDs would save maybe 20 W, but would cost thousands at my current capacity.
  • Consolidate three NUCs to one beefier box. Could in principle save another 30 W. Loses redundancy, which is the main reason I have three.
  • Move to a laptop-class mini-PC. Some of these are <10 W idle. Would require re-plumbing a lot of my storage. Maybe next year.

Monitoring

I now scrape the PDU’s current draw every minute with a Shelly EM plus a prometheus exporter. Dashboard showing daily kWh. Alert if idle exceeds 200 W for more than 30 minutes: that usually means a scrub or backup started unexpectedly.

curl -s http://shelly-rack.lan/rpc/Switch.GetStatus?id=0 | jq '.apower'
# 178.4

Reflection

Most of the wins came from things that were slightly misconfigured rather than things that fundamentally needed replacement. The closet sounds quieter. My electricity bill is slightly lower. My closet AC runs less. All wins.

If you have not measured your rack’s idle draw recently, get a Kill-A-Watt or a Shelly and look at the number. You will probably find at least one thing pulling more than it should.

Related: see my post on sizing a UPS for a quiet homelab rack for the complementary “smaller load means longer UPS runtime” story.