Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wakeonlan service: use powerUpCommands #97362

Merged
merged 1 commit into from Dec 18, 2020
Merged

Conversation

martinetd
Copy link
Member

Motivation for this change

powerDownCommands is supposed to run before shutdown, but the current
implementation only runs before-sleep, thus not enabling wakeonlan on
devices when powering off even if the hardware supports it.

Taking into consideration the possibility of unexpected shutdown, it is
preferable to move the commands to powerUpCommands instead which is
executed at boot time as well as after resume - that should cover all
use cases for wakeonlan.

Fixes #91352

I'll fill in a second PR to rename powerDownCommands into preSleepCommands (like resumeCommands) after this gets merged, it looks like nothing that currently uses powerDownCommands actually cares about power off time.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

powerDownCommands is supposed to run before shutdown, but the current
implementation only runs before-sleep, thus not enabling wakeonlan on
devices when powering off even if the hardware supports it.

Taking into consideration the possibility of unexpected shutdown, it is
preferable to move the commands to powerUpCommands instead which is
executed at boot time as well as after resume - that should cover all
use cases for wakeonlan.

Fixes NixOS#91352
Copy link
Contributor

@rnhmjoj rnhmjoj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the long wait.
I agree this should be moved to power up in order to run as early as possible, but I don't really like the idea of renaming powerDownCommands to preSleepCommands: it's like sweeping the problem under a rug. I'll look for a way to actually make it run at power down.

@rnhmjoj rnhmjoj merged commit d7b5284 into NixOS:master Dec 18, 2020
@magnetophon
Copy link
Member

Thanks for the fix.
Maybe something to backport to 20.09?

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 20, 2021

Done: d6f95aa

@magnetophon
Copy link
Member

Great, thanks!

@magnetophon
Copy link
Member

After some more testing, I found out my server doesn't seem to have the network interface ready when ethtool is called, so I ended up using:

  systemd.services.wol-eth0 = {
    description = "Wake-on-LAN for eno1";
    requires = [ "network.target" ];
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      Type = "oneshot";
      ExecStart = "${pkgs.ethtool}/bin/ethtool -s eno1 wol g"; # magicpacket
    };
  };

Seems like the most logical moment to do it, since by definition the network is ready to go, so the interface must be too.
Not sure how to do it in the correct way for inclusion upstream though.

magnetophon added a commit to magnetophon/nixosConfig that referenced this pull request Apr 20, 2021
@martinetd
Copy link
Member Author

@magnetophon the problem with this simple systemd service is that if you use wol for wake from suspend, you need to run the command again after everytime the system gets out of suspend; which is something powerUpCommand does.

For the initial post-boot run, it is indeed run pretty early (at the end of bootStage2, before the main systemd kicks in with networking and everything) -- I've personally not had a problem with network not being ready, do you get an error or did you just notice wol is not actually enabled? That might be hardware/driver dependent, in which case an extra after network.target service might be good for safety... Better activate wol twice than none :|

@magnetophon
Copy link
Member

Thanks for the heads up, I've un-commented my services.wakeonlan.interfaces again to make sure!

I indeed got an error.

Ideally we'd find a place to run it that covers both cases in one go, right?
Any ideas?

@martinetd
Copy link
Member Author

Do you still have the error for reference? (mostly curiosity on my part)

And I guess yes, ideally not reinvent the wheel by recreating two services ourselves, but I'm afraid I don't really know of a magic place that would cover both.
I guess the second best would be powerManagement.resumeCommands instaed of powerUpCommands (that only covers after-resume-from-sleep/hibernation/etc) plus an extra service after network like you've done, that will cover both usecases.

Although err now I'm looking at it again it doesn't have any wantedBy/requiredBy so I can't say I'm confident it actually works, would need testing somewhere that can suspend freely, I don't have anywhere to...

At this rate though it might be simpler to just define a systemd service like you did yourself and put it in multi-user.target after network.target and in wantedBy sleep.target after sleep.target; will need testing but that should work to just list both in after and wantedBy in a single service...

@magnetophon
Copy link
Member

magnetophon commented Apr 20, 2021

Thanks.

I didn't save the error and it'd be a bit of an expedition to get it again.
If it's mostly curiosity, I'd like to spare myself the hassle.

On the other hand, I would be more then happy to test any proposals for a solution that can be up-streamed.

@legendofmiracles
Copy link
Contributor

legendofmiracles commented Sep 28, 2021

Same here, it seems like the interface gets reset later on in the boot process.

My manual solution, but with a systemd link file:

  # enables wake on lan
  systemd.network.links."50-wol" = {
    enable = true;
    matchConfig = {
      MACAddress = "00:00:00:00:00:00";
    };
    linkConfig = {
      NamePolicy = "kernel database onboard slot path";
      MACAddressPolicy = "persistent";
      WakeOnLan = "magic";
    };
  };

Based on this here: https://wiki.archlinux.org/title/Wol#systemd.link

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Sep 28, 2021

Using a link seems more reliable and only requires systemd-udev, which is always available.
It's worth considering to rewrite this module to use them.

@legendofmiracles
Copy link
Contributor

The downside of this is that you need to know the mac address, a larger burden for the user who wants to enable it.
I tried using the name attribute as described in the arch wiki article, but it did not work.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Sep 28, 2021

That's true, but matching the interface by name isn't reliable. The standard kernel names (ie. eth0, eth1) tends to flip-flop across reboots and the systemd names (ie. ens1) change when adding new hardware or changing BIOS settings. To be really sure the name is stable you have to manually assign the name beforehand using a MAC address anyway.

@legendofmiracles
Copy link
Contributor

legendofmiracles commented Sep 28, 2021

If this is going to happen, maybe we should consider moving the wakeonlan option under interface, so e.g.

networking.interfaces.enp8s0.wol = {
  enable = true;
  # if set to anything then it's assumed as the prefered method
  password = "";
  # mac address only needed if networking.interfaces.name.macAdress is not set
  macAdress = "bla bla";
}

would by my preferred way of configuring it

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Sep 29, 2021

Good idea: the current services.wakeonlan doesn't make much sense given the module doesn't set up a service.

@legendofmiracles
Copy link
Contributor

I've looked into implementing this, and the mac option wouldn't be needed since the option in the interfaces is meant to override. And the only way how you can select interfaces is by name, which are assumed stable in newer kernels and udev/systemd releases.

One problem that I have faced tho is that it seems you cannot enable secureon for wol with the systemd link file, the option exists but I cannot figure out how to pass the specific password to systemd, the relevant code (judging by a quick glance) doesn't give any hints how to, so maybe it's not possible (read: a bug in systemd). https://man.archlinux.org/man/systemd.link.5

@legendofmiracles
Copy link
Contributor

I made a quick mockup here: legendofmiracles@b8ea535, it works on my system.

But the password option doesn't work yet, due to the issues mentioned above.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Oct 2, 2021

But the password option doesn't work yet, due to the issues mentioned above.

I've opened an issue, let's see.

@legendofmiracles
Copy link
Contributor

It's probably worth upstreaming my fork without the secure on support. I doubt anyone actually uses it (as shown by the fact that systend only had half assed support, but nobody complained). Waiting for the next systems release, if it even gets merged by then, is not really in my interest and the people having to manually setup wol due to it not working for them.

@legendofmiracles
Copy link
Contributor

PR is here: #140779

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wake-On-Lan won't work, after poweroff
4 participants