Nixpkgs: How to override Wireguard unit?

Created on 23 Jun 2017  路  8Comments  路  Source: NixOS/nixpkgs

Issue description

Subj.

My unit file:

[Unit]
Description=WireGuard Client

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/ip netns add vpn0
ExecStart=/bin/ip link set enp3s0 down
ExecStart=/bin/ip link set wlp2s0b1 down
ExecStart=/bin/ip link set enp3s0 netns vpn0
ExecStart=/bin/iw phy phy0 set netns name vpn0
ExecStart=/bin/ip -n vpn0 link add wg0 type wireguard
ExecStart=/bin/ip -n vpn0 link set wg0 netns 1
ExecStart=/bin/ip netns exec vpn0 dhcpcd enp3s0
ExecStart=/bin/ip address add fc00::*/64  dev wg0
ExecStart=/bin/ip address add 192.***.***.*/24 dev wg0
ExecStart=/bin/wg setconf wg0 /etc/wireguard/client.conf
ExecStart=/bin/ip link set mtu 1400 dev wg0
ExecStart=/bin/ip link set wg0 up 
ExecStart=/bin/ip route add default dev wg0
ExecStart=/bin/ip -6 route add default dev wg0
ExecStart=/bin/dnscrypt-proxy /etc/dnscrypt-proxy.conf

ExecStop=/bin/ip -n vpn0 link set enp3s0 down
ExecStop=/bin/ip -n vpn0 link set wlp2s0b1 down
ExecStop=/bin/ip -n vpn0 link set enp3s0 netns 1
ExecStop=/bin/ip netns exec vpn0 iw phy phy0 set netns 1
ExecStop=/bin/ip link del wg0
ExecStop=/bin/ip netns del vpn0
ExecStop=/bin/killall dnscrypt-proxy

[Install]
WantedBy=multi-user.target

I'm not sure that options 'postSetup' & 'preSetup' can help me.

Maybe add option for custom unit? If this option not found, use default unit.

All 8 comments

preSetup and postSetup can be used for all the ExecStart commands that are not run by default, for example:

  networking.wireguard = {
    wg0 = {
      ips = [ "192.168.20.4/24" ];
      privateKey = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
      peers = [
        { allowedIPs = [ "192.168.20.1/32" ];
          publicKey  = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
          endpoint   = "demo.wireguard.io:12913"; }
      ];
      preSetup = [
        "${pkgs.iproute}/bin/ip netns add vpn0"
        "${pkgs.iproute}/bin/ip set enp3s0 down"
        ...
      ];
      postSetup = [
        "${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy /etc/dnscrypt-proxy.conf"
      ];
    };
  };

Maybe add option for custom unit? If this option not found, use default unit.

The whole point of the module is to abstract the systemd unit creation so I think it would not make much sense to add a such option.
But you can easily create a custom systemd unit in configuration.nix by adding an entry in systemd.services, eg:

  systemd.services.wireguard = {
    description = "WireGuard Client";
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = true;
      ExecStart = [
        "${pkgs.iproute}/bin/ip netns add vpn0"
        ...
      ];
      ExecStop = [
        "${pkgs.iproute}/bin/ip -n vpn0 link set enp3s0 down"
        ...
      ];
    };
  };

Hope that helps.

But how i can disable default wireguard unit?

If there is no wireguard interfaces configured, the module will not generate any unit.

So if you remove all the networking.wireguard settings from configuration.nix, the wireguard module will do nothing.

If i want use wireguard with my own systemd unit, i can comment this line and use new unit from systemd.services.wireguard? Right?

If i want use wireguard with my own systemd unit, i can comment this line and use new unit from systemd.services.wireguard? Right?

You don't even need to comment that.

  config = mkIf (cfg.interfaces != {}) {

    boot.extraModulePackages = [ kernel.wireguard ];
    environment.systemPackages = [ pkgs.wireguard ];

    systemd.services = mapAttrs' generateUnit cfg.interfaces;

  };

The config is applied if the condition in the mkIf evaluates to true. The condition is cfg.interfaces != {}, so if there are no networking.wireguard interfaces configured, the module will not generate any unit.

You can check the value of networking.wireguard value by running the following command:

$ nixos-option networking.wireguard.interfaces
Value:
{ }

Default:
{ }

Example:
{ wg0 = <CODE>; }

If its value is { }, then no unit will be generated.

I'm confused. Sorry.
I have configured interface, like this:

  networking.wireguard.interfaces.wg0.privateKey = "BBB...";
  networking.wireguard.interfaces.wg0.listenPort = 50505;
  networking.wireguard.interfaces.wg0.peers = [
    {
      publicKey = "AAA...";
      endpoint = "[2a01:***:***::5]:60606;
      allowedIPs = [ "::/0" "0.0.0.0/0" ];
    }
  ];

But i don't want to use generated config from generateUnit, because i have my own unit with network namespace. They are differents (units)...
And it's not possible, because i have configured interface in networking.wireguard.interfaces.wg0 that always return true in mkIf...

If you do not want to use the generated unit, then there is no point in setting any networking.wireguard setting, as these settings are only used generate the systemd unit.

So if the generated unit doesn't match your needs, you can just go with a custom one like:

  systemd.services.wireguard = {
    description = "WireGuard Client";
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = true;
      ExecStart = [
        "${pkgs.iproute}/bin/ip netns add vpn0"
        ...
      ];
      ExecStop = [
        "${pkgs.iproute}/bin/ip -n vpn0 link set enp3s0 down"
        ...
      ];
    };
  };

The wireguard module basically generate a generic systemd unit like the one above according to the networking.wireguard settings.

Also, if you go with the custom unit, do not forget to add the wireguard kernel module explicitly in configuration.nix:

  boot.extraModulePackages = [ config.boot.kernelPackages.wireguard ];

Thank you so much.

Was this page helpful?
0 / 5 - 0 ratings