From 302e49dc4e189ed9ddc46bf997f91b9486a8c7d7 Mon Sep 17 00:00:00 2001 From: Alex Chan Date: Mon, 23 Mar 2026 11:59:12 +0000 Subject: [PATCH] cmd/tailscale/cli: add a debug command to print the statedir Example: ```console $ tailscale debug statedir /tmp/ts/node1 ``` Updates #18019 Change-Id: I7c93c94179bd7b56d0fa8fe57a9129df05c2c1df Signed-off-by: Alex Chan --- cmd/tailscale/cli/debug.go | 25 +++++++++++++++++++++++++ ipn/localapi/debug.go | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index 629c694c0..10c383a51 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -387,6 +387,12 @@ func debugCmd() *ffcli.Command { return fs })(), }, + { + Name: "statedir", + ShortUsage: "tailscale debug statedir", + ShortHelp: "Print the location of the state directory (if any)", + Exec: runPrintStateDir, + }, ccall(debugPeerRelayCmd), }...), } @@ -1407,3 +1413,22 @@ func runTestRisk(ctx context.Context, args []string) error { fmt.Println("did-test-risky-action") return nil } + +func runPrintStateDir(ctx context.Context, args []string) error { + if len(args) > 0 { + return errors.New("unexpected arguments") + } + v, err := localClient.DebugResultJSON(ctx, "statedir") + if err != nil { + return err + } + statedir, ok := v.(string) + if ok && statedir != "" { + fmt.Println(statedir) + return nil + } else if ok && statedir == "" { + return errors.New("no statedir is set") + } else { + return fmt.Errorf("got unexpected response from debug API: %v", v) + } +} diff --git a/ipn/localapi/debug.go b/ipn/localapi/debug.go index 36fce16ac..bc77464fd 100644 --- a/ipn/localapi/debug.go +++ b/ipn/localapi/debug.go @@ -234,6 +234,13 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) { } case "rotate-disco-key": err = h.b.DebugRotateDiscoKey() + case "statedir": + root := h.b.TailscaleVarRoot() + w.Header().Set("Content-Type", "application/json") + err = json.NewEncoder(w).Encode(root) + if err == nil { + return + } case "": err = fmt.Errorf("missing parameter 'action'") default: