"Network is unreachable" error in systemd service

Hello - I have been using some flavor of Linux on my home desktop system for many years, but am very new to NixOS (still trying to learn how to use flakes).

This is my systemd service for making a daily, incremental backup of my wife’s laptop - it uses rsnapshot (an rsync wrapper) to back it up to an external drive attached to my system:

  # systemd timer and service for daily laptop backup:  
  systemd.timers."netback" = {
    enable = true;
    wantedBy = [ "timers.target" ];
    timerConfig = {
      OnCalendar = "hourly";
      Persistent = "true";
      Unit = "netback.service";
    };
  };
  systemd.services."netback" = {
    after = [ "network-online.target" ];
    wants = [ "network-online.target" ];
    description = "Daily backup of Debbie's laptop";
    serviceConfig = {
      Type = "simple";
      Environment = ''PATH=/run/wrappers/bin:/etc/profiles/per-user/root/bin:/nix/profile/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin'';
      ExecStart = ''/nix/profile/bin/netback -c /etc/shared/backup/netback_debbie.conf --daily'';
    };
  };


The problem is that the first time netback.service runs after booting up, a ping fails with “ping: connect: Network is unreachable”.

My workaround is to sleep a few seconds and retry if the ping exit code is 2 (in my testing with this, the ping exit code is 1 if the laptop is shut down). After a 10 second wait, the ping is successful. So I guess this “fixes” the problem, but I think it is kind of ugly. Why is a delay needed if the service has reached “network-online”?

From https://systemd.io/NETWORK_ONLINE:

network-online.target is a target that actively waits until the network is “up”, where the definition of “up” is defined by the network management software. Usually it indicates a configured, routable IP address of some kind.

So, whether this works depends on which network daemon you have.

For NetworkManager or systemd-networkd, the default should be that network-online is delayed by a service (*-wait-online.service) that waits for at least one IP address to be configured on any interface via DHCP (check systemd.network.wait-online.enable).

For dhcpcd, unless you configured a static gateway, network-online should be delayed by dhcpcd itself until an address is received on any interface it manages (check networking.dhcpcd.wait).

For connman, I don’t think network-online.target is used at all.

In a standard home network, I think receiving an address should be enough to reach a LAN host, but if you want to be safe you could use a script like this:

systemd.services."netback" = {
  after = [ "network-online.target" ];
  wants = [ "network-online.target" ];
  description = "Daily backup of Debbie's laptop";
  serviceConfig = {
    Type = "simple";
    Environment = ''PATH=/run/wrappers/bin:/etc/profiles/per-user/root/bin:/nix/profile/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin'';
  };
  script = ''
    until ping -c1 -w1 backup-host; do sleep 1; done
    /nix/profile/bin/netback -c /etc/shared/backup/netback_debbie.conf --daily
  '';
};

Thank-you. I was using dhcpcd, but I have switched to networkmanager and it looks like this doesn’t happen. For now, I’ll stick with that.