2023-01-27 13:37:20 -08:00
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
2022-10-21 23:05:43 +00:00
// Code generated by tailscale/cmd/viewer; DO NOT EDIT.
package ipn
import (
2025-08-14 13:46:48 -07:00
jsonv1 "encoding/json"
2022-10-21 23:05:43 +00:00
"errors"
"net/netip"
2025-08-14 13:46:48 -07:00
jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext"
2024-04-02 13:32:30 -07:00
"tailscale.com/drive"
2022-10-21 23:05:43 +00:00
"tailscale.com/tailcfg"
2024-05-06 15:22:17 -07:00
"tailscale.com/types/opt"
2022-10-21 23:05:43 +00:00
"tailscale.com/types/persist"
"tailscale.com/types/preftype"
"tailscale.com/types/views"
)
2025-01-30 11:24:25 -06:00
//go:generate go run tailscale.com/cmd/cloner -clonefunc=false -type=LoginProfile,Prefs,ServeConfig,ServiceConfig,TCPPortHandler,HTTPHandler,WebServerConfig
// View returns a read-only view of LoginProfile.
func ( p * LoginProfile ) View ( ) LoginProfileView {
return LoginProfileView { ж : p }
}
// LoginProfileView provides a read-only view over LoginProfile.
//
// Its methods should only be called if `Valid()` returns true.
type LoginProfileView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * LoginProfile
}
// Valid reports whether v's underlying value is non-nil.
func ( v LoginProfileView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v LoginProfileView ) AsStruct ( ) * LoginProfile {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v LoginProfileView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v LoginProfileView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2025-01-30 11:24:25 -06:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2025-01-30 11:24:25 -06:00
func ( v * LoginProfileView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x LoginProfile
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * LoginProfileView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x LoginProfile
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2025-01-30 11:24:25 -06:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// ID is a unique identifier for this profile.
// It is assigned on creation and never changes.
// It may seem redundant to have both ID and UserProfile.ID
// but they are different things. UserProfile.ID may change
// over time (e.g. if a device is tagged).
func ( v LoginProfileView ) ID ( ) ProfileID { return v . ж . ID }
// Name is the user-visible name of this profile.
// It is filled in from the UserProfile.LoginName field.
func ( v LoginProfileView ) Name ( ) string { return v . ж . Name }
// NetworkProfile is a subset of netmap.NetworkMap that we
// store to remember information about the tailnet that this
// profile was logged in with.
//
// This field was added on 2023-11-17.
func ( v LoginProfileView ) NetworkProfile ( ) NetworkProfile { return v . ж . NetworkProfile }
// Key is the StateKey under which the profile is stored.
// It is assigned once at profile creation time and never changes.
func ( v LoginProfileView ) Key ( ) StateKey { return v . ж . Key }
// UserProfile is the server provided UserProfile for this profile.
// This is updated whenever the server provides a new UserProfile.
2025-01-30 11:24:25 -06:00
func ( v LoginProfileView ) UserProfile ( ) tailcfg . UserProfile { return v . ж . UserProfile }
2025-08-27 00:06:28 -07:00
// NodeID is the NodeID of the node that this profile is logged into.
// This should be stable across tagging and untagging nodes.
// It may seem redundant to check against both the UserProfile.UserID
// and the NodeID. However the NodeID can change if the node is deleted
// from the admin panel.
func ( v LoginProfileView ) NodeID ( ) tailcfg . StableNodeID { return v . ж . NodeID }
// LocalUserID is the user ID of the user who created this profile.
// It is only relevant on Windows where we have a multi-user system.
// It is assigned once at profile creation time and never changes.
func ( v LoginProfileView ) LocalUserID ( ) WindowsUserID { return v . ж . LocalUserID }
// ControlURL is the URL of the control server that this profile is logged
// into.
func ( v LoginProfileView ) ControlURL ( ) string { return v . ж . ControlURL }
2025-01-30 11:24:25 -06:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _LoginProfileViewNeedsRegeneration = LoginProfile ( struct {
ID ProfileID
Name string
NetworkProfile NetworkProfile
Key StateKey
UserProfile tailcfg . UserProfile
NodeID tailcfg . StableNodeID
LocalUserID WindowsUserID
ControlURL string
} { } )
2022-10-21 23:05:43 +00:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of Prefs.
2022-10-21 23:05:43 +00:00
func ( p * Prefs ) View ( ) PrefsView {
return PrefsView { ж : p }
}
// PrefsView provides a read-only view over Prefs.
//
// Its methods should only be called if `Valid()` returns true.
type PrefsView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * Prefs
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-10-21 23:05:43 +00:00
func ( v PrefsView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v PrefsView ) AsStruct ( ) * Prefs {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v PrefsView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v PrefsView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-10-21 23:05:43 +00:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-10-21 23:05:43 +00:00
func ( v * PrefsView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x Prefs
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * PrefsView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x Prefs
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-10-21 23:05:43 +00:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// ControlURL is the URL of the control server to use.
//
// If empty, the default for new installs, DefaultControlURL
// is used. It's set non-empty once the daemon has been started
// for the first time.
//
// TODO(apenwarr): Make it safe to update this with EditPrefs().
// Right now, you have to pass it in the initial prefs in Start(),
// which is the only code that actually uses the ControlURL value.
// It would be more consistent to restart controlclient
// automatically whenever this variable changes.
//
// Meanwhile, you have to provide this as part of
// Options.LegacyMigrationPrefs or Options.UpdatePrefs when
// calling Backend.Start().
func ( v PrefsView ) ControlURL ( ) string { return v . ж . ControlURL }
// RouteAll specifies whether to accept subnets advertised by
// other nodes on the Tailscale network. Note that this does not
// include default routes (0.0.0.0/0 and ::/0), those are
// controlled by ExitNodeID/IP below.
func ( v PrefsView ) RouteAll ( ) bool { return v . ж . RouteAll }
// ExitNodeID and ExitNodeIP specify the node that should be used
// as an exit node for internet traffic. At most one of these
// should be non-zero.
//
// The preferred way to express the chosen node is ExitNodeID, but
// in some cases it's not possible to use that ID (e.g. in the
// linux CLI, before tailscaled has a netmap). For those
// situations, we allow specifying the exit node by IP, and
// ipnlocal.LocalBackend will translate the IP into an ID when the
// node is found in the netmap.
//
// If the selected exit node doesn't exist (e.g. it's not part of
// the current tailnet), or it doesn't offer exit node services, a
// blackhole route will be installed on the local system to
// prevent any traffic escaping to the local network.
func ( v PrefsView ) ExitNodeID ( ) tailcfg . StableNodeID { return v . ж . ExitNodeID }
func ( v PrefsView ) ExitNodeIP ( ) netip . Addr { return v . ж . ExitNodeIP }
// AutoExitNode is an optional expression that specifies whether and how
// tailscaled should pick an exit node automatically.
//
// If specified, tailscaled will use an exit node based on the expression,
// and will re-evaluate the selection periodically as network conditions,
// available exit nodes, or policy settings change. A blackhole route will
// be installed to prevent traffic from escaping to the local network until
// an exit node is selected. It takes precedence over ExitNodeID and ExitNodeIP.
//
// If empty, tailscaled will not automatically select an exit node.
//
// If the specified expression is invalid or unsupported by the client,
// it falls back to the behavior of [AnyExitNode].
//
// As of 2025-07-02, the only supported value is [AnyExitNode].
// It's a string rather than a boolean to allow future extensibility
// (e.g., AutoExitNode = "mullvad" or AutoExitNode = "geo:us").
func ( v PrefsView ) AutoExitNode ( ) ExitNodeExpression { return v . ж . AutoExitNode }
// InternalExitNodePrior is the most recently used ExitNodeID in string form. It is set by
// the backend on transition from exit node on to off and used by the
// backend.
//
// As an Internal field, it can't be set by LocalAPI clients, rather it is set indirectly
// when the ExitNodeID value is zero'd and via the set-use-exit-node-enabled endpoint.
2024-04-16 14:53:56 -04:00
func ( v PrefsView ) InternalExitNodePrior ( ) tailcfg . StableNodeID { return v . ж . InternalExitNodePrior }
2025-08-27 00:06:28 -07:00
// ExitNodeAllowLANAccess indicates whether locally accessible subnets should be
// routed directly or via the exit node.
func ( v PrefsView ) ExitNodeAllowLANAccess ( ) bool { return v . ж . ExitNodeAllowLANAccess }
// CorpDNS specifies whether to install the Tailscale network's
// DNS configuration, if it exists.
func ( v PrefsView ) CorpDNS ( ) bool { return v . ж . CorpDNS }
// RunSSH bool is whether this node should run an SSH
// server, permitting access to peers according to the
// policies as configured by the Tailnet's admin(s).
func ( v PrefsView ) RunSSH ( ) bool { return v . ж . RunSSH }
// RunWebClient bool is whether this node should expose
// its web client over Tailscale at port 5252,
// permitting access to peers according to the
// policies as configured by the Tailnet's admin(s).
func ( v PrefsView ) RunWebClient ( ) bool { return v . ж . RunWebClient }
// WantRunning indicates whether networking should be active on
// this node.
func ( v PrefsView ) WantRunning ( ) bool { return v . ж . WantRunning }
// LoggedOut indicates whether the user intends to be logged out.
// There are other reasons we may be logged out, including no valid
// keys.
// We need to remember this state so that, on next startup, we can
// generate the "Login" vs "Connect" buttons correctly, without having
// to contact the server to confirm our nodekey status first.
func ( v PrefsView ) LoggedOut ( ) bool { return v . ж . LoggedOut }
// ShieldsUp indicates whether to block all incoming connections,
// regardless of the control-provided packet filter. If false, we
// use the packet filter as provided. If true, we block incoming
// connections. This overrides tailcfg.Hostinfo's ShieldsUp.
func ( v PrefsView ) ShieldsUp ( ) bool { return v . ж . ShieldsUp }
// AdvertiseTags specifies tags that should be applied to this node, for
// purposes of ACL enforcement. These can be referenced from the ACL policy
// document. Note that advertising a tag on the client doesn't guarantee
// that the control server will allow the node to adopt that tag.
func ( v PrefsView ) AdvertiseTags ( ) views . Slice [ string ] { return views . SliceOf ( v . ж . AdvertiseTags ) }
// Hostname is the hostname to use for identifying the node. If
// not set, os.Hostname is used.
func ( v PrefsView ) Hostname ( ) string { return v . ж . Hostname }
// NotepadURLs is a debugging setting that opens OAuth URLs in
// notepad.exe on Windows, rather than loading them in a browser.
//
// apenwarr 2020-04-29: Unfortunately this is still needed sometimes.
// Windows' default browser setting is sometimes screwy and this helps
// users narrow it down a bit.
func ( v PrefsView ) NotepadURLs ( ) bool { return v . ж . NotepadURLs }
// ForceDaemon specifies whether a platform that normally
// operates in "client mode" (that is, requires an active user
// logged in with the GUI app running) should keep running after the
// GUI ends and/or the user logs out.
//
// The only current applicable platform is Windows. This
// forced Windows to go into "server mode" where Tailscale is
// running even with no users logged in. This might also be
// used for macOS in the future. This setting has no effect
// for Linux/etc, which always operate in daemon mode.
func ( v PrefsView ) ForceDaemon ( ) bool { return v . ж . ForceDaemon }
// Egg is a optional debug flag.
func ( v PrefsView ) Egg ( ) bool { return v . ж . Egg }
// AdvertiseRoutes specifies CIDR prefixes to advertise into the
// Tailscale network as reachable through the current
// node.
2023-08-18 10:57:04 -07:00
func ( v PrefsView ) AdvertiseRoutes ( ) views . Slice [ netip . Prefix ] {
return views . SliceOf ( v . ж . AdvertiseRoutes )
2022-10-21 23:05:43 +00:00
}
2025-08-27 00:06:28 -07:00
// AdvertiseServices specifies the list of services that this
// node can serve as a destination for. Note that an advertised
// service must still go through the approval process from the
// control server.
2024-10-16 19:08:06 -04:00
func ( v PrefsView ) AdvertiseServices ( ) views . Slice [ string ] {
return views . SliceOf ( v . ж . AdvertiseServices )
}
2025-08-27 00:06:28 -07:00
2025-11-17 08:06:16 -08:00
// Sync is whether this node should sync its configuration from
// the control plane. If unset, this defaults to true.
// This exists primarily for testing, to verify that netmap caching
// and offline operation work correctly.
func ( v PrefsView ) Sync ( ) opt . Bool { return v . ж . Sync }
2025-08-27 00:06:28 -07:00
// NoSNAT specifies whether to source NAT traffic going to
// destinations in AdvertiseRoutes. The default is to apply source
// NAT, which makes the traffic appear to come from the router
// machine rather than the peer's Tailscale IP.
//
// Disabling SNAT requires additional manual configuration in your
// network to route Tailscale traffic back to the subnet relay
// machine.
//
// Linux-only.
func ( v PrefsView ) NoSNAT ( ) bool { return v . ж . NoSNAT }
// NoStatefulFiltering specifies whether to apply stateful filtering when
// advertising routes in AdvertiseRoutes. The default is to not apply
// stateful filtering.
//
// To allow inbound connections from advertised routes, both NoSNAT and
// NoStatefulFiltering must be true.
//
// This is an opt.Bool because it was first added after NoSNAT, with a
// backfill based on the value of that parameter. The backfill has been
// removed since then, but the field remains an opt.Bool.
//
// Linux-only.
func ( v PrefsView ) NoStatefulFiltering ( ) opt . Bool { return v . ж . NoStatefulFiltering }
// NetfilterMode specifies how much to manage netfilter rules for
// Tailscale, if at all.
2022-10-21 23:05:43 +00:00
func ( v PrefsView ) NetfilterMode ( ) preftype . NetfilterMode { return v . ж . NetfilterMode }
2025-08-27 00:06:28 -07:00
// OperatorUser is the local machine user name who is allowed to
// operate tailscaled without being root or using sudo.
func ( v PrefsView ) OperatorUser ( ) string { return v . ж . OperatorUser }
// ProfileName is the desired name of the profile. If empty, then the user's
// LoginName is used. It is only used for display purposes in the client UI
// and CLI.
func ( v PrefsView ) ProfileName ( ) string { return v . ж . ProfileName }
// AutoUpdate sets the auto-update preferences for the node agent. See
// AutoUpdatePrefs docs for more details.
func ( v PrefsView ) AutoUpdate ( ) AutoUpdatePrefs { return v . ж . AutoUpdate }
// AppConnector sets the app connector preferences for the node agent. See
// AppConnectorPrefs docs for more details.
func ( v PrefsView ) AppConnector ( ) AppConnectorPrefs { return v . ж . AppConnector }
// PostureChecking enables the collection of information used for device
// posture checks.
//
// Note: this should be named ReportPosture, but it was shipped as
// PostureChecking in some early releases and this JSON field is written to
// disk, so we just keep its old name. (akin to CorpDNS which is an internal
// pref name that doesn't match the public interface)
func ( v PrefsView ) PostureChecking ( ) bool { return v . ж . PostureChecking }
// NetfilterKind specifies what netfilter implementation to use.
//
2025-09-26 16:19:12 -07:00
// It can be "iptables", "nftables", or "" to auto-detect.
//
2025-08-27 00:06:28 -07:00
// Linux-only.
func ( v PrefsView ) NetfilterKind ( ) string { return v . ж . NetfilterKind }
// DriveShares are the configured DriveShares, stored in increasing order
// by name.
2024-04-03 10:09:58 -07:00
func ( v PrefsView ) DriveShares ( ) views . SliceView [ * drive . Share , drive . ShareView ] {
return views . SliceOfViews [ * drive . Share , drive . ShareView ] ( v . ж . DriveShares )
2024-03-07 10:56:11 -06:00
}
2025-08-27 00:06:28 -07:00
// RelayServerPort is the UDP port number for the relay server to bind to,
// on all interfaces. A non-nil zero value signifies a random unused port
// should be used. A nil value signifies relay server functionality
2025-11-25 15:05:04 -08:00
// should be disabled.
func ( v PrefsView ) RelayServerPort ( ) views . ValuePointer [ uint16 ] {
2025-04-09 10:25:57 -07:00
return views . ValuePointerOf ( v . ж . RelayServerPort )
}
2025-11-21 15:29:25 -08:00
// RelayServerStaticEndpoints are static IP:port endpoints to advertise as
// candidates for relay connections. Only relevant when RelayServerPort is
// non-nil.
func ( v PrefsView ) RelayServerStaticEndpoints ( ) views . Slice [ netip . AddrPort ] {
return views . SliceOf ( v . ж . RelayServerStaticEndpoints )
}
2025-08-27 00:06:28 -07:00
// AllowSingleHosts was a legacy field that was always true
// for the past 4.5 years. It controlled whether Tailscale
2025-11-17 07:54:29 -08:00
// peers got /32 or /128 routes for each other.
2025-08-27 00:06:28 -07:00
// As of 2024-05-17 we're starting to ignore it, but to let
// people still downgrade Tailscale versions and not break
// all peer-to-peer networking we still write it to disk (as JSON)
// so it can be loaded back by old versions.
// TODO(bradfitz): delete this in 2025 sometime. See #12058.
2024-05-17 13:47:57 -07:00
func ( v PrefsView ) AllowSingleHosts ( ) marshalAsTrueInJSON { return v . ж . AllowSingleHosts }
2025-08-27 00:06:28 -07:00
// The Persist field is named 'Config' in the file for backward
// compatibility with earlier versions.
// TODO(apenwarr): We should move this out of here, it's not a pref.
//
// We can maybe do that once we're sure which module should persist
// it (backend or frontend?)
func ( v PrefsView ) Persist ( ) persist . PersistView { return v . ж . Persist . View ( ) }
2022-10-21 23:05:43 +00:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _PrefsViewNeedsRegeneration = Prefs ( struct {
2025-11-21 15:29:25 -08:00
ControlURL string
RouteAll bool
ExitNodeID tailcfg . StableNodeID
ExitNodeIP netip . Addr
AutoExitNode ExitNodeExpression
InternalExitNodePrior tailcfg . StableNodeID
ExitNodeAllowLANAccess bool
CorpDNS bool
RunSSH bool
RunWebClient bool
WantRunning bool
LoggedOut bool
ShieldsUp bool
AdvertiseTags [ ] string
Hostname string
NotepadURLs bool
ForceDaemon bool
Egg bool
AdvertiseRoutes [ ] netip . Prefix
AdvertiseServices [ ] string
Sync opt . Bool
NoSNAT bool
NoStatefulFiltering opt . Bool
NetfilterMode preftype . NetfilterMode
OperatorUser string
ProfileName string
AutoUpdate AutoUpdatePrefs
AppConnector AppConnectorPrefs
PostureChecking bool
NetfilterKind string
DriveShares [ ] * drive . Share
2025-11-25 15:05:04 -08:00
RelayServerPort * uint16
2025-11-21 15:29:25 -08:00
RelayServerStaticEndpoints [ ] netip . AddrPort
AllowSingleHosts marshalAsTrueInJSON
Persist * persist . Persist
2022-10-21 23:05:43 +00:00
} { } )
2022-11-09 06:10:06 -08:00
2025-01-14 08:15:27 -08:00
// View returns a read-only view of ServeConfig.
2022-11-09 06:10:06 -08:00
func ( p * ServeConfig ) View ( ) ServeConfigView {
return ServeConfigView { ж : p }
}
// ServeConfigView provides a read-only view over ServeConfig.
//
// Its methods should only be called if `Valid()` returns true.
type ServeConfigView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * ServeConfig
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-11-09 06:10:06 -08:00
func ( v ServeConfigView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v ServeConfigView ) AsStruct ( ) * ServeConfig {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v ServeConfigView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v ServeConfigView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-11-09 06:10:06 -08:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-11-09 06:10:06 -08:00
func ( v * ServeConfigView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x ServeConfig
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * ServeConfigView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x ServeConfig
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-11-09 06:10:06 -08:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// TCP are the list of TCP port numbers that tailscaled should handle for
// the Tailscale IP addresses. (not subnet routers, etc)
2022-11-10 22:58:40 -05:00
func ( v ServeConfigView ) TCP ( ) views . MapFn [ uint16 , * TCPPortHandler , TCPPortHandlerView ] {
2022-11-09 06:10:06 -08:00
return views . MapFnOf ( v . ж . TCP , func ( t * TCPPortHandler ) TCPPortHandlerView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// Web maps from "$SNI_NAME:$PORT" to a set of HTTP handlers
// keyed by mount point ("/", "/foo", etc)
2022-11-09 06:10:06 -08:00
func ( v ServeConfigView ) Web ( ) views . MapFn [ HostPort , * WebServerConfig , WebServerConfigView ] {
return views . MapFnOf ( v . ж . Web , func ( t * WebServerConfig ) WebServerConfigView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// Services maps from service name (in the form "svc:dns-label") to a ServiceConfig.
// Which describes the L3, L4, and L7 forwarding information for the service.
2025-01-21 17:07:34 -05:00
func ( v ServeConfigView ) Services ( ) views . MapFn [ tailcfg . ServiceName , * ServiceConfig , ServiceConfigView ] {
2024-11-28 12:49:37 -05:00
return views . MapFnOf ( v . ж . Services , func ( t * ServiceConfig ) ServiceConfigView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// AllowFunnel is the set of SNI:port values for which funnel
// traffic is allowed, from trusted ingress peers.
2022-11-17 16:09:43 -05:00
func ( v ServeConfigView ) AllowFunnel ( ) views . Map [ HostPort , bool ] {
return views . MapOf ( v . ж . AllowFunnel )
2022-11-07 10:46:42 -05:00
}
2025-08-27 00:06:28 -07:00
// Foreground is a map of an IPN Bus session ID to an alternate foreground serve config that's valid for the
// life of that WatchIPNBus session ID. This allows the config to specify ephemeral configs that are used
// in the CLI's foreground mode to ensure ungraceful shutdowns of either the client or the LocalBackend does not
// expose ports that users are not aware of. In practice this contains any serve config set via 'tailscale
// serve' command run without the '--bg' flag. ServeConfig contained by Foreground is not expected itself to contain
// another Foreground block.
2023-09-05 14:33:18 -04:00
func ( v ServeConfigView ) Foreground ( ) views . MapFn [ string , * ServeConfig , ServeConfigView ] {
return views . MapFnOf ( v . ж . Foreground , func ( t * ServeConfig ) ServeConfigView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// ETag is the checksum of the serve config that's populated
// by the LocalClient through the HTTP ETag header during a
// GetServeConfig request and is translated to an If-Match header
// during a SetServeConfig request.
2023-09-11 21:32:51 -04:00
func ( v ServeConfigView ) ETag ( ) string { return v . ж . ETag }
2023-09-05 14:33:18 -04:00
2022-11-09 06:10:06 -08:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _ServeConfigViewNeedsRegeneration = ServeConfig ( struct {
2022-11-17 16:09:43 -05:00
TCP map [ uint16 ] * TCPPortHandler
Web map [ HostPort ] * WebServerConfig
2025-01-21 17:07:34 -05:00
Services map [ tailcfg . ServiceName ] * ServiceConfig
2022-11-17 16:09:43 -05:00
AllowFunnel map [ HostPort ] bool
2023-09-05 14:33:18 -04:00
Foreground map [ string ] * ServeConfig
2023-09-11 21:32:51 -04:00
ETag string
2022-11-09 06:10:06 -08:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of ServiceConfig.
2024-11-28 12:49:37 -05:00
func ( p * ServiceConfig ) View ( ) ServiceConfigView {
return ServiceConfigView { ж : p }
}
// ServiceConfigView provides a read-only view over ServiceConfig.
//
// Its methods should only be called if `Valid()` returns true.
type ServiceConfigView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * ServiceConfig
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2024-11-28 12:49:37 -05:00
func ( v ServiceConfigView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v ServiceConfigView ) AsStruct ( ) * ServiceConfig {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v ServiceConfigView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
2024-11-28 12:49:37 -05:00
2025-08-14 13:46:48 -07:00
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v ServiceConfigView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2024-11-28 12:49:37 -05:00
func ( v * ServiceConfigView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x ServiceConfig
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * ServiceConfigView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x ServiceConfig
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2024-11-28 12:49:37 -05:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// TCP are the list of TCP port numbers that tailscaled should handle for
// the Tailscale IP addresses. (not subnet routers, etc)
2024-11-28 12:49:37 -05:00
func ( v ServiceConfigView ) TCP ( ) views . MapFn [ uint16 , * TCPPortHandler , TCPPortHandlerView ] {
return views . MapFnOf ( v . ж . TCP , func ( t * TCPPortHandler ) TCPPortHandlerView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// Web maps from "$SNI_NAME:$PORT" to a set of HTTP handlers
// keyed by mount point ("/", "/foo", etc)
2024-11-28 12:49:37 -05:00
func ( v ServiceConfigView ) Web ( ) views . MapFn [ HostPort , * WebServerConfig , WebServerConfigView ] {
return views . MapFnOf ( v . ж . Web , func ( t * WebServerConfig ) WebServerConfigView {
return t . View ( )
} )
}
2025-08-27 00:06:28 -07:00
// Tun determines if the service should be using L3 forwarding (Tun mode).
2024-11-28 12:49:37 -05:00
func ( v ServiceConfigView ) Tun ( ) bool { return v . ж . Tun }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _ServiceConfigViewNeedsRegeneration = ServiceConfig ( struct {
TCP map [ uint16 ] * TCPPortHandler
Web map [ HostPort ] * WebServerConfig
Tun bool
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of TCPPortHandler.
2022-11-09 06:10:06 -08:00
func ( p * TCPPortHandler ) View ( ) TCPPortHandlerView {
return TCPPortHandlerView { ж : p }
}
// TCPPortHandlerView provides a read-only view over TCPPortHandler.
//
// Its methods should only be called if `Valid()` returns true.
type TCPPortHandlerView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * TCPPortHandler
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-11-09 06:10:06 -08:00
func ( v TCPPortHandlerView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v TCPPortHandlerView ) AsStruct ( ) * TCPPortHandler {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v TCPPortHandlerView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v TCPPortHandlerView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-11-09 06:10:06 -08:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-11-09 06:10:06 -08:00
func ( v * TCPPortHandlerView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x TCPPortHandler
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * TCPPortHandlerView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x TCPPortHandler
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-11-09 06:10:06 -08:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// HTTPS, if true, means that tailscaled should handle this connection as an
// HTTPS request as configured by ServeConfig.Web.
//
// It is mutually exclusive with TCPForward.
func ( v TCPPortHandlerView ) HTTPS ( ) bool { return v . ж . HTTPS }
// HTTP, if true, means that tailscaled should handle this connection as an
// HTTP request as configured by ServeConfig.Web.
//
// It is mutually exclusive with TCPForward.
func ( v TCPPortHandlerView ) HTTP ( ) bool { return v . ж . HTTP }
// TCPForward is the IP:port to forward TCP connections to.
// Whether or not TLS is terminated by tailscaled depends on
// TerminateTLS.
//
// It is mutually exclusive with HTTPS.
func ( v TCPPortHandlerView ) TCPForward ( ) string { return v . ж . TCPForward }
// TerminateTLS, if non-empty, means that tailscaled should terminate the
// TLS connections before forwarding them to TCPForward, permitting only the
// SNI name with this value. It is only used if TCPForward is non-empty.
// (the HTTPS mode uses ServeConfig.Web)
2022-11-10 21:24:22 -08:00
func ( v TCPPortHandlerView ) TerminateTLS ( ) string { return v . ж . TerminateTLS }
2022-11-09 06:10:06 -08:00
2025-10-20 11:40:30 -04:00
// ProxyProtocol indicates whether to send a PROXY protocol header
// before forwarding the connection to TCPForward.
//
// This is only valid if TCPForward is non-empty.
func ( v TCPPortHandlerView ) ProxyProtocol ( ) int { return v . ж . ProxyProtocol }
2022-11-09 06:10:06 -08:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _TCPPortHandlerViewNeedsRegeneration = TCPPortHandler ( struct {
2025-10-20 11:40:30 -04:00
HTTPS bool
HTTP bool
TCPForward string
TerminateTLS string
ProxyProtocol int
2022-11-09 06:10:06 -08:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of HTTPHandler.
2022-11-09 06:10:06 -08:00
func ( p * HTTPHandler ) View ( ) HTTPHandlerView {
return HTTPHandlerView { ж : p }
}
// HTTPHandlerView provides a read-only view over HTTPHandler.
//
// Its methods should only be called if `Valid()` returns true.
type HTTPHandlerView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * HTTPHandler
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-11-09 06:10:06 -08:00
func ( v HTTPHandlerView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v HTTPHandlerView ) AsStruct ( ) * HTTPHandler {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v HTTPHandlerView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
2022-11-09 06:10:06 -08:00
2025-08-14 13:46:48 -07:00
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v HTTPHandlerView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-11-09 06:10:06 -08:00
func ( v * HTTPHandlerView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x HTTPHandler
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * HTTPHandlerView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x HTTPHandler
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-11-09 06:10:06 -08:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// absolute path to directory or file to serve
func ( v HTTPHandlerView ) Path ( ) string { return v . ж . Path }
// http://localhost:3000/, localhost:3030, 3030
2022-11-09 06:10:06 -08:00
func ( v HTTPHandlerView ) Proxy ( ) string { return v . ж . Proxy }
2025-08-27 00:06:28 -07:00
// plaintext to serve (primarily for testing)
func ( v HTTPHandlerView ) Text ( ) string { return v . ж . Text }
2022-11-09 06:10:06 -08:00
2025-10-03 17:52:41 +01:00
// peer capabilities to forward in grant header, e.g. example.com/cap/mon
2025-10-15 12:59:10 +01:00
func ( v HTTPHandlerView ) AcceptAppCaps ( ) views . Slice [ tailcfg . PeerCapability ] {
return views . SliceOf ( v . ж . AcceptAppCaps )
2025-10-03 17:52:41 +01:00
}
2025-10-29 21:27:59 -04:00
// Redirect, if not empty, is the target URL to redirect requests to.
// By default, we redirect with HTTP 302 (Found) status.
// If Redirect starts with '<httpcode>:', then we use that status instead.
//
// The target URL supports the following expansion variables:
// - ${HOST}: replaced with the request's Host header value
// - ${REQUEST_URI}: replaced with the request's full URI (path and query string)
func ( v HTTPHandlerView ) Redirect ( ) string { return v . ж . Redirect }
2022-11-09 06:10:06 -08:00
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _HTTPHandlerViewNeedsRegeneration = HTTPHandler ( struct {
2025-10-15 12:59:10 +01:00
Path string
Proxy string
Text string
AcceptAppCaps [ ] tailcfg . PeerCapability
2025-10-29 21:27:59 -04:00
Redirect string
2022-11-09 06:10:06 -08:00
} { } )
2025-01-14 08:15:27 -08:00
// View returns a read-only view of WebServerConfig.
2022-11-09 06:10:06 -08:00
func ( p * WebServerConfig ) View ( ) WebServerConfigView {
return WebServerConfigView { ж : p }
}
// WebServerConfigView provides a read-only view over WebServerConfig.
//
// Its methods should only be called if `Valid()` returns true.
type WebServerConfigView struct {
// ж is the underlying mutable value, named with a hard-to-type
// character that looks pointy like a pointer.
// It is named distinctively to make you think of how dangerous it is to escape
// to callers. You must not let callers be able to mutate it.
ж * WebServerConfig
}
2025-01-14 08:15:27 -08:00
// Valid reports whether v's underlying value is non-nil.
2022-11-09 06:10:06 -08:00
func ( v WebServerConfigView ) Valid ( ) bool { return v . ж != nil }
// AsStruct returns a clone of the underlying value which aliases no memory with
// the original.
func ( v WebServerConfigView ) AsStruct ( ) * WebServerConfig {
if v . ж == nil {
return nil
}
return v . ж . Clone ( )
}
2025-08-14 13:46:48 -07:00
// MarshalJSON implements [jsonv1.Marshaler].
func ( v WebServerConfigView ) MarshalJSON ( ) ( [ ] byte , error ) {
return jsonv1 . Marshal ( v . ж )
}
// MarshalJSONTo implements [jsonv2.MarshalerTo].
func ( v WebServerConfigView ) MarshalJSONTo ( enc * jsontext . Encoder ) error {
return jsonv2 . MarshalEncode ( enc , v . ж )
}
2022-11-09 06:10:06 -08:00
2025-08-14 13:46:48 -07:00
// UnmarshalJSON implements [jsonv1.Unmarshaler].
2022-11-09 06:10:06 -08:00
func ( v * WebServerConfigView ) UnmarshalJSON ( b [ ] byte ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
if len ( b ) == 0 {
return nil
}
var x WebServerConfig
2025-08-14 13:46:48 -07:00
if err := jsonv1 . Unmarshal ( b , & x ) ; err != nil {
return err
}
v . ж = & x
return nil
}
// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func ( v * WebServerConfigView ) UnmarshalJSONFrom ( dec * jsontext . Decoder ) error {
if v . ж != nil {
return errors . New ( "already initialized" )
}
var x WebServerConfig
if err := jsonv2 . UnmarshalDecode ( dec , & x ) ; err != nil {
2022-11-09 06:10:06 -08:00
return err
}
v . ж = & x
return nil
}
2025-08-27 00:06:28 -07:00
// mountPoint => handler
2022-11-09 06:10:06 -08:00
func ( v WebServerConfigView ) Handlers ( ) views . MapFn [ string , * HTTPHandler , HTTPHandlerView ] {
return views . MapFnOf ( v . ж . Handlers , func ( t * HTTPHandler ) HTTPHandlerView {
return t . View ( )
} )
}
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _WebServerConfigViewNeedsRegeneration = WebServerConfig ( struct {
Handlers map [ string ] * HTTPHandler
} { } )