Loading nixos/modules/services/networking/tailscale.nix +36 −10 Original line number Diff line number Diff line Loading @@ -84,6 +84,8 @@ in description = '' A file containing the auth key. Tailscale will be automatically started if provided. Services that bind to Tailscale IPs should order using {option}`systemd.services.<name>.after` `tailscaled-autoconnect.service`. ''; }; Loading Loading @@ -116,7 +118,7 @@ in extraUpFlags = mkOption { description = '' Extra flags to pass to {command}`tailscale up`. Only applied if `authKeyFile` is specified."; Extra flags to pass to {command}`tailscale up`. Only applied if {option}`services.tailscale.authKeyFile` is specified. ''; type = types.listOf types.str; default = [ ]; Loading Loading @@ -183,12 +185,15 @@ in wants = [ "tailscaled.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; Type = "notify"; }; # https://github.com/tailscale/tailscale/blob/v1.72.1/ipn/backend.go#L24-L32 path = [ cfg.package pkgs.jq ]; enableStrictShellChecks = true; script = let statusCommand = "${lib.getExe cfg.package} status --json --peers=false | ${lib.getExe pkgs.jq} -r '.BackendState'"; paramToString = v: if (builtins.isBool v) then (lib.boolToString v) else (toString v); params = lib.pipe cfg.authKeyParameters [ (lib.filterAttrs (_: v: v != null)) Loading @@ -197,14 +202,35 @@ in (params: if params != "" then "?${params}" else "") ]; in # bash '' while [[ "$(${statusCommand})" == "NoState" ]]; do sleep 0.5 done status=$(${statusCommand}) if [[ "$status" == "NeedsLogin" || "$status" == "NeedsMachineAuth" ]]; then ${lib.getExe cfg.package} up --auth-key "$(cat ${cfg.authKeyFile})${params}" ${escapeShellArgs cfg.extraUpFlags} getState() { tailscale status --json --peers=false | jq -r '.BackendState' } lastState="" while state="$(getState)"; do if [[ "$state" != "$lastState" ]]; then # https://github.com/tailscale/tailscale/blob/v1.72.1/ipn/backend.go#L24-L32 case "$state" in NeedsLogin) echo "Server needs authentication, sending auth key" tailscale up --auth-key "$(cat ${cfg.authKeyFile})${params}" ${escapeShellArgs cfg.extraUpFlags} ;; Running) echo "Tailscale is running" systemd-notify --ready exit 0 ;; *) echo "Waiting for Tailscale State = Running or systemd timeout" ;; esac fi echo "State = $state" lastState="$state" sleep .5 done ''; }; Loading Loading
nixos/modules/services/networking/tailscale.nix +36 −10 Original line number Diff line number Diff line Loading @@ -84,6 +84,8 @@ in description = '' A file containing the auth key. Tailscale will be automatically started if provided. Services that bind to Tailscale IPs should order using {option}`systemd.services.<name>.after` `tailscaled-autoconnect.service`. ''; }; Loading Loading @@ -116,7 +118,7 @@ in extraUpFlags = mkOption { description = '' Extra flags to pass to {command}`tailscale up`. Only applied if `authKeyFile` is specified."; Extra flags to pass to {command}`tailscale up`. Only applied if {option}`services.tailscale.authKeyFile` is specified. ''; type = types.listOf types.str; default = [ ]; Loading Loading @@ -183,12 +185,15 @@ in wants = [ "tailscaled.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; Type = "notify"; }; # https://github.com/tailscale/tailscale/blob/v1.72.1/ipn/backend.go#L24-L32 path = [ cfg.package pkgs.jq ]; enableStrictShellChecks = true; script = let statusCommand = "${lib.getExe cfg.package} status --json --peers=false | ${lib.getExe pkgs.jq} -r '.BackendState'"; paramToString = v: if (builtins.isBool v) then (lib.boolToString v) else (toString v); params = lib.pipe cfg.authKeyParameters [ (lib.filterAttrs (_: v: v != null)) Loading @@ -197,14 +202,35 @@ in (params: if params != "" then "?${params}" else "") ]; in # bash '' while [[ "$(${statusCommand})" == "NoState" ]]; do sleep 0.5 done status=$(${statusCommand}) if [[ "$status" == "NeedsLogin" || "$status" == "NeedsMachineAuth" ]]; then ${lib.getExe cfg.package} up --auth-key "$(cat ${cfg.authKeyFile})${params}" ${escapeShellArgs cfg.extraUpFlags} getState() { tailscale status --json --peers=false | jq -r '.BackendState' } lastState="" while state="$(getState)"; do if [[ "$state" != "$lastState" ]]; then # https://github.com/tailscale/tailscale/blob/v1.72.1/ipn/backend.go#L24-L32 case "$state" in NeedsLogin) echo "Server needs authentication, sending auth key" tailscale up --auth-key "$(cat ${cfg.authKeyFile})${params}" ${escapeShellArgs cfg.extraUpFlags} ;; Running) echo "Tailscale is running" systemd-notify --ready exit 0 ;; *) echo "Waiting for Tailscale State = Running or systemd timeout" ;; esac fi echo "State = $state" lastState="$state" sleep .5 done ''; }; Loading