Today I’m trying to reduce the power consumption of my Proxmox Backup Server. The HP Microserver is great for what I need, but it’s kinda loud and I’m working on optimizing my power bill. The homelab is the largest single consumer of electricity aside from the air conditioning in the summer, so it’s something I’m looking at heavily.

Anyway, I thought I could do this purely with systemd sleep / suspend initially. Systemd can set up the system RTC to wake the system from suspend or hibernate at a specific time, and it’s easy to configure this by setting up a timer unit which is allowed to wake the system to happen. Of course, this requires the system to be able to suspend or hibernate.

I tried doing S3 speep (normal suspend to RAM) and found that the Microserver doesn’t support this. I then didn’t have enough space on my 16G boot disk (microSD card) for a swap partition to hibernate to, and don’t want to mess with the partition tables on my zfs drives to add one there, so hibernate is out too. This leaves me with actually fully shutting the system down and booting back up in the future. Downside to this is the RTC won’t wake it back up, I need to have another system send a Wake on LAN magic packet. No big deal, I just need to make sure I send it early enough that the backups aren’t scheduled to start until after the server is fully booted.

Video

Here’s the video if you want to listen to me say all of these things: Video Thumbnail

Wake On LAN

I found the MACs of all of my interfaces. In this case, I’m using eno1, so I am using 70:10:6f:3e:d1:f8. You will of course need to find your own MAC address. This is also the hardware MAC, not the virtual MAC if you’re using a bond. I then installed the simple wakeonlan utility with apt install wakeonlan. It’s installed in /usr/bin so I can call it directly from the systemd service unit.

Service Unit to Wake On LAN

This just calls wakeonlan with the MAC address. Don’t enable the service, but you can systemctl start wakebigstor to bootup the server if you want. I put the file in /etc/systemd/system/wakebigstor.service. Bigstor is the name of the backup server.

[Unit]
Description=Wake up Bigstor

[Service]
Type=oneshot
ExecStart=/usr/bin/wakeonlan 70:10:6f:3e:d1:f8

[Install]
WantedBy=default.target

Timer Unit to call Service Unit

Systemd timers are separate units from services, so here’s the timer unit that triggers the service unit at 19:05 local time daily. I put this one in /etc/systemd/system/wakebigstor.timer and enabled and started it (systemctl enable --now wakebigstor.timer). Again, don’t enable the service, just the timer.

[Unit]
Description=Wakeup Bigstor
RefuseManualStart=no
RefuseManualStop=no

[Timer]
#Run at 19:05 (7pm local time)
OnCalendar=*-*-* 19:05:00
Unit=wakebigstor.service

[Install]
WantedBy=timers.target

Autoshutdown

This is 3 parts - a systemd timer that runs 5 hours after we start the server, to attempt shutdown (this gives clients 5 hours to start their backups), a systemd service unit that calls a bash script, and a bash script that waits until there are no more tasks running in proxmox-backup-manager.

Bash Script

This script calls proxmox-backup-manager repeatedly. Hopefully you can understand my bash scripting. I put this file in /usr/local/bin/autoshutdown. Don’t forget to chmod +x it since it’s executable.

#!/bin/bash

#Count of times we have queried and there are tasks running
count=0
#Number of no-task intervals before we shutdown
max=10
#Interval in seconds
interval=5


#Continue until we shutdown
while true; do
    #Check if we should shutdown until we see not 
    if [[ $(proxmox-backup-manager task list) ]]; then
        #Continue to wait
        count=0
    else
        #There are no tasks running, so increment counter
        count=$((count + 1))
        echo "No tasks running, time until shutdown is $(((max - count) * interval)) seconds"
        #If we reached the max count, then shutdown
        if  ((count >= max)); then
            echo "Time to shutdown!"
            shutdown now
        fi
    fi
    #Delay by interval to next check
    sleep "$interval"
done
echo "Exiting"

Service Unit

And the service unit that calls autoshutdown goes in /etc/systemd/system/autoshutdown.service:

[Unit]
Description=Shutdown when there are no tasks left

[Service]
ExecStart=/usr/local/bin/autoshutdown

[Install]
WantedBy=default.target

Timer Unit

And it also has a timer, /etc/systemd/system/autoshutdown.timer:

[Unit]
Description=Shutdown
RefuseManualStart=no
RefuseManualStop=no

[Timer]
#Run at 22:00 local time
OnCalendar=*-*-* 22:00:00
Unit=autoshutdown.service

[Install]
WantedBy=timers.target

When you are done, don’t forget to run systemctl daemon-reload and systemctl enable --now autoshutdown.timer (but not the service unit, just the timer).

Mount Root FS noatime

To reduce writes to the SD card, I mounted the root fs with noatime. The line in my /etc/fstab now looks like this:

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sdh1 during installation
UUID=b58dfd0c-b6dc-4e44-a9b8-22ba3a5540d8 /               ext4    errors=remount-ro,noatime 0       1

Move Logs to Datastore Disks

Logs are stored in /var/log/proxmox-backup and a subdirectory for tasks can grow qutite significantly, with my larger file backups taking hundreds of MB for a log. This is not great for my root SD card, so I want to move them to zfs. I’m going to keep the api logs on root.

The zfs fs is already mounted at /mnt/datastore/backup (the datastore is named backup), so I created a zfs dataset backup/logs. I then rsync copied the logs into it rsync -r -v /var/log/proxmox-backup/tasks /mnt/datastore/backup/logs/, deleted the original rm -rf /var/log/proxmox-backup/tasks and symlinked it back back ln -s /mnt/datastore/backup/logs/tasks /var/log/proxmox-backup/tasks. I then needed to fix permissions to user/group backup:backup with chown backup:backup -R /mnt/datastore/backup/logs and chown backup:backup /var/log/proxmox-backup/tasks. After this, task logs were working correctly and backups were happy again.

Increase ZFS ARC Limit

Since the system exists primarily to store the data in ZFS and has no large workload otherwise, I increased the ARC max from 50% of system RAM (Default) to 75%, in my case 12GB. I did this by first calculating the number of bytes in 12GB (12884901888) and storing this in a new file /etc/modprobe.d/zfs.conf with the following contents:

options zfs zfs_arc_max=12884901888

This applies on the next boot.