summary refs log tree commit diff
path: root/modules/tailscale.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/tailscale.nix')
-rw-r--r--modules/tailscale.nix62
1 files changed, 62 insertions, 0 deletions
diff --git a/modules/tailscale.nix b/modules/tailscale.nix
new file mode 100644
index 0000000..0aaed8d
--- /dev/null
+++ b/modules/tailscale.nix
@@ -0,0 +1,62 @@
+{
+  pkgs,
+  options,
+  lib,
+  ...
+}:
+
+let
+  inherit (lib) getExe getExe' genAttrs;
+
+  # we use tailscale as the main network provider
+  # for multiple essential services.
+  # it's important that tailscale starts up prior
+  # to them.
+  vitalServices = [
+    "sshd"
+    "docker"
+    "nginx"
+  ];
+
+  # all metrics exporters are exposed through the tailnet,
+  # they also need to wait for the tailscale0 interface to be up.
+  # note that we modify all existing
+  monitoringServices = map (e: "prometheus-${e}-exporter") (
+    builtins.attrNames options.services.prometheus.exporters.value
+  );
+
+  servicesNeedingTailscale = vitalServices ++ monitoringServices;
+  serviceConfigAfterTailscale = {
+    after = [ "tailscaled.service" ];
+  };
+in
+{
+  # start tailscale :)
+  services.tailscale = {
+    enable = true;
+    useRoutingFeatures = "both";
+    extraUpFlags = [ "--ssh" ];
+  };
+  # tailscale0 is the only interface that is allowed
+  # to fully bypass the firewall.
+  networking.firewall.trustedInterfaces = [ "tailscale0" ];
+
+  systemd.services = {
+    # the tailscaled systemd service is
+    # too eager in marking itself ready,
+    # so we need to ensure it's actually
+    # up before proceeding with other units.
+    # see: https://github.com/tailscale/tailscale/issues/11504
+    "tailscaled".postStart = with pkgs; ''
+      echo "Waiting for tailscale0 to come online..."
+
+      for try in in {1..30}; do
+        if ${getExe' iproute2 "ip"} addr show dev tailscale0 | ${getExe gnugrep} -q 'inet '; then
+          echo "tailscale0 is up!"
+          break
+        fi
+        sleep 1
+      done
+    '';
+  } // genAttrs servicesNeedingTailscale (x: serviceConfigAfterTailscale);
+}