Wake On Lan - For those running home assistant in docker

I guess if someone gets inside your home-assistant docker then they could ssh into your server as the user?

The user wouldn’t be root though, Could you create a user with very little access?

Thank you for your guidance. But to be honest, I don’t think it is better or safer than using the Network Mode Host or giving the container its own IP address via macvlan?

I have very limited knowledge.
I do know that network mode host doesn’t work well for docker if you are running reverse_proxy and other services as well.
Yes macvlan would be better.

Macvlan or Host Network will work perfectly with a proxy if you assign both networks (and the proxy’s) to the HA container.
This is how it looks like in my case in combination with Macvlan and Traefik as proxy:

  homeassistant:
    container_name: home-assistant
    image: homeassistant/home-assistant
    networks:
      mynet:
        ipv4_address: 192.168.178.203
      proxy:
    logging:
      driver: "fluentd"
      options:
        fluentd-address: 172.20.0.6:24224
        tag: docker.homeassistant
    depends_on:
      - "timescale"
      - "esphome"
      - "mqtt"
      - "reverse-proxy"
      - "deconz"
    restart: always
    volumes:
      - /srv/dev-disk-by-id-ata-ST32000542AS_5XW2HFG7/data/docker_data/homeassistant:/config
      - /etc/localtime:/etc/localtime:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https@docker"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      - "traefik.http.routers.homeassistant.rule=Host(`MYWEBADRESS.de`)"
      - "traefik.http.routers.homeassistant.entrypoints=websecure"
      - "traefik.http.routers.homeassistant.tls.certresolver=mytlschallenge"
      - "traefik.http.services.homeassistant.loadbalancer.server.port=8123"
      - "traefik.docker.network=proxy"
    ports:
      - "8123:8123"

I use letsencrypt so would have to change the subdomain.conf file and have not quite figured out that part.

The Traefik Proxy automatically generates SSL certificates via Letsencrypt for all domains :wink:

What do you mean by subdomain.conf?

I don’t use Traefik.

I’ve updated my post so that the ssh user just runs one commands then exits, it doesn’t have access to do anything else.

I just followed the Home Assistant guide and then adapted the command within the configuration.yaml file

## wol ##

wake_on_lan:

shell_command:
  turn_off_rocky: "ssh -i /config/.ssh/id_rsa -o StrictHostKeyChecking=no  [user]@192.168.1.1 'sudo systemctl start systemd-suspend.service'"

I also used the following command to copy the contents of the /config/.ssh folder out of the container for persistence:

sudo podman cp hassos:./.ssh/ /home/hassos/config/.ssh/

in terms of the question raised by @brahmafear regarding the authrozed_keys file - ssh-copy-id does exactly that, it copies the generated public key to the authorized_keys file of your target node and saves you having to cat, copy, vi etc.

I wanted to post my reply in this old thread to share my solution to this, mainly because this was my first hit when searching for a solution to wake-on-lan from Docker.

I don’t want to use host network, and I was reluctant to use the ssh solution presented here (good effort and documentation though!).

My solution was to use named pipe, inspired by this answer from Stackoverflow
I also took inspiration from this thread with how to structure the switch on_command.

I had never used named pipes prior to this, so I won’t go into detail how they work. See the Stackoverflow post above for some more explanation, or do a quick google.
For our purposes, they are a way of passing information from docker to the controlling host. We will use the ability of wakeonlan to read the mac-adress from a file, that file will be our named pipe which will just be waiting for us to input the mac-adress to it.

Howto (tested on Ubuntu Server 18.04)
Install wakeonlan if you don’t have it already
sudo apt install wakeonlan

Create a named pipe. You can create it anywhere. If you choose a new location you must expose that location to your home assistant container.
I found it simplest to just create the pipe in home assistants config directory, remember to change the path to your own:
sudo mkfifo /path/to/homeassistant/config/wolpipe

Normally the pipe would be created with correct permission, to set them properly just in case use the command below (probably optional):
sudo chmod 644 /path/to/homeassistant/config/wolpipe

Create a systemd-service to continously listen for WOL-requests from the named pipe.
Remember to change the path to your homeassistant config directory.
Note that the service will be running as user nobody which should severely limit what a potential attacker could do on your docker host even if attacker gains access to your docker container

sudo cat > /etc/systemd/system/docker-wol.service << EOF
[Unit]
Description=Listen for wake-on-lan from docker via pipe

[Service]
Restart=always
User=nobody
Group=nogroup
ExecStart=/usr/bin/wakeonlan -f /path/to/homeassistant/config/wolpipe

[Install]
WantedBy=multi-user.target
EOF

Reload systemd, start the service and set the service to start on boot (if that’s what you want)

sudo systemctl daemon-reload
sudo systemctl start docker-wol
sudo systemctl enable docker-wol

At this point you should be able to send the mac-adress through the pipe and have your appliance turn on, to test:
sudo echo 'ma:ca:dd:re:ss' > /path/to/homeassistant/config/wolpipe

To verify, check your appliance and the logs of the service you created
journalctl -fu docker-wol

If you repeat the above test it should keep working since systemd restarts the command everytime it completes.

Now you can do the same thing from inside the home-assistant docker container.
To test communication from inside docker, get a shell on the container:
docker exec -it homeassistant bash

Run the same echo command there but use the path inside the container:
echo 'ma:ca:dd:re:ss' > /config/wolpipe

It should still work.

Finally some inspiration to what I did to get my LG WebOS TV to work with wake-on-lan from docker, in configuration.yaml (Edited for version 2022.2.0)

#wake_on_lan: # Home assistant wol support not needed anymore

webostv:
  host: !secret tvrum_ip
  name: TV-rum
  customize:
    sources:
      - MySources

shell_command:
  tvrum_wol: !secret tvrum_command_on

# Either put this here or in your automations.yaml
automation:
  - id: 'tvrum_wol'
    trigger:
      - platform: webostv.turn_on
        entity_id: media_player.tv_rum
    action:
      - service: shell_command.tvrum_wol

media_player:

Then in secrets.yaml I put the entire command line (note that we’re using the path inside the docker container here):

tvrum_command_on: "/bin/echo 'ma:ca:dd:re:ss' > /config/wolpipe"
other_secrets: 123456

Good luck, hope this helps anyone.

6 Likes

Hi Peter, thanks for posting the namedpipes method for WOL. I’m trying to implement this but get permission denied when I try to test the new service. Any ideas?

FYI, the stack post suggested to tail the pipe and then from another terminal test, which I tried but that didn’t help.

For what it’s worth, Simon’s macvlan approach worked well for me. I can now use wakeonlan like I’m truly on my local network.

Sorry for the really late reply.
Did you manage to solve this? If not, could you give any more details as to what is not working? What kind of permission errors did you get?

Hi @peterh, I think I used a different process in the end. no biggie, 18 ways to skin that cat!

1 Like

@peterh thanks for that solution with pipes, works great! Only thing i needed to do was to run the service as my regular user otherwise it couldnt run wakeonlan probably better ways to do it but works.

User=myuser
Group=myuser

I have the same problem with WOL with my HA docker.

Tried the named pipe method but it doesnt seem to be working. I want to try the macvlan method which seems more elegant but I already have my network adapter used for the pihole docker macvlan network.

I can’t seem to be able to create another macvlan for HA since the network adapter is already being used. Any other way around this?

Sorry if I am not sharing enough information. I am not well-versed in Linux.

I tried the named pipe solution and got some permission issues like others.
Solved this by changing user nobody by root and the same for nogroup.
It’s working great now and this allow me to switch on my NAS from anywhere through remote and secured access to Home Assistant.
This might give my family access to pictures archives at any time, without the need to keep the NAS constantly ON.
Thanks a lot Peter.

Great thought! The service definition was throwing errors in my setup for some reason, but creating a script such as the below and calling that one as ExecStart did the trick for me:

#!/bin/bash

pipe=/virtual/other/homeassistant/config/wolpipe
remac=“^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$” # regex for mac address

while true
do
if read line <$pipe; then
if [[ “$line” =~ $re ]]; then
wakeonlan -i 192.168.2.99 $line # where 192.168.2.99 is the dummy target IP of my wol forwarder between subnets
fi
fi
done

Hi Gary.
I too got the permission error, when trying to test it (the echo command):
I had to changed the chmod value to 666 - e.i.:
sudo chmod 666 /path/to/homeassistant/config/wolpipe

This is a great solution, thanks a lot for sharing! I will only add that for me it was failing at first with

Permission denied at /usr/bin/wakeonlan

error, which I guess was because I created the pipe inside a root-owned directory. So I just re-created it at /opt/wolpipe (and added mapping for it on container creation with -v), and then it went fine, I didn’t even need to chown it to a different user.

One other thing to add here is that for nobody user I was getting this warning:

Special user nobody configured, this is not safe!

so I replaced User=nodoby with DynamicUser=yes in the /etc/systemd/system/docker-wol.service, and now it’s all perfectly splendid (unless there are other security-related problems with exposing named pipes, which I don’t yet know about).