cmd/tailscale, ipn/ipnlocal: add ts_omit_webclient

Fixes #17063
Updates #12614

Change-Id: I0a189f6a4d1c4558351e3195839867725774fa96
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2025-09-08 12:09:29 -07:00
committed by Brad Fitzpatrick
parent ffc82ad820
commit 3e4b0c1516
8 changed files with 63 additions and 23 deletions

View File

@@ -41,7 +41,7 @@ while [ "$#" -gt 1 ]; do
fi
shift
ldflags="$ldflags -w -s"
tags="${tags:+$tags,}ts_omit_aws,ts_omit_bird,ts_omit_tap,ts_omit_kube,ts_omit_completion,ts_omit_ssh,ts_omit_wakeonlan,ts_omit_capture,ts_omit_relayserver,ts_omit_systray,ts_omit_taildrop,ts_omit_tpm,ts_omit_syspolicy,ts_omit_debugeventbus"
tags="${tags:+$tags,}ts_omit_aws,ts_omit_bird,ts_omit_tap,ts_omit_kube,ts_omit_completion,ts_omit_ssh,ts_omit_wakeonlan,ts_omit_capture,ts_omit_relayserver,ts_omit_systray,ts_omit_taildrop,ts_omit_tpm,ts_omit_syspolicy,ts_omit_debugeventbus,ts_omit_webclient"
;;
--box)
if [ ! -z "${TAGS:-}" ]; then

View File

@@ -209,6 +209,7 @@ func noDupFlagify(c *ffcli.Command) {
var fileCmd func() *ffcli.Command
var sysPolicyCmd func() *ffcli.Command
var maybeWebCmd func() *ffcli.Command
func newRootCmd() *ffcli.Command {
rootfs := newFlagSet("tailscale")
@@ -251,7 +252,7 @@ change in the future.
funnelCmd(),
serveCmd(),
versionCmd,
webCmd,
nilOrCall(maybeWebCmd),
nilOrCall(fileCmd),
bugReportCmd,
certCmd,

View File

@@ -15,13 +15,13 @@ import (
"strings"
"github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/client/web"
"tailscale.com/clientupdate"
"tailscale.com/cmd/tailscale/cli/ffcomplete"
"tailscale.com/ipn"
"tailscale.com/net/netutil"
"tailscale.com/net/tsaddr"
"tailscale.com/safesocket"
"tailscale.com/tsconst"
"tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views"
@@ -264,7 +264,7 @@ func runSet(ctx context.Context, args []string) (retErr error) {
}
if setArgs.runWebClient && len(st.TailscaleIPs) > 0 {
printf("\nWeb interface now running at %s:%d\n", st.TailscaleIPs[0], web.ListenPort)
printf("\nWeb interface now running at %s:%d\n", st.TailscaleIPs[0], tsconst.WebListenPort)
}
return nil

View File

@@ -1,6 +1,8 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !ts_omit_webclient
package cli
import (
@@ -22,14 +24,20 @@ import (
"github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/client/web"
"tailscale.com/ipn"
"tailscale.com/tsconst"
)
var webCmd = &ffcli.Command{
Name: "web",
ShortUsage: "tailscale web [flags]",
ShortHelp: "Run a web server for controlling Tailscale",
func init() {
maybeWebCmd = webCmd
}
LongHelp: strings.TrimSpace(`
func webCmd() *ffcli.Command {
return &ffcli.Command{
Name: "web",
ShortUsage: "tailscale web [flags]",
ShortHelp: "Run a web server for controlling Tailscale",
LongHelp: strings.TrimSpace(`
"tailscale web" runs a webserver for controlling the Tailscale daemon.
It's primarily intended for use on Synology, QNAP, and other
@@ -37,16 +45,17 @@ NAS devices where a web interface is the natural place to control
Tailscale, as opposed to a CLI or a native app.
`),
FlagSet: (func() *flag.FlagSet {
webf := newFlagSet("web")
webf.StringVar(&webArgs.listen, "listen", "localhost:8088", "listen address; use port 0 for automatic")
webf.BoolVar(&webArgs.cgi, "cgi", false, "run as CGI script")
webf.StringVar(&webArgs.prefix, "prefix", "", "URL prefix added to requests (for cgi or reverse proxies)")
webf.BoolVar(&webArgs.readonly, "readonly", false, "run web UI in read-only mode")
webf.StringVar(&webArgs.origin, "origin", "", "origin at which the web UI is served (if behind a reverse proxy or used with cgi)")
return webf
})(),
Exec: runWeb,
FlagSet: (func() *flag.FlagSet {
webf := newFlagSet("web")
webf.StringVar(&webArgs.listen, "listen", "localhost:8088", "listen address; use port 0 for automatic")
webf.BoolVar(&webArgs.cgi, "cgi", false, "run as CGI script")
webf.StringVar(&webArgs.prefix, "prefix", "", "URL prefix added to requests (for cgi or reverse proxies)")
webf.BoolVar(&webArgs.readonly, "readonly", false, "run web UI in read-only mode")
webf.StringVar(&webArgs.origin, "origin", "", "origin at which the web UI is served (if behind a reverse proxy or used with cgi)")
return webf
})(),
Exec: runWeb,
}
}
var webArgs struct {
@@ -101,7 +110,7 @@ func runWeb(ctx context.Context, args []string) error {
var startedManagementClient bool // we started the management client
if !existingWebClient && !webArgs.readonly {
// Also start full client in tailscaled.
log.Printf("starting tailscaled web client at http://%s\n", netip.AddrPortFrom(selfIP, web.ListenPort))
log.Printf("starting tailscaled web client at http://%s\n", netip.AddrPortFrom(selfIP, tsconst.WebListenPort))
if err := setRunWebClient(ctx, true); err != nil {
return fmt.Errorf("starting web client in tailscaled: %w", err)
}

View File

@@ -4,6 +4,7 @@
package main
import (
"strings"
"testing"
"tailscale.com/tstest/deptest"
@@ -41,3 +42,22 @@ func TestOmitSyspolicy(t *testing.T) {
},
}.Check(t)
}
// Test that we can build a binary without reflect.MethodByName.
// See https://github.com/tailscale/tailscale/issues/17063
func TestOmitReflectThings(t *testing.T) {
deptest.DepChecker{
GOOS: "linux",
GOARCH: "amd64",
Tags: "ts_include_cli,ts_omit_systray,ts_omit_debugeventbus,ts_omit_webclient",
BadDeps: map[string]string{
"text/template": "unexpected text/template usage",
"html/template": "unexpected text/template usage",
},
OnDep: func(dep string) {
if strings.Contains(dep, "systray") {
t.Errorf("unexpected systray dep %q", dep)
}
},
}.Check(t)
}

View File

@@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !ios && !android
//go:build !ios && !android && !ts_omit_webclient
package ipnlocal
@@ -22,11 +22,12 @@ import (
"tailscale.com/logtail/backoff"
"tailscale.com/net/netutil"
"tailscale.com/tailcfg"
"tailscale.com/tsconst"
"tailscale.com/types/logger"
"tailscale.com/util/mak"
)
const webClientPort = web.ListenPort
const webClientPort = tsconst.WebListenPort
// webClient holds state for the web interface for managing this
// tailscale instance. The web interface is not used by default,

View File

@@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build ios || android
//go:build ios || android || ts_omit_webclient
package ipnlocal

9
tsconst/webclient.go Normal file
View File

@@ -0,0 +1,9 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package tsconst
// WebListenPort is the static port used for the web client when run inside
// tailscaled. (5252 are the numbers above the letters "TSTS" on a qwerty
// keyboard.)
const WebListenPort = 5252