No advice from the VAGUE peanut gallery today, but I did test the strategy I outlined in my previous email. It works, but using a set of units together like doesn't necessarily work well with DynamicUser, see https://github.com/systemd/systemd/issues/7090, but in this example there is no local state, so it works fine.

Here is a complete set of units (this time in nix syntax since that is what I tested):

  systemd.services.igd-nat = {
    description = "Configure the IGD's NAT";
    requires = [ "igd-nat.timer" ];
    before = [ "igd-nat.timer" ];
    serviceConfig = {
      DynamicUser = "yes";
      Type = "oneshot";
      RemainAfterExit = "yes";
      ExecStart = "";
    };
    preStop = ''
${pkgs.miniupnpc}/bin/upnpc -e "name of service" -d port-external UDP &
      ${pkgs.miniupnpc}/bin/upnpc -e "name of service" -d port-external TCP
    '';
  };

  systemd.services.igd-nat-renewal = {
    description = "Renew the IGD's NAT";
    partOf = [ "igd-nat.service" ];
    serviceConfig = {
      DynamicUser = "yes";
      Type = "oneshot";
    };
    script = ''
${pkgs.miniupnpc}/bin/upnpc -e "name of service" -r port-internal port-external UDP port-internal port-external TCP
    '';
  };

  systemd.timers.igd-nat = {
    description = "Renewal timer for the IGD's NAT";
    partOf = [ "igd-nat.service" ];
    timerConfig = {
      OnActiveSec= "0";
      OnUnitInactiveSec = "1m";
      Unit = "igd-nat-renewal.service";
    };
  };

These all start and stop together correctly with systemd start/stop.

--
Anthony Carrico

Reply via email to