Wake on lan for VM

Frigg

Active Member
Sep 4, 2016
63
2
28
52
Hello,

Some VMs are only useful on demand. Leaving them running all the time is a waste of hardware capacity.

I would like to allow users to run them on demand.


There are two solutions to do this:

1/ go through GUI permissions management.

But, to have VM.PowerMgmt rights, VM.Audit must also be allowed. The latter gives access to the notes of the summary, which may have content that should not be distributed.

> Is there a way to give only VM.PowerMgmt rights on certain VMs, without any other rights?


2/ use the Wake on lan command for VMs.

But VM bios do not include Wol function.

> How to do it?

Could you enhance the GUI to allow Wol on VMs?

Best regards
 
Hello

Wake on Lan needs a network card connected that in fact is powered.
As the VM does not really exist, for simulating this, the VM shoud be powered but in a "low powered" mode to only respond on a WOL packet ... I'm not sure that this functionnality would be power efficient regarding the normal electrical power consumption of a VM that does nothing.

A possible way is to script the "start" of the VM thru the Proxmox API.
https://pve.proxmox.com/wiki/Proxmox_VE_API

Regards
 
Hello Pierre-Yves,

Thank you for your answer.

It's not a question of energy, but rather of memory and processor resources. There are also many other reasons not to let machines run unnecessarily, if only in terms of security.
I am well aware of how WOL works. But since VM network cards are vitruous, I suppose that the magic packet addressed to their mac address can be "listened to" at the node, which will trigger their boot.

I've seen the API an script way, but don't have the level.
Best regards
 
To the OP did you ever figure this out? I remember having this functionality enabled in esxi when using a win10/gpu for a htpc function. At the end of the session the windows vm would be put to 'sleep', then wake via wol (shortcut on cell phone or any other standard wol magic packet) next time.
 
To the OP did you ever figure this out? I remember having this functionality enabled in esxi when using a win10/gpu for a htpc function. At the end of the session the windows vm would be put to 'sleep', then wake via wol (shortcut on cell phone or any other standard wol magic packet) next time.
No, and apparently there is little demand to integrate this function.
If this exists in other virtualization software, maybe the Proxmox team could take up the subject...
Thanks for your contribution
 
I wonder why it seems that nobody had the idea to do a search for this topic. Even "the search engine" finds this tagged old thread:
https://forum.proxmox.com/threads/update-wake-and-other-on-lan-for-vms-v0-3.26381/
Thank you for your contribution.
It seems that you are more efficient than me in your research.
This post had escaped me, and is indeed very interesting.
Anyway, since this feature exists in competing supervisors, maybe the Proxmox team could add the development of this feature into their roadmap, especially since you have done all the work to facilitate this...
I am not a computer scientist, and not very comfortable with scripts. So it would be easier for me if this function was built into the GUI.
If someone from the Proxmox team could take a stand, it would be nice.
 
Last edited:
The feature should be part of the proxmox services. So that any client, e.g. miniWOL can power up any VM as long as proxmox itself is running. Maybe the service written by @ojaksch can be made a default setup of proxmox.

(To get proxmox running, this setting can be enabled in the BIOS or by setting the network card via the console (and setting up a service that does it after every boot).)
 
Hello,
i fixed that with that simple Script:

Bash:
#!/bin/bash
re='^[0-9]+$'
while true ; do
    echo "\n" | nc -knl -p 9 -u | # listen to udp port 9 for packets, check if it is a magic packet
        stdbuf -o0 xxd -c 6 -p |
        stdbuf -o0 uniq |
        stdbuf -o0 grep -v 'ffffffffffff' |
        while read ; do
            macWOL="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"
            macWOL=`echo "$macWOL" |tr "[:upper:]" "[:lower:]"`     
            /usr/sbin/qm list  |tr -s ' ' | cut -d ' ' -f 2 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/qm config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/qm start $id
                    fi
                done
            fi
        done
    done
done

This script evaluates the magic packet on the proxmox host and checks wich VMS have the MAC-Address provided by the Magic Packet. Then the VM with the correct MAC-Address ist started.
 
Hi @stele99
works well thank you!
If so else needs it: I took your script, made it executable and startet it. Will be scheduled with cron in future.
I had the problem that the WOL package was not received by the script - I then noticed that the WOL tool (WOL2) by default uses port 6 instead of 9.

BR,
Hugo
 
Considering this discussion, I found it easier to use Proxmox API.
I created an API token for my user followed by its permission.
Then saved the token to a file in my user's home and restricted its permissions.

The following script works for me.

Bash:
#!/bin/bash

# SCRIPT TO START A PROXMOX VM

# SET UP API
PROX_HOST="proxmox.domain"
PROX_HOST_PORT="8006"
APIURL="https://${PROX_HOST}:${PROX_HOST_PORT}/api2"


# SET UP USER
TOKEN_FILE="./.pve-token"
TOKEN_NAME="API"
USERNAME="username"
REALM="pve"


# SET UP VM
NODE_NAME="node"
VM_TYPE="qemu"          # "qemu" for VM or "lxc" for container
VMID="106"


# POST A START REQUEST
curl -k -X POST \
        -H "Authorization: PVEAPIToken=${USERNAME}@${REALM}!${TOKEN_NAME}=$(cat $TOKEN_FILE)" \
        ${APIURL}/json/nodes/${NODE_NAME}/${VM_TYPE}/${VMID}/status/start


Observe the variables values for your own environment.
 
Last edited:
  • Like
Reactions: MilesTEG1
I been searching for this solution for a long time, I end up using ssh Snippets eg “qm start 100”
 
Last edited:
kindly explain how exactly are you doing it?
I use an app call Termius. Add proxmox as host. Add “qm start xxx” in Snippets. Everytime you want to start the vm open app, press the snippets.
 
@stele99 and others with an idea,
first of all thank you for your elegant short script. The first access to a switched off desired VM works perfectly. But as soon as I shut down the awakened VM and want to control it again, your script no longer registers the WOL packets. Sometimes it works twice but at the latest the third time it doesn't work anymore.
It never works with access to another following inactive VM.
Unfortunately, I can't see any causal error in your script. Do you have an idea?
If I abort the script and start it again, it works immediately as desired. The connection is made via Guacamole, for which WOL can be activated in the connection settings.

tcpdump -v -i vmbr0 ether proto 0x0842 or udp port 9
shows always received WOL-packets.
 
Last edited:
After trying to narrow down the problem for a few days, I ended up with the following condensed script:
#!/bin/bash while true ; do # listen to udp port 9 for packets, check if it is a magic packet echo "\n" | nc -knl -p 9 -u done
This stops working for me after about 5 attempts.
So it seems to be due to Netcat. Wrong parameter problem? Internal netcat problem?
Does anyone have an idea?
 
Last edited:
Hello,
i fixed that with that simple Script:

Bash:
#!/bin/bash
re='^[0-9]+$'
while true ; do
    echo "\n" | nc -knl -p 9 -u | # listen to udp port 9 for packets, check if it is a magic packet
        stdbuf -o0 xxd -c 6 -p |
        stdbuf -o0 uniq |
        stdbuf -o0 grep -v 'ffffffffffff' |
        while read ; do
            macWOL="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"
            macWOL=`echo "$macWOL" |tr "[:upper:]" "[:lower:]"` 
            /usr/sbin/qm list  |tr -s ' ' | cut -d ' ' -f 2 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/qm config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/qm start $id
                    fi
                done
            fi
        done
    done
done

This script evaluates the magic packet on the proxmox host and checks wich VMS have the MAC-Address provided by the Magic Packet. Then the VM with the correct MAC-Address ist started.

Hello,
I change script stele99 and now this start WOL your CT too:

wol.sh
Bash:
#!/bin/bash
re='^[0-9]+$'
while true ; do
    echo "\n" | nc -knl -p 9 -u | # listen to udp port 9 for packets, check if it is a magic packet
        stdbuf -o0 xxd -c 6 -p |
        stdbuf -o0 uniq |
        stdbuf -o0 grep -v 'ffffffffffff' |
        while read ; do
            macWOL="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"
            macWOL=`echo "$macWOL" |tr "[:upper:]" "[:lower:]"`  
            /usr/sbin/qm list  |tr -s ' ' | cut -d ' ' -f 2 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/qm config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/qm start $id
                    fi
                done
            fi
    done
        /usr/sbin/pct list  |tr -s ' ' | cut -d ' ' -f 1 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/pct config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/pct start $id
                    fi
                done
            fi
        done
    done
done


And add to autostart:

cp wol.sh /usr/local/bin/wol.sh
chmod +x /usr/local/bin/wol.sh

make file wol.service.app
Code:
[Unit]
Description=WOL (Wakeup on LAN)

[Service]
Type=simple
ExecStart=/bin/bash /usr/local/bin/wol.sh

[Install]
WantedBy=multi-user.target

cp wol.service.app /etc/systemd/system/wol.service
chmod 644 /etc/systemd/system/wol.service
systemctl enable wol.service

reboot your server and try
 
Last edited:
Did you see/checked any difference between systemd-autostart and manual shell-start regarding my comments?
 
Hello,
I change script stele99 and now this start WOL your CT too:

wol.sh
Bash:
#!/bin/bash
re='^[0-9]+$'
while true ; do
    echo "\n" | nc -knl -p 9 -u | # listen to udp port 9 for packets, check if it is a magic packet
        stdbuf -o0 xxd -c 6 -p |
        stdbuf -o0 uniq |
        stdbuf -o0 grep -v 'ffffffffffff' |
        while read ; do
            macWOL="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"
            macWOL=`echo "$macWOL" |tr "[:upper:]" "[:lower:]"`
            /usr/sbin/qm list  |tr -s ' ' | cut -d ' ' -f 2 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/qm config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/qm start $id
                    fi
                done
            fi
    done
        /usr/sbin/pct list  |tr -s ' ' | cut -d ' ' -f 1 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/pct config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/pct start $id
                    fi
                done
            fi
        done
    done
done


And add to autostart:

cp wol.sh /usr/local/bin/wol.sh
chmod +x /usr/local/bin/wol.sh

make file wol.service.app
Code:
[Unit]
Description=WOL (Wakeup on LAN)

[Service]
Type=simple
ExecStart=/bin/bash /usr/local/bin/wol.sh

[Install]
WantedBy=multi-user.target

cp wol.service.app /etc/systemd/system/wol.service
chmod 644 /etc/systemd/system/wol.service
systemctl enable wol.service

reboot your server and try

This script still seems to stop after the first received magic package.. I'm not 100% sure what exactly is happening, but from some troubleshooting I can now tell:
  1. Script receives magic package containing the MAC address to be woken up
  2. Script goes through one iteration for every VM and container, eventually waking up the desired one
  3. Script goes through an additional iteration within
Bash:
echo "\n" | nc -knl -p 9 -u | # listen to udp port 9 for packets, check if it is a magic packet
        stdbuf -o0 xxd -c 6 -p |
        stdbuf -o0 uniq |
        stdbuf -o0 grep -v 'ffffffffffff' |
        while read ; do

with the MAC-address being set to 00:00:00:00:00:00​
4. Script hangs in an infinite loop, never listening to another magic package​

Here is my dirty fix, which
  • just restarts the service in order to reset the script*
  • added some extra logging for journalctl -u wol.service -f
  • adds "resume" to the wake-up call, if the machine is sleeping

*(I chose this way instead of calling the script again, since that would probably cause memory issues for longer operation – anybody feel free to correct me; I'm new to this)

I tried to figure out how to break or continue the while read loop, but I wasn't able to.. If someone knows bash a bit better than me, please provide your solution since that would be much cleaner than restarting the service..

Bash:
#!/bin/bash
re='^[0-9]+$'
port=7 # Define UDP port to listen on for the package
echo "Starting Wake on LAN script"

while true ; do
    echo "Listening on UDP port $port ..."
    echo "\n" | nc -knl -p $port -u | # listen to udp port (default: 9) for packets, check if it is a magic packet
        stdbuf -o0 xxd -c 6 -p |
        stdbuf -o0 uniq |
        stdbuf -o0 grep -v 'ffffffffffff' |
    while read ; do
        macWOL="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"
          if [[ "00:00:00:00:00:00" == *"$macWOL"* ]]; then
            echo "script is finished and would go to endless loop. Restarting service..."
            systemctl restart wol.service
          fi
        macWOL=`echo "$macWOL" |tr "[:upper:]" "[:lower:]"`
        #VM loop
            /usr/sbin/qm list  |tr -s ' ' | cut -d ' ' -f 2 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/qm config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/qm start $id
                        /usr/sbin/qm resume $id
                    fi
                done
            fi
    done
  
        #container loop
        /usr/sbin/pct list  |tr -s ' ' | cut -d ' ' -f 1 | while read -r id ; do
            if [[ $id =~ $re ]] ; then
                echo  "check VM-ID $id for $macWOL"
                /usr/sbin/pct config $id | grep ^net0 | while read -r macstr ; do
                    macstr=`echo "$macstr" |tr "[:upper:]" "[:lower:]"`
                    if [[ $macstr == *"$macWOL"* ]]; then
                        echo "MAC $macWOL found at VMID  $id. Starting VM"
                        /usr/sbin/pct start $id
                        /usr/sbin/pct resume $id
                    fi
                done
            fi
        done
    done
# the script never reaches here.. and I do not know why,
# which is why we just restart the service to listen for
# new magic packages after the first iteration
done

echo "script has concluded and stopped.. this should never happen"
 
Last edited:
I keep getting this error: stdbuf: failed to run command ‘xxd’: No such file or directory

Idk if it's because I'm using PVE 8.0.3, but I would like to use this script for my config.
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!