summary refs log tree commit diff
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-04-18 23:43:53 +0200
committerMel <mel@rnrd.eu>2025-04-19 00:37:00 +0200
commitb0865ada5b4dffa0471f046cf8420ed34c587131 (patch)
tree5e09badb69d5d0730f1f06d42262d6fa1dab0174
parent7dd632f91e85ac168f99e2aae804599972402e3a (diff)
downloadnetwork-b0865ada5b4dffa0471f046cf8420ed34c587131.tar.zst
network-b0865ada5b4dffa0471f046cf8420ed34c587131.zip
Service target to delay service start until tailnet is ready
Signed-off-by: Mel <mel@rnrd.eu>
-rw-r--r--modules/foundation/default.nix1
-rw-r--r--modules/foundation/tailnet.nix101
-rw-r--r--modules/foundation/www/tailnet.nix11
-rw-r--r--modules/go2rtc.nix6
-rw-r--r--modules/klipper.nix5
5 files changed, 110 insertions, 14 deletions
diff --git a/modules/foundation/default.nix b/modules/foundation/default.nix
index fcf1225..fbcb2f8 100644
--- a/modules/foundation/default.nix
+++ b/modules/foundation/default.nix
@@ -3,6 +3,7 @@
 {
   imports = [
     ./services.nix
+    ./tailnet.nix
     ./monitoring
     ./www
   ];
diff --git a/modules/foundation/tailnet.nix b/modules/foundation/tailnet.nix
new file mode 100644
index 0000000..404c5ad
--- /dev/null
+++ b/modules/foundation/tailnet.nix
@@ -0,0 +1,101 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+
+let
+  inherit (lib) mkOption types;
+  inherit (pkgs) tailscale;
+
+  cfg = config.foundation;
+
+  tailnet-wait-for-ip = pkgs.writeShellScriptBin "tailnet-wait-for-ip.sh" ''
+    echo "waiting for tailscale to acquire tailnet ip address..."
+
+    while ! ${lib.getExe tailscale} ip -1; do
+      echo "tailnet ip not yet available... sleeping for 1 second."
+      sleep 1
+    done
+
+    ip=$(${lib.getExe tailscale} ip -1)
+    echo "acquired tailnet address! ip: $ip"
+    exit 0
+  '';
+in
+{
+  options.foundation = {
+    tailnetServices = mkOption {
+      type = with types; listOf str;
+
+      default = [ ];
+      example = [ "nginx" ];
+
+      description = ''
+        services that depend on the tailnet.
+        will be launched only after tailscaled.service
+        is fully up and online.
+      '';
+    };
+  };
+
+  config =
+    let
+      tailnetWaitOnlineService = {
+        enable = true;
+
+        after = [
+          "tailscaled.service"
+          "network.target"
+        ];
+        # kill service if tailscaled dies.
+        bindsTo = [ "tailscaled.service" ];
+
+        serviceConfig = {
+          # unit is marked as active after script exits.
+          Type = "oneshot";
+          RemainAfterExit = true;
+          # consider connection failed after 3 minutes.
+          TimeoutStartSec = "3m";
+
+          ExecStart = "${tailnet-wait-for-ip}/bin/tailnet-wait-for-ip.sh";
+        };
+
+        description = ''
+          wait for tailscale device to be online and ready
+        '';
+      };
+
+      tailnetOnlineTarget = {
+        enable = true;
+
+        after = [
+          "tailnet-wait-online.service"
+          "tailscaled.service"
+        ];
+        requires = [ "tailnet-wait-online.service" ];
+        bindsTo = [ "tailscaled.service" ];
+
+        description = "tailnet is online";
+      };
+
+      tailnetDependantUnit = {
+        after = [ "tailnet-online.target" ];
+        requires = [ "tailnet-online.target" ];
+      };
+
+      tailnetDependantServices = lib.genAttrs cfg.tailnetServices (x: tailnetDependantUnit);
+    in
+    {
+      systemd = {
+        services = {
+          "tailnet-wait-online" = tailnetWaitOnlineService;
+        } // tailnetDependantServices;
+
+        targets = {
+          "tailnet-online" = tailnetOnlineTarget;
+        };
+      };
+    };
+}
diff --git a/modules/foundation/www/tailnet.nix b/modules/foundation/www/tailnet.nix
index ff2410c..b361fef 100644
--- a/modules/foundation/www/tailnet.nix
+++ b/modules/foundation/www/tailnet.nix
@@ -78,13 +78,14 @@ in
 
   config =
     lib.mkIf (cfg.enable && cfg.tailnet) {
+      foundation.tailnetServices = [
+        "nginx"
+        "acme-${me.tailscale.domain}"
+      ];
+
       # overwrite default acme behaviour with tailscale
       systemd.services."acme-${me.tailscale.domain}" = {
-        after = [ "tailscaled.service" ];
-        requires = [ "tailscaled.service" ];
-        serviceConfig = {
-          ExecStart = lib.mkForce "+${tailscaleRenewScript}";
-        };
+        serviceConfig.ExecStart = lib.mkForce "+${tailscaleRenewScript}";
       };
 
       # tailnet internal vhost
diff --git a/modules/go2rtc.nix b/modules/go2rtc.nix
index e1fb881..488d679 100644
--- a/modules/go2rtc.nix
+++ b/modules/go2rtc.nix
@@ -34,9 +34,5 @@ in
     };
   };
 
-  # todo: put this into foundation option.
-  systemd.services.go2rtc = {
-    after = [ "tailscaled.service" ];
-    requires = [ "tailscaled.service" ];
-  };
+  foundation.tailnetServices = [ "go2rtc" ];
 }
diff --git a/modules/klipper.nix b/modules/klipper.nix
index ddfeb84..7f962c2 100644
--- a/modules/klipper.nix
+++ b/modules/klipper.nix
@@ -100,8 +100,5 @@ in
     nginx.clientMaxBodySize = "1000M";
   };
 
-  systemd.services.moonraker = {
-    after = [ "tailscaled.service" ];
-    requires = [ "tailscaled.service" ];
-  };
+  foundation.tailnetServices = [ "moonraker" ];
 }