|
|
|
|
@ -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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func webCmd() *ffcli.Command {
|
|
|
|
|
return &ffcli.Command{
|
|
|
|
|
Name: "web",
|
|
|
|
|
ShortUsage: "tailscale web [flags]",
|
|
|
|
|
ShortHelp: "Run a web server for controlling Tailscale",
|
|
|
|
|
|
|
|
|
|
LongHelp: strings.TrimSpace(`
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|