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

nixos/wireguard: Add dynamicEndpointRefreshSeconds option #121331

Merged
merged 3 commits into from
May 24, 2021

Conversation

nh2
Copy link
Contributor

@nh2 nh2 commented Apr 30, 2021

Motivation for this change

Implements refreshing the IP of DNS-based endpoints periodically, which WireGuard itself cannot do. It only does it once at the beginning when the wg utility is invoked.

See also ArchWiki: Endpoint with changing IP

Those also mention a script called reresolve-dns that is included in WireGuard's examples folder (but not packaged in nixpkgs); however, that does some pretty ugly shell-based config file parsing, and it is much cleaner to just periodically execute the wg set wg0 peer command we already construct in the module for initial setup.

Also included:

  • A refactoring that implement correct shell argument quoting for all CLI invocations
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.

Standard best-practice shell quoting, which can prevent the most
horrible production accidents.

Note that we cannot use `+ optionalString someBool '' someString''`
because Nix's multi-line ''double-quoted'' strings remove leading
whitespace.
@nh2 nh2 added the 0.kind: enhancement Add something new label Apr 30, 2021
@nh2 nh2 self-assigned this Apr 30, 2021
@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: changelog 8.has: documentation This PR adds or changes documentation 8.has: module (update) This PR changes an existing module in `nixos/` labels Apr 30, 2021
@nh2 nh2 requested a review from dotlambda April 30, 2021 21:32
@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 10.rebuild-linux: 1 labels Apr 30, 2021
@dotlambda dotlambda changed the title wireguard module: Add dynamicEndpointRefreshSeconds option nixo/wireguard: Add dynamicEndpointRefreshSeconds option May 1, 2021
@nh2 nh2 mentioned this pull request May 7, 2021
@peterhoeg
Copy link
Member

The feature is great, but turning the regular oneshot service into simple + sleep gives me a slightly bad taste in the mouth. How about this instead - leave the exiting units alone and then have a simple timer + oneshot that runs the wg set wg0 peer bit?

@nh2
Copy link
Contributor Author

nh2 commented May 13, 2021

How about this instead - leave the exiting units alone and then have a simple timer + oneshot that runs the wg set wg0 peer bit?

@peterhoeg I am not in favour of it, because timers + oneshot do not work well with reliable automation:

  • It is not easy to determine whether the DNS update loop is currently "running" or not. I need that for my NixOps setups; for example, I need other services to shut down if the Wireguard refresh stops working.
    Systemd gives us tools like Requires, BindsTo etc, to run something when a simple service is up, but none of those work well with timers and oneshots.
  • systemd timers have bugs that stop them from working after a while, which I have already observed on NixOS in production, and which I cannot afford on important fundamental infrastructure services like VPN.

turning the regular oneshot service into simple + sleep gives me a slightly bad taste in the mouth

That surprises me a bit -- I found it quite sensible that a "do it once" configuration turns into a oneshot, and a "do it permanently" configuration turns into a simple.

@nh2
Copy link
Contributor Author

nh2 commented May 13, 2021

How about this instead - leave the exiting units alone and then have a simple timer + oneshot that runs the wg set wg0 peer bit?

@peterhoeg I am not in favour of it, because timers + oneshot do not work well with reliable automation:

  • It is not easy to determine whether the DNS update loop is currently "running" or not. I need that for my NixOps setups; for example, I need other services to shut down if the Wireguard refresh stops working.
    Systemd gives us tools like Requires, BindsTo etc, to run something when a simple service is up, but none of those work well with timers and oneshots.
  • systemd timers have bugs that stop them from working after a while, which I have already observed on NixOS in production, and which I cannot afford on important fundamental infrastructure services like VPN.

turning the regular oneshot service into simple + sleep gives me a slightly bad taste in the mouth

That surprises me a bit -- I found it quite sensible that a "do it once" configuration turns into a oneshot, and a "do it permanently" configuration turns into a simple.

We could make a separate simple service though (with a different name), if that would be preferred, e.g. wireguard-${interfaceName}-peer-${unitName}-refresh or so.

@fricklerhandwerk
Copy link
Contributor

Diff LGTM. Excellent documentation!

@dotlambda dotlambda changed the title nixo/wireguard: Add dynamicEndpointRefreshSeconds option nixos/wireguard: Add dynamicEndpointRefreshSeconds option May 13, 2021
@nh2 nh2 force-pushed the wireguard-dynamicEndpointRefreshSeconds branch from 51f8edd to 83ed11c Compare May 16, 2021 15:55
@nh2
Copy link
Contributor Author

nh2 commented May 16, 2021

I've force-pushed out the timer, which was superfluous from my preivous implementation.

@nh2 nh2 force-pushed the wireguard-dynamicEndpointRefreshSeconds branch from 83ed11c to 0da7487 Compare May 16, 2021 18:12
@nh2
Copy link
Contributor Author

nh2 commented May 16, 2021

(with a different name), if that would be preferred, e.g. wireguard-${interfaceName}-peer-${unitName}-refresh

I have implemented this with the last force-push; the service is now suffixed -refresh if it's a simple.

@nh2 nh2 merged commit 83a8acc into NixOS:master May 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0.kind: enhancement Add something new 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: changelog 8.has: documentation This PR adds or changes documentation 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 10.rebuild-linux: 1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants