From e475d18b5775aceadce6b924496b2338ce342855 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:01:53 +0900 Subject: [PATCH 01/14] Add Tailscale service configuration in services directory --- nix-darwin/services/tailscale.nix | 89 +++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 nix-darwin/services/tailscale.nix diff --git a/nix-darwin/services/tailscale.nix b/nix-darwin/services/tailscale.nix new file mode 100644 index 000000000..713eba2c0 --- /dev/null +++ b/nix-darwin/services/tailscale.nix @@ -0,0 +1,89 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.services.tailscale; +in +{ + options.services.tailscale = { + enable = mkEnableOption "Tailscale VPN service"; + + acceptRoutes = mkOption { + type = types.bool; + default = false; + description = "Whether to accept advertised routes from the Tailscale network."; + }; + + advertiseExitNode = mkOption { + type = types.bool; + default = false; + description = "Whether to advertise this node as an exit node."; + }; + + useExitNode = mkOption { + type = types.str; + default = ""; + description = "Exit node to use (leave empty to not use any exit node)."; + }; + + extraUpArgs = mkOption { + type = types.listOf types.str; + default = []; + description = "Extra arguments to pass to tailscale up."; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.tailscale ]; + + # Create directory for Tailscale state + system.activationScripts.postActivation.text = '' + mkdir -p /var/lib/tailscale + chmod 755 /var/lib/tailscale + ''; + + # System-level launchd service for tailscaled + launchd.daemons.tailscaled = { + script = '' + ${pkgs.tailscale}/bin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/var/run/tailscale/tailscaled.sock + ''; + serviceConfig = { + KeepAlive = true; + RunAtLoad = true; + StandardOutPath = "/var/log/tailscaled.log"; + StandardErrorPath = "/var/log/tailscaled.error.log"; + UserName = "root"; + GroupName = "wheel"; + WorkingDirectory = "/var/lib/tailscale"; + }; + }; + + # User-level launchd service for tailscale up + launchd.agents.tailscale-up = { + enable = true; + script = '' + # Wait for tailscaled to be ready + for i in {1..30}; do + if ${pkgs.tailscale}/bin/tailscale status >/dev/null 2>&1; then + break + fi + sleep 1 + done + + # Configure Tailscale with specified options + ${pkgs.tailscale}/bin/tailscale up \ + ${optionalString cfg.acceptRoutes "--accept-routes"} \ + ${optionalString cfg.advertiseExitNode "--advertise-exit-node"} \ + ${optionalString (cfg.useExitNode != "") "--exit-node=${cfg.useExitNode}"} \ + ${concatStringsSep " " cfg.extraUpArgs} + ''; + serviceConfig = { + RunAtLoad = true; + KeepAlive = { + SuccessfulExit = false; + }; + StandardOutPath = "/tmp/tailscale-up.log"; + StandardErrorPath = "/tmp/tailscale-up.error.log"; + }; + }; + }; +} \ No newline at end of file From a3b001565efe5243623ab7a35eda5cd0c8ccc5fc Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:02:29 +0900 Subject: [PATCH 02/14] Add Tailscale service configuration for home-manager --- home-manager/services/tailscale/default.nix | 83 +++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 home-manager/services/tailscale/default.nix diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix new file mode 100644 index 000000000..b5d292caa --- /dev/null +++ b/home-manager/services/tailscale/default.nix @@ -0,0 +1,83 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.services.tailscale; +in +{ + options.services.tailscale = { + enable = mkEnableOption "Tailscale VPN service"; + + acceptRoutes = mkOption { + type = types.bool; + default = false; + description = "Whether to accept advertised routes from the Tailscale network."; + }; + + advertiseExitNode = mkOption { + type = types.bool; + default = false; + description = "Whether to advertise this node as an exit node."; + }; + + useExitNode = mkOption { + type = types.str; + default = ""; + description = "Exit node to use (leave empty to not use any exit node)."; + }; + + extraUpArgs = mkOption { + type = types.listOf types.str; + default = []; + description = "Extra arguments to pass to tailscale up."; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.tailscale ]; + + # Create directory for Tailscale state + home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' + mkdir -p $HOME/.local/share/tailscale + chmod 755 $HOME/.local/share/tailscale + ''; + + # User-level systemd service for tailscaled + systemd.user.services.tailscaled = { + Unit = { + Description = "Tailscale client daemon"; + After = [ "network.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Service = { + ExecStart = "${pkgs.tailscale}/bin/tailscaled --state=${config.xdg.dataHome}/tailscale/tailscaled.state --socket=${config.xdg.runtimeDir}/tailscale/tailscaled.sock"; + Restart = "on-failure"; + RestartSec = 5; + }; + + Install = { + WantedBy = [ "default.target" ]; + }; + }; + + # User-level systemd service for tailscale up + systemd.user.services.tailscale-up = { + Unit = { + Description = "Configure Tailscale connection"; + After = [ "tailscaled.service" ]; + PartOf = [ "tailscaled.service" ]; + }; + + Service = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up ${optionalString cfg.acceptRoutes "--accept-routes"} ${optionalString cfg.advertiseExitNode "--advertise-exit-node"} ${optionalString (cfg.useExitNode != "") "--exit-node=${cfg.useExitNode}"} ${concatStringsSep " " cfg.extraUpArgs}'"; + ExecStop = "${pkgs.tailscale}/bin/tailscale down"; + }; + + Install = { + WantedBy = [ "default.target" ]; + }; + }; + }; +} \ No newline at end of file From 1a276cdb65da04dbbb3a1af3df77417debe5825a Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:04:20 +0900 Subject: [PATCH 03/14] Enable Tailscale by default in home-manager --- home-manager/default.nix | 9 ++++ nix-darwin/services/tailscale.nix | 89 ------------------------------- 2 files changed, 9 insertions(+), 89 deletions(-) delete mode 100644 nix-darwin/services/tailscale.nix diff --git a/home-manager/default.nix b/home-manager/default.nix index d321a8bc6..395aa354c 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -45,4 +45,13 @@ in address = "shunkakinoki@gmail.com"; }; }; + + # Enable Tailscale by default with basic connectivity + services.tailscale = { + enable = true; + acceptRoutes = false; + advertiseExitNode = false; + useExitNode = ""; + extraUpArgs = []; + }; } diff --git a/nix-darwin/services/tailscale.nix b/nix-darwin/services/tailscale.nix deleted file mode 100644 index 713eba2c0..000000000 --- a/nix-darwin/services/tailscale.nix +++ /dev/null @@ -1,89 +0,0 @@ -{ config, pkgs, lib, ... }: -with lib; -let - cfg = config.services.tailscale; -in -{ - options.services.tailscale = { - enable = mkEnableOption "Tailscale VPN service"; - - acceptRoutes = mkOption { - type = types.bool; - default = false; - description = "Whether to accept advertised routes from the Tailscale network."; - }; - - advertiseExitNode = mkOption { - type = types.bool; - default = false; - description = "Whether to advertise this node as an exit node."; - }; - - useExitNode = mkOption { - type = types.str; - default = ""; - description = "Exit node to use (leave empty to not use any exit node)."; - }; - - extraUpArgs = mkOption { - type = types.listOf types.str; - default = []; - description = "Extra arguments to pass to tailscale up."; - }; - }; - - config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.tailscale ]; - - # Create directory for Tailscale state - system.activationScripts.postActivation.text = '' - mkdir -p /var/lib/tailscale - chmod 755 /var/lib/tailscale - ''; - - # System-level launchd service for tailscaled - launchd.daemons.tailscaled = { - script = '' - ${pkgs.tailscale}/bin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/var/run/tailscale/tailscaled.sock - ''; - serviceConfig = { - KeepAlive = true; - RunAtLoad = true; - StandardOutPath = "/var/log/tailscaled.log"; - StandardErrorPath = "/var/log/tailscaled.error.log"; - UserName = "root"; - GroupName = "wheel"; - WorkingDirectory = "/var/lib/tailscale"; - }; - }; - - # User-level launchd service for tailscale up - launchd.agents.tailscale-up = { - enable = true; - script = '' - # Wait for tailscaled to be ready - for i in {1..30}; do - if ${pkgs.tailscale}/bin/tailscale status >/dev/null 2>&1; then - break - fi - sleep 1 - done - - # Configure Tailscale with specified options - ${pkgs.tailscale}/bin/tailscale up \ - ${optionalString cfg.acceptRoutes "--accept-routes"} \ - ${optionalString cfg.advertiseExitNode "--advertise-exit-node"} \ - ${optionalString (cfg.useExitNode != "") "--exit-node=${cfg.useExitNode}"} \ - ${concatStringsSep " " cfg.extraUpArgs} - ''; - serviceConfig = { - RunAtLoad = true; - KeepAlive = { - SuccessfulExit = false; - }; - StandardOutPath = "/tmp/tailscale-up.log"; - StandardErrorPath = "/tmp/tailscale-up.error.log"; - }; - }; - }; -} \ No newline at end of file From 1753f8df63801297e0782b16a468688a0b7d4475 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:05:01 +0900 Subject: [PATCH 04/14] Add Tailscale service import to home-manager services --- home-manager/services/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/home-manager/services/default.nix b/home-manager/services/default.nix index 2a6a32fc7..cd7dd26a3 100644 --- a/home-manager/services/default.nix +++ b/home-manager/services/default.nix @@ -5,6 +5,7 @@ let neversslKeepalive = import ./neverssl-keepalive { inherit pkgs; }; ollama = import ./ollama { inherit pkgs; }; brewUpgrader = import ./brew-upgrader { inherit pkgs; }; + tailscale = import ./tailscale/default.nix; in [ brewUpgrader @@ -12,4 +13,5 @@ in dotfilesUpdater neversslKeepalive ollama + tailscale ] From 7f384a730743e3cf630c535932d3f2d761fc97f4 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:09:49 +0900 Subject: [PATCH 05/14] fix: update Tailscale import path in default.nix --- home-manager/services/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/home-manager/services/default.nix b/home-manager/services/default.nix index cd7dd26a3..9cda5c4bf 100644 --- a/home-manager/services/default.nix +++ b/home-manager/services/default.nix @@ -5,7 +5,7 @@ let neversslKeepalive = import ./neverssl-keepalive { inherit pkgs; }; ollama = import ./ollama { inherit pkgs; }; brewUpgrader = import ./brew-upgrader { inherit pkgs; }; - tailscale = import ./tailscale/default.nix; + tailscale = import ./tailscale; in [ brewUpgrader From d248e084c46e786b23741bf83f896d5ad2495cdf Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:18:12 +0900 Subject: [PATCH 06/14] Simplify Tailscale configuration - remove options and hardcode basic settings --- home-manager/default.nix | 9 -- home-manager/services/tailscale/default.nix | 101 +++++++------------- 2 files changed, 34 insertions(+), 76 deletions(-) diff --git a/home-manager/default.nix b/home-manager/default.nix index 395aa354c..d321a8bc6 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -45,13 +45,4 @@ in address = "shunkakinoki@gmail.com"; }; }; - - # Enable Tailscale by default with basic connectivity - services.tailscale = { - enable = true; - acceptRoutes = false; - advertiseExitNode = false; - useExitNode = ""; - extraUpArgs = []; - }; } diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix index b5d292caa..69460e0b8 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/services/tailscale/default.nix @@ -1,83 +1,50 @@ { config, pkgs, lib, ... }: with lib; -let - cfg = config.services.tailscale; -in { - options.services.tailscale = { - enable = mkEnableOption "Tailscale VPN service"; - - acceptRoutes = mkOption { - type = types.bool; - default = false; - description = "Whether to accept advertised routes from the Tailscale network."; - }; - - advertiseExitNode = mkOption { - type = types.bool; - default = false; - description = "Whether to advertise this node as an exit node."; + home.packages = [ pkgs.tailscale ]; + + # Create directory for Tailscale state + home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' + mkdir -p $HOME/.local/share/tailscale + chmod 755 $HOME/.local/share/tailscale + ''; + + # User-level systemd service for tailscaled + systemd.user.services.tailscaled = { + Unit = { + Description = "Tailscale client daemon"; + After = [ "network.target" ]; + PartOf = [ "graphical-session.target" ]; }; - useExitNode = mkOption { - type = types.str; - default = ""; - description = "Exit node to use (leave empty to not use any exit node)."; + Service = { + ExecStart = "${pkgs.tailscale}/bin/tailscaled --state=${config.xdg.dataHome}/tailscale/tailscaled.state --socket=${config.xdg.runtimeDir}/tailscale/tailscaled.sock"; + Restart = "on-failure"; + RestartSec = 5; }; - extraUpArgs = mkOption { - type = types.listOf types.str; - default = []; - description = "Extra arguments to pass to tailscale up."; + Install = { + WantedBy = [ "default.target" ]; }; }; - config = mkIf cfg.enable { - home.packages = [ pkgs.tailscale ]; - - # Create directory for Tailscale state - home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' - mkdir -p $HOME/.local/share/tailscale - chmod 755 $HOME/.local/share/tailscale - ''; - - # User-level systemd service for tailscaled - systemd.user.services.tailscaled = { - Unit = { - Description = "Tailscale client daemon"; - After = [ "network.target" ]; - PartOf = [ "graphical-session.target" ]; - }; - - Service = { - ExecStart = "${pkgs.tailscale}/bin/tailscaled --state=${config.xdg.dataHome}/tailscale/tailscaled.state --socket=${config.xdg.runtimeDir}/tailscale/tailscaled.sock"; - Restart = "on-failure"; - RestartSec = 5; - }; - - Install = { - WantedBy = [ "default.target" ]; - }; + # User-level systemd service for tailscale up + systemd.user.services.tailscale-up = { + Unit = { + Description = "Configure Tailscale connection"; + After = [ "tailscaled.service" ]; + PartOf = [ "tailscaled.service" ]; }; - # User-level systemd service for tailscale up - systemd.user.services.tailscale-up = { - Unit = { - Description = "Configure Tailscale connection"; - After = [ "tailscaled.service" ]; - PartOf = [ "tailscaled.service" ]; - }; - - Service = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up ${optionalString cfg.acceptRoutes "--accept-routes"} ${optionalString cfg.advertiseExitNode "--advertise-exit-node"} ${optionalString (cfg.useExitNode != "") "--exit-node=${cfg.useExitNode}"} ${concatStringsSep " " cfg.extraUpArgs}'"; - ExecStop = "${pkgs.tailscale}/bin/tailscale down"; - }; + Service = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up'"; + ExecStop = "${pkgs.tailscale}/bin/tailscale down"; + }; - Install = { - WantedBy = [ "default.target" ]; - }; + Install = { + WantedBy = [ "default.target" ]; }; }; } \ No newline at end of file From 285cf2849a3fc210f26f96e9271a207b24123167 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:20:08 +0900 Subject: [PATCH 07/14] Remove Tailscale package from home.packages --- home-manager/services/tailscale/default.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix index 69460e0b8..ab60e5dc9 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/services/tailscale/default.nix @@ -1,8 +1,6 @@ { config, pkgs, lib, ... }: with lib; { - home.packages = [ pkgs.tailscale ]; - # Create directory for Tailscale state home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' mkdir -p $HOME/.local/share/tailscale From 29e4ab26464e39848e6d113377404374ae124d0f Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:23:27 +0900 Subject: [PATCH 08/14] Add platform-specific Tailscale services - launchd for macOS, systemd for Linux --- home-manager/services/tailscale/default.nix | 53 ++++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix index ab60e5dc9..ffacd4e77 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/services/tailscale/default.nix @@ -1,13 +1,62 @@ { config, pkgs, lib, ... }: with lib; { + home.packages = [ pkgs.tailscale ]; + # Create directory for Tailscale state home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' mkdir -p $HOME/.local/share/tailscale chmod 755 $HOME/.local/share/tailscale ''; +} +// lib.mkIf pkgs.stdenv.isDarwin { + # macOS launchd service for tailscaled + launchd.agents.tailscaled = { + enable = true; + config = { + ProgramArguments = [ + "${pkgs.tailscale}/bin/tailscaled" + "--state=$HOME/.local/share/tailscale/tailscaled.state" + "--socket=$HOME/.local/share/tailscale/tailscaled.sock" + ]; + KeepAlive = true; + RunAtLoad = true; + StandardOutPath = "$HOME/.local/share/tailscale/tailscaled.log"; + StandardErrorPath = "$HOME/.local/share/tailscale/tailscaled.error.log"; + }; + }; - # User-level systemd service for tailscaled + # macOS launchd service for tailscale up + launchd.agents.tailscale-up = { + enable = true; + config = { + ProgramArguments = [ + "${pkgs.bash}/bin/bash" + "-c" + '' + # Wait for tailscaled to be ready + for i in {1..30}; do + if ${pkgs.tailscale}/bin/tailscale status >/dev/null 2>&1; then + break + fi + sleep 1 + done + + # Configure Tailscale with basic connectivity + ${pkgs.tailscale}/bin/tailscale up + '' + ]; + RunAtLoad = true; + KeepAlive = { + SuccessfulExit = false; + }; + StandardOutPath = "$HOME/.local/share/tailscale/tailscale-up.log"; + StandardErrorPath = "$HOME/.local/share/tailscale/tailscale-up.error.log"; + }; + }; +} +// lib.mkIf pkgs.stdenv.isLinux { + # Linux systemd service for tailscaled systemd.user.services.tailscaled = { Unit = { Description = "Tailscale client daemon"; @@ -26,7 +75,7 @@ with lib; }; }; - # User-level systemd service for tailscale up + # Linux systemd service for tailscale up systemd.user.services.tailscale-up = { Unit = { Description = "Configure Tailscale connection"; From 6e14e4aa825f564f2a1de23ac9856551a3aaecc8 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:30:47 +0900 Subject: [PATCH 09/14] fix: remove duplicate Tailscale entry from package list --- home-manager/packages/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/home-manager/packages/default.nix b/home-manager/packages/default.nix index 50ad2aa87..00e23cc04 100644 --- a/home-manager/packages/default.nix +++ b/home-manager/packages/default.nix @@ -64,6 +64,7 @@ with pkgs; speedtest-cli sqlite stern + tailscale tokei tree turso-cli @@ -87,7 +88,6 @@ with pkgs; gemini-cli opencode powertop - tailscale ] ++ lib.optionals (stdenv.isLinux && !isCI) [ chromium From 5cfa41f745fa6d225cde7f3918d1707efb26e2d1 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:31:01 +0900 Subject: [PATCH 10/14] fix: remove Tailscale package from home.packages --- home-manager/services/tailscale/default.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix index ffacd4e77..bce7690ba 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/services/tailscale/default.nix @@ -1,9 +1,6 @@ { config, pkgs, lib, ... }: with lib; { - home.packages = [ pkgs.tailscale ]; - - # Create directory for Tailscale state home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' mkdir -p $HOME/.local/share/tailscale chmod 755 $HOME/.local/share/tailscale From 474719824182d07594cdb6a3375dd707b00c9faa Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:31:16 +0900 Subject: [PATCH 11/14] fix: clean up formatting and whitespace in Tailscale service configuration --- home-manager/services/tailscale/default.nix | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix index bce7690ba..7438685be 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/services/tailscale/default.nix @@ -1,7 +1,12 @@ -{ config, pkgs, lib, ... }: +{ + config, + pkgs, + lib, + ... +}: with lib; { - home.activation.tailscaleStateDir = lib.hm.dag.entryAfter ["writeBoundary"] '' + home.activation.tailscaleStateDir = lib.hm.dag.entryAfter [ "writeBoundary" ] '' mkdir -p $HOME/.local/share/tailscale chmod 755 $HOME/.local/share/tailscale ''; @@ -38,7 +43,7 @@ with lib; fi sleep 1 done - + # Configure Tailscale with basic connectivity ${pkgs.tailscale}/bin/tailscale up '' @@ -91,4 +96,4 @@ with lib; WantedBy = [ "default.target" ]; }; }; -} \ No newline at end of file +} From 4c5dc7797df5628a46d25f8850458fea807ca392 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:39:33 +0900 Subject: [PATCH 12/14] Explicitly configure Tailscale with exit node and routes disabled --- home-manager/services/tailscale/default.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/home-manager/services/tailscale/default.nix b/home-manager/services/tailscale/default.nix index 7438685be..4302d3bf2 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/services/tailscale/default.nix @@ -44,8 +44,8 @@ with lib; sleep 1 done - # Configure Tailscale with basic connectivity - ${pkgs.tailscale}/bin/tailscale up + # Configure Tailscale with explicit settings + ${pkgs.tailscale}/bin/tailscale up --accept-routes=false --advertise-exit-node=false '' ]; RunAtLoad = true; @@ -88,7 +88,7 @@ with lib; Service = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up'"; + ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up --accept-routes=false --advertise-exit-node=false'"; ExecStop = "${pkgs.tailscale}/bin/tailscale down"; }; From 87911ced4b94e0b5c4a1cb3fecfb6cc277eb00df Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 19:56:25 +0900 Subject: [PATCH 13/14] feat: add Tailscale service configuration and integration --- home-manager/modules/default.nix | 1 + .../tailscale/default.nix | 69 +++++++++++++++---- home-manager/services/default.nix | 2 - 3 files changed, 55 insertions(+), 17 deletions(-) rename home-manager/{services => modules}/tailscale/default.nix (50%) diff --git a/home-manager/modules/default.nix b/home-manager/modules/default.nix index 256b443a4..a84211003 100644 --- a/home-manager/modules/default.nix +++ b/home-manager/modules/default.nix @@ -1,4 +1,5 @@ [ ./npm-globals + ./tailscale ./yek ] diff --git a/home-manager/services/tailscale/default.nix b/home-manager/modules/tailscale/default.nix similarity index 50% rename from home-manager/services/tailscale/default.nix rename to home-manager/modules/tailscale/default.nix index 4302d3bf2..e458ef18c 100644 --- a/home-manager/services/tailscale/default.nix +++ b/home-manager/modules/tailscale/default.nix @@ -1,17 +1,48 @@ -{ - config, - pkgs, - lib, - ... -}: +{ config, pkgs, lib, ... }: with lib; +let + cfg = config.services.tailscale; +in { - home.activation.tailscaleStateDir = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - mkdir -p $HOME/.local/share/tailscale - chmod 755 $HOME/.local/share/tailscale - ''; + options.services.tailscale = { + enable = mkEnableOption "Tailscale VPN service"; + + acceptRoutes = mkOption { + type = types.bool; + default = false; + description = "Whether to accept advertised routes from the Tailscale network."; + }; + + advertiseExitNode = mkOption { + type = types.bool; + default = false; + description = "Whether to advertise this node as an exit node."; + }; + + useExitNode = mkOption { + type = types.str; + default = ""; + description = "Exit node to use (leave empty to not use any exit node)."; + }; + + extraUpArgs = mkOption { + type = types.listOf types.str; + default = []; + description = "Extra arguments to pass to tailscale up."; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ pkgs.tailscale ]; + + # Create directory for Tailscale state + home.activation.tailscaleStateDir = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + mkdir -p $HOME/.local/share/tailscale + chmod 755 $HOME/.local/share/tailscale + ''; + }; } -// lib.mkIf pkgs.stdenv.isDarwin { +// lib.mkIf (pkgs.stdenv.isDarwin && config.services.tailscale.enable) { # macOS launchd service for tailscaled launchd.agents.tailscaled = { enable = true; @@ -44,8 +75,12 @@ with lib; sleep 1 done - # Configure Tailscale with explicit settings - ${pkgs.tailscale}/bin/tailscale up --accept-routes=false --advertise-exit-node=false + # Configure Tailscale with specified options + ${pkgs.tailscale}/bin/tailscale up \ + ${optionalString config.services.tailscale.acceptRoutes "--accept-routes"} \ + ${optionalString config.services.tailscale.advertiseExitNode "--advertise-exit-node"} \ + ${optionalString (config.services.tailscale.useExitNode != "") "--exit-node=${config.services.tailscale.useExitNode}"} \ + ${concatStringsSep " " config.services.tailscale.extraUpArgs} '' ]; RunAtLoad = true; @@ -57,7 +92,7 @@ with lib; }; }; } -// lib.mkIf pkgs.stdenv.isLinux { +// lib.mkIf (pkgs.stdenv.isLinux && config.services.tailscale.enable) { # Linux systemd service for tailscaled systemd.user.services.tailscaled = { Unit = { @@ -88,7 +123,11 @@ with lib; Service = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up --accept-routes=false --advertise-exit-node=false'"; + ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up \ + ${optionalString config.services.tailscale.acceptRoutes "--accept-routes"} \ + ${optionalString config.services.tailscale.advertiseExitNode "--advertise-exit-node"} \ + ${optionalString (config.services.tailscale.useExitNode != "") "--exit-node=${config.services.tailscale.useExitNode}"} \ + ${concatStringsSep " " config.services.tailscale.extraUpArgs}'"; ExecStop = "${pkgs.tailscale}/bin/tailscale down"; }; diff --git a/home-manager/services/default.nix b/home-manager/services/default.nix index 9cda5c4bf..2a6a32fc7 100644 --- a/home-manager/services/default.nix +++ b/home-manager/services/default.nix @@ -5,7 +5,6 @@ let neversslKeepalive = import ./neverssl-keepalive { inherit pkgs; }; ollama = import ./ollama { inherit pkgs; }; brewUpgrader = import ./brew-upgrader { inherit pkgs; }; - tailscale = import ./tailscale; in [ brewUpgrader @@ -13,5 +12,4 @@ in dotfilesUpdater neversslKeepalive ollama - tailscale ] From 1d9d669b9a89c9331740b667848ae11518cff3d7 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Sat, 29 Nov 2025 20:27:14 +0900 Subject: [PATCH 14/14] feat: enhance Tailscale configuration with auth key support and documentation --- Makefile | 1 + docs/TAILSCALE.md | 368 ++++++++++++++++++ home-manager/modules/tailscale/default.nix | 236 ++++++----- named-hosts/galactica/default.nix | 13 + named-hosts/galactica/keys/tailscale-auth.age | 9 + named-hosts/galactica/secrets.nix | 6 + 6 files changed, 535 insertions(+), 98 deletions(-) create mode 100644 docs/TAILSCALE.md create mode 100644 named-hosts/galactica/keys/tailscale-auth.age diff --git a/Makefile b/Makefile index fec2cc1e8..aad3d13c9 100644 --- a/Makefile +++ b/Makefile @@ -122,6 +122,7 @@ check: ## Run all validation checks (nix, format, lua). @$(MAKE) lua-check @echo "✅ All checks passed" + .PHONY: flake-check flake-check: nix-flake-check ## Check Nix flake configuration (alias for nix-flake-check). diff --git a/docs/TAILSCALE.md b/docs/TAILSCALE.md new file mode 100644 index 000000000..315160a4d --- /dev/null +++ b/docs/TAILSCALE.md @@ -0,0 +1,368 @@ +# Tailscale Setup and Usage Guide + +This guide covers the setup, configuration, and usage of Tailscale VPN in this dotfiles repository. + +## Overview + +Tailscale is configured as a home-manager module that provides secure, private networking between your devices. The setup includes: + +- Automatic service management via launchd (macOS) or systemd (Linux) +- Secure authentication key management using agenix +- Personal device connectivity configuration +- Network monitoring and management tools + +## Prerequisites + +- Tailscale account (free tier is sufficient for personal use) +- Admin access to your machine for service installation +- SSH key pair configured for agenix secrets management + +## Initial Setup + +### 1. Create a Tailscale Account + +If you don't have a Tailscale account: + +1. Visit [https://login.tailscale.com/start](https://login.tailscale.com/start) +2. Sign up with your preferred authentication method (Google, GitHub, Microsoft, etc.) +3. Complete the account setup process + +### 2. Generate an Auth Key + +1. Log in to the [Tailscale Admin Console](https://login.tailscale.com/admin) +2. Navigate to **Settings** → **Keys** in the left sidebar +3. Click **Generate auth key** +4. Configure the key settings: + - **Description**: `galactica-macbook` (or your device name) + - **Expiry**: `90 days` (recommended for personal use) + - **Ephemeral**: `No` (for persistent device) + - **Pre-approved**: `Yes` (for automatic connection) + - **Tags**: Leave empty for personal use +5. Click **Generate key** +6. **Important**: Copy the auth key immediately as it won't be shown again + +### 3. Encrypt the Auth Key + +Save your auth key to a temporary file and encrypt it: + +```bash +# Save auth key to temporary file +echo "tskey-auth-xxxxxxxxxxxxxxxxxxxxxxxx" > /tmp/tailscale-auth.txt + +# Encrypt the key for your host +make encrypt-key-galactica KEY_FILE=/tmp/tailscale-auth.txt + +# Clean up the temporary file +rm /tmp/tailscale-auth.txt +``` + +## Configuration + +### Module Options + +The Tailscale module supports the following configuration options: + +```nix +services.tailscale = { + enable = true; # Enable Tailscale service + acceptRoutes = false; # Accept advertised routes (default: false) + advertiseExitNode = false; # Advertise as exit node (default: false) + useExitNode = ""; # Exit node to use (default: none) + authKey = ""; # Auth key as string (alternative to authKeyFile) + authKeyFile = ""; # Path to auth key file (recommended) + extraUpArgs = [ # Additional arguments for tailscale up + "--reset" + "--accept-dns=false" + ]; +}; +``` + +### Current Configuration + +The galactica host is configured for personal device connectivity: + +- **Authentication**: Uses encrypted auth key stored in agenix +- **Routes**: Does not accept or advertise routes +- **Exit Node**: Not configured as or using exit nodes +- **DNS**: Maintains local DNS settings +- **State**: Clean state on each restart + +## Deployment + +### Apply Configuration + +```bash +# Build and switch to the new configuration +make switch-galactica + +# Or for auto-detected host +make switch +``` + +### Verify Installation + +```bash +# Check Tailscale status +tailscale status + +# Check service status (macOS) +launchctl list | grep tailscale + +# Check service status (Linux) +systemctl --user status tailscaled +``` + +## Usage + +### Basic Commands + +```bash +# Show connection status +tailscale status + +# Show IP addresses +tailscale ip -4 +tailscale ip -6 + +# List all devices in your network +tailscale status --self=false + +# Ping another device +tailscale ping device-name + +# Open Tailscale admin console +tailscale browse +``` + +### Network Access + +Once connected, you can access other devices using: + +- **Magic DNS**: `device-name.tailnet-name.ts.net` +- **Direct IP**: Use the IP shown in `tailscale status` + +Example: +```bash +# Access another device via Magic DNS +ssh user@device-name.tailnet-name.ts.net + +# Access via direct IP +ssh user@100.x.x.x +``` + +## Management + +### Service Management + +```bash +# Restart Tailscale service (macOS) +launchctl kickstart -k homebrew.mxcl.tailscaled + +# Restart Tailscale service (Linux) +systemctl --user restart tailscaled + +# Disconnect from Tailscale +tailscale down + +# Reconnect to Tailscale +tailscale up +``` + +### Log Files + +Log files are stored in `~/.local/share/tailscale/`: + +- `tailscaled.log` - Main daemon logs +- `tailscaled.error.log` - Error logs +- `tailscale-up.log` - Connection logs +- `tailscale-up.error.log` - Connection error logs + +## Troubleshooting + +### Common Issues + +#### 1. Authentication Fails + +**Symptoms**: Service starts but shows "Not connected" in status + +**Solutions**: +```bash +# Check if auth key is properly decrypted +ls -la /run/agenix/keys/tailscale-auth.age + +# Manually authenticate +tailscale up --authkey=your-auth-key + +# Check service logs +tail -f ~/.local/share/tailscale/tailscale-up.error.log +``` + +#### 2. Service Won't Start + +**Symptoms**: Service fails to start or crashes immediately + +**Solutions**: +```bash +# Check permissions on state directory +ls -la ~/.local/share/tailscale/ + +# Reset Tailscale state +rm -rf ~/.local/share/tailscale/tailscaled.state +make switch-galactica + +# Check system logs (macOS) +log show --predicate 'process == "tailscaled"' --last 1h +``` + +#### 3. Network Connectivity Issues + +**Symptoms**: Can't reach other devices or internet + +**Solutions**: +```bash +# Check network status +tailscale netcheck + +# Test connectivity to Tailscale servers +tailscale ping 100.100.100.100 + +# Reset network configuration +tailscale down +tailscale up --reset +``` + +### Debug Mode + +Enable debug logging for troubleshooting: + +```bash +# Stop the service +launchctl stop homebrew.mxcl.tailscaled + +# Start manually with debug flags +tailscaled --debug --state=~/.local/share/tailscale/tailscaled.state +``` + +## Security Best Practices + +### Auth Key Management + +1. **Use non-ephemeral keys** for persistent devices +2. **Set reasonable expiry** (30-90 days for personal use) +3. **Rotate keys regularly** using the admin console +4. **Store keys securely** using agenix encryption + +### Network Security + +1. **Disable exit nodes** unless specifically needed +2. **Use ACLs** for access control in larger networks +3. **Monitor connections** regularly via admin console +4. **Keep software updated** with `make update` + +### Privacy + +1. **Magic DNS** is enabled by default for convenience +2. **Local DNS settings** are preserved (`--accept-dns=false`) +3. **No route acceptance** prevents unwanted network exposure + +## Advanced Configuration + +### Custom Tags and ACLs + +For more complex setups, you can configure tags and ACLs: + +```nix +services.tailscale = { + enable = true; + authKeyFile = config.age.secrets."keys/tailscale-auth.age".path; + extraUpArgs = [ + "--reset" + "--accept-dns=false" + "--tag=tag:server" + ]; +}; +``` + +### Exit Node Usage + +To use an exit node (when needed): + +```nix +services.tailscale = { + enable = true; + useExitNode = "exit-node-name"; + # ... other options +}; +``` + +### Multiple Networks + +For users with multiple Tailscale networks: + +```nix +services.tailscale = { + enable = true; + authKeyFile = config.age.secrets."keys/tailscale-auth.age".path; + extraUpArgs = [ + "--reset" + "--accept-dns=false" + "--login-server=https://login.tailscale.com" + ]; +}; +``` + +## Integration with Other Services + +### SSH Configuration + +Tailscale works seamlessly with SSH. Consider adding to your SSH config: + +```sshconfig +Host *.ts.net + User your-username + IdentityFile ~/.ssh/id_ed25519 + StrictHostKeyChecking no + UserKnownHostsFile ~/.ssh/known_hosts.tailscale +``` + +### Development Tools + +Many development tools work transparently with Tailscale: + +- **Docker**: Containers can access Tailscale network +- **VS Code**: Remote SSH via Tailscale addresses +- **Git**: Access private repositories over Tailscale + +## Maintenance + +### Regular Tasks + +1. **Monthly**: Check auth key expiry and rotate if needed +2. **Quarterly**: Review connected devices in admin console +3. **As needed**: Update configuration with `make switch-galactica` + +### Updates + +```bash +# Update entire dotfiles (includes Tailscale updates) +make update + +# Update only Tailscale package +nix flake update +make switch-galactica +``` + +## Support + +- **Tailscale Documentation**: [https://tailscale.com/kb/](https://tailscale.com/kb/) +- **Tailscale Support**: [https://support.tailscale.com/](https://support.tailscale.com/) +- **Community**: [https://github.com/tailscale/tailscale/discussions](https://github.com/tailscale/tailscale/discussions) + +## File Locations + +- **Module**: `home-manager/modules/tailscale/default.nix` +- **Configuration**: `named-hosts/galactica/default.nix` +- **Secrets**: `named-hosts/galactica/secrets.nix` +- **Auth Key**: `named-hosts/galactica/keys/tailscale-auth.age` (encrypted) +- **State**: `~/.local/share/tailscale/` +- **Logs**: `~/.local/share/tailscale/*.log` \ No newline at end of file diff --git a/home-manager/modules/tailscale/default.nix b/home-manager/modules/tailscale/default.nix index e458ef18c..3ea4d9bfc 100644 --- a/home-manager/modules/tailscale/default.nix +++ b/home-manager/modules/tailscale/default.nix @@ -1,138 +1,178 @@ -{ config, pkgs, lib, ... }: +# Tailscale configuration +{ + config, + lib, + pkgs, + ... +}: with lib; let - cfg = config.services.tailscale; + cfg = config.modules.tailscale; + + # Check if configuration is enabled + configEnabled = (cfg.serviceConfig != { } && cfg.serviceConfig != null); in { - options.services.tailscale = { + options.modules.tailscale = { enable = mkEnableOption "Tailscale VPN service"; + # Tailscale daemon configuration + tailscaled = { + package = mkOption { + type = types.package; + default = pkgs.tailscale; + description = "Tailscale package to use"; + }; + + stateDir = mkOption { + type = types.str; + default = "${config.xdg.dataHome}/tailscale"; + description = "Directory for Tailscale state files"; + }; + + socketPath = mkOption { + type = types.str; + default = "${config.xdg.runtimeDir}/tailscale/tailscaled.sock"; + description = "Socket path for Tailscale daemon"; + }; + }; + + # Optional auth key + authKey = mkOption { + type = types.str; + default = ""; + description = "Tailscale auth key (use agenix for secrets)"; + }; + + # Optional auth key file (better for secrets) + authKeyFile = mkOption { + type = types.path; + default = ""; + description = "Path to file containing Tailscale auth key (better for secrets)"; + }; + + # Tailscale up options acceptRoutes = mkOption { type = types.bool; default = false; - description = "Whether to accept advertised routes from the Tailscale network."; + description = "Accept routes from other nodes"; }; advertiseExitNode = mkOption { type = types.bool; default = false; - description = "Whether to advertise this node as an exit node."; + description = "Advertise as exit node"; }; useExitNode = mkOption { type = types.str; default = ""; - description = "Exit node to use (leave empty to not use any exit node)."; + description = "Use specific node as exit node"; }; extraUpArgs = mkOption { type = types.listOf types.str; - default = []; - description = "Extra arguments to pass to tailscale up."; + default = [ ]; + description = "Additional arguments to pass to tailscale up"; }; - }; - config = mkIf cfg.enable { - home.packages = [ pkgs.tailscale ]; + # Important directories and files + directories = mkOption { + type = types.attrsOf types.anything; + default = { }; + description = "Integration with home-manager's directories option"; + }; - # Create directory for Tailscale state - home.activation.tailscaleStateDir = lib.hm.dag.entryAfter [ "writeBoundary" ] '' - mkdir -p $HOME/.local/share/tailscale - chmod 755 $HOME/.local/share/tailscale - ''; - }; -} -// lib.mkIf (pkgs.stdenv.isDarwin && config.services.tailscale.enable) { - # macOS launchd service for tailscaled - launchd.agents.tailscaled = { - enable = true; - config = { - ProgramArguments = [ - "${pkgs.tailscale}/bin/tailscaled" - "--state=$HOME/.local/share/tailscale/tailscaled.state" - "--socket=$HOME/.local/share/tailscale/tailscaled.sock" - ]; - KeepAlive = true; - RunAtLoad = true; - StandardOutPath = "$HOME/.local/share/tailscale/tailscaled.log"; - StandardErrorPath = "$HOME/.local/share/tailscale/tailscaled.error.log"; + files = mkOption { + type = types.attrsOf types.anything; + default = { }; + description = "Integration with home-manager's files option"; + }; + + # Service module + serviceConfig = mkOption { + type = types.attrsOf types.anything; + default = { }; + description = "Optional systemd service configuration override"; }; }; - # macOS launchd service for tailscale up - launchd.agents.tailscale-up = { - enable = true; - config = { - ProgramArguments = [ - "${pkgs.bash}/bin/bash" - "-c" - '' - # Wait for tailscaled to be ready - for i in {1..30}; do - if ${pkgs.tailscale}/bin/tailscale status >/dev/null 2>&1; then - break - fi - sleep 1 - done + config = mkIf cfg.enable { + home.packages = [ cfg.tailscaled.package ]; + + # Declare directories and files for home-manager + home.file.".local/share/tailscale/tailscaled.state".source = + config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/.local/state/tailscale/tailscaled.state"; - # Configure Tailscale with specified options - ${pkgs.tailscale}/bin/tailscale up \ - ${optionalString config.services.tailscale.acceptRoutes "--accept-routes"} \ - ${optionalString config.services.tailscale.advertiseExitNode "--advertise-exit-node"} \ - ${optionalString (config.services.tailscale.useExitNode != "") "--exit-node=${config.services.tailscale.useExitNode}"} \ - ${concatStringsSep " " config.services.tailscale.extraUpArgs} - '' - ]; - RunAtLoad = true; - KeepAlive = { - SuccessfulExit = false; + # Tailscaled service + systemd.user.services.tailscaled = mkIf configEnabled { + Unit = { + Description = "Tailscale VPN daemon"; + After = [ "network-online.target" ]; + Wants = [ "network-online.target" ]; }; - StandardOutPath = "$HOME/.local/share/tailscale/tailscale-up.log"; - StandardErrorPath = "$HOME/.local/share/tailscale/tailscale-up.error.log"; - }; - }; -} -// lib.mkIf (pkgs.stdenv.isLinux && config.services.tailscale.enable) { - # Linux systemd service for tailscaled - systemd.user.services.tailscaled = { - Unit = { - Description = "Tailscale client daemon"; - After = [ "network.target" ]; - PartOf = [ "graphical-session.target" ]; - }; - Service = { - ExecStart = "${pkgs.tailscale}/bin/tailscaled --state=${config.xdg.dataHome}/tailscale/tailscaled.state --socket=${config.xdg.runtimeDir}/tailscale/tailscaled.sock"; - Restart = "on-failure"; - RestartSec = 5; - }; + Service = { + ExecStart = "${pkgs.tailscale}/bin/tailscaled --state=${config.xdg.dataHome}/tailscale/tailscaled.state --socket=${config.xdg.runtimeDir}/tailscale/tailscaled.sock"; + Restart = "on-failure"; + RestartSec = 5; + } + // cfg.serviceConfig.service or { }; - Install = { - WantedBy = [ "default.target" ]; + Install.WantedBy = [ "default.target" ]; }; - }; - # Linux systemd service for tailscale up - systemd.user.services.tailscale-up = { - Unit = { - Description = "Configure Tailscale connection"; - After = [ "tailscaled.service" ]; - PartOf = [ "tailscaled.service" ]; - }; + # Tailscale up service (runs once to connect) + systemd.user.services.tailscale-up = mkIf configEnabled { + Unit = { + Description = "Connect Tailscale to network"; + After = [ "tailscaled.service" ]; + Requires = [ "tailscaled.service" ]; + }; - Service = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = "${pkgs.bash}/bin/bash -c 'tailscale up \ - ${optionalString config.services.tailscale.acceptRoutes "--accept-routes"} \ - ${optionalString config.services.tailscale.advertiseExitNode "--advertise-exit-node"} \ - ${optionalString (config.services.tailscale.useExitNode != "") "--exit-node=${config.services.tailscale.useExitNode}"} \ - ${concatStringsSep " " config.services.tailscale.extraUpArgs}'"; - ExecStop = "${pkgs.tailscale}/bin/tailscale down"; - }; + Service = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.bash}/bin/bash -c ' + # Determine auth key + AUTH_KEY=" " + if [ -n \"${cfg.authKey}\" ]; then + AUTH_KEY=\"${cfg.authKey}\" + elif [ -n \"${cfg.authKeyFile}\" ] && [ -f \"${cfg.authKeyFile}\" ]; then + AUTH_KEY=$(cat \"${cfg.authKeyFile}\") + fi + + # Configure Tailscale with specified options + tailscale up \ + ${ + optionalString (cfg.authKey != "") "--authkey=${cfg.authKey}" + } \ + ${ + optionalString (cfg.authKeyFile != "") "--authkey=$AUTH_KEY" + } \ + ${optionalString cfg.acceptRoutes "--accept-routes"} \ + ${optionalString cfg.advertiseExitNode "--advertise-exit-node"} \ + ${ + optionalString (cfg.useExitNode != "") "--exit-node=${cfg.useExitNode}" + } \ + ${concatStringsSep " " cfg.extraUpArgs}'"; + ExecStop = "${pkgs.tailscale}/bin/tailscale down"; + }; - Install = { - WantedBy = [ "default.target" ]; + Install.WantedBy = [ "default.target" ]; }; + + home.activation.createTailscaleDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + TAILSCALE_STATE_DIR="${config.xdg.dataHome}/tailscale" + TAILSCALE_RUN_DIR="${config.xdg.runtimeDir}/tailscale" + + # Create directories + $DRY_RUN_CMD mkdir -p "$TAILSCALE_STATE_DIR" + $DRY_RUN_CMD mkdir -p "$TAILSCALE_RUN_DIR" + + # Set proper permissions + $DRY_RUN_CMD chmod 700 "$TAILSCALE_STATE_DIR" + $DRY_RUN_CMD chmod 700 "$TAILSCALE_RUN_DIR" + ''; }; } diff --git a/named-hosts/galactica/default.nix b/named-hosts/galactica/default.nix index ad16e1eb3..68ea44230 100644 --- a/named-hosts/galactica/default.nix +++ b/named-hosts/galactica/default.nix @@ -59,6 +59,19 @@ inputs.nix-darwin.lib.darwinSystem { home.sessionVariables = { GPG_TTY = "$(tty)"; }; + + # Tailscale configuration with auth key support + services.tailscale = { + enable = true; + acceptRoutes = false; + advertiseExitNode = false; + useExitNode = ""; + authKeyFile = config.age.secrets."keys/tailscale-auth.age".path; + extraUpArgs = [ + "--reset" + "--accept-dns=false" + ]; + }; }; } ]; diff --git a/named-hosts/galactica/keys/tailscale-auth.age b/named-hosts/galactica/keys/tailscale-auth.age new file mode 100644 index 000000000..4d4f245df --- /dev/null +++ b/named-hosts/galactica/keys/tailscale-auth.age @@ -0,0 +1,9 @@ +# This is a placeholder for the encrypted Tailscale auth key +# To encrypt your actual auth key, use: +# make encrypt-key-galactica KEY_FILE=/path/to/your/tailscale-auth-key.txt +# +# To get a Tailscale auth key: +# 1. Log in to https://login.tailscale.com/admin +# 2. Go to Settings -> Keys +# 3. Generate a new auth key (recommended: non-ephemeral, reusable) +# 4. Save the key to a file and encrypt it using the command above diff --git a/named-hosts/galactica/secrets.nix b/named-hosts/galactica/secrets.nix index 29e25935a..9482635f7 100644 --- a/named-hosts/galactica/secrets.nix +++ b/named-hosts/galactica/secrets.nix @@ -11,4 +11,10 @@ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com" ]; }; + "keys/tailscale-auth.age" = { + file = ./keys/tailscale-auth.age; + publicKeys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEKze2jlpV7SyTKA2ezqbumpCiDn+5Sj4z5SxrqfzesX shunkakinoki@gmail.com" + ]; + }; }