Documentation ¶
Index ¶
- Constants
- Variables
- func LoadConfig(path string, isFile bool) error
- func NotifyCtx(ctx context.Context, origin, hostname string) context.Context
- type APIKey
- type CLIConfig
- type Config
- type DERPConfig
- type DNSConfig
- type DatabaseConfig
- type FlexibleBoolean
- type GormConfig
- type IPAllocationStrategy
- type LetsEncryptConfig
- type LogConfig
- type LogTailConfig
- type Nameservers
- type Node
- func (node *Node) AppendToIPSet(build *netipx.IPSetBuilder)
- func (node *Node) ApplyHostnameFromHostInfo(hostInfo *tailcfg.Hostinfo)
- func (node *Node) ApplyPeerChange(change *tailcfg.PeerChange)
- func (node *Node) CanAccess(filter []tailcfg.FilterRule, node2 *Node) bool
- func (node *Node) GetFQDN(baseDomain string) (string, error)
- func (node *Node) GivenNameHasBeenChanged() bool
- func (node *Node) IPs() []netip.Addr
- func (node *Node) IPsAsString() []string
- func (node *Node) InIPSet(set *netipx.IPSet) bool
- func (node *Node) IsEphemeral() bool
- func (node Node) IsExpired() bool
- func (node *Node) PeerChangeFromMapRequest(req tailcfg.MapRequest) tailcfg.PeerChange
- func (node *Node) Prefixes() []netip.Prefix
- func (node *Node) Proto() *v1.Node
- func (node *Node) RegisterMethodToV1Enum() v1.RegisterMethod
- type NodeID
- type Nodes
- type OIDCClaims
- type OIDCConfig
- type PKCEConfig
- type Policy
- type PolicyConfig
- type PolicyMode
- type PostgresConfig
- type PreAuthKey
- type Route
- type Routes
- type SqliteConfig
- type StateUpdate
- type StateUpdateType
- type TLSConfig
- type Tuning
- type User
- func (u *User) DisplayNameOrUsername() string
- func (u *User) FromClaim(claims *OIDCClaims)
- func (u *User) Proto() *v1.User
- func (u *User) TailscaleLogin() *tailcfg.Login
- func (u *User) TailscaleUser() *tailcfg.User
- func (u *User) TailscaleUserProfile() tailcfg.UserProfile
- func (u *User) Username() string
- type UserID
Constants ¶
const ( SelfUpdateIdentifier = "self-update" DatabasePostgres = "postgres" DatabaseSqlite = "sqlite3" )
const ( PKCEMethodPlain string = "plain" PKCEMethodS256 string = "S256" )
const ( PolicyModeDB = "database" PolicyModeFile = "file" )
Variables ¶
var ( NotifyOriginKey = ctxkey.New("notify.origin", "") NotifyHostnameKey = ctxkey.New("notify.hostname", "") )
var ( ErrNodeAddressesInvalid = errors.New("failed to parse node addresses") ErrHostnameTooLong = errors.New("hostname too long, cannot except 255 ASCII chars") ErrNodeHasNoGivenName = errors.New("node has no given name") ErrNodeUserHasNoName = errors.New("node user has no name") )
var ( ErrPolicyNotFound = errors.New("acl policy not found") ErrPolicyUpdateIsDisabled = errors.New("update is disabled for modes other than 'database'") )
var ErrCannotParsePrefix = errors.New("cannot parse prefix")
Functions ¶
func LoadConfig ¶
LoadConfig prepares and loads the Headscale configuration into Viper. This means it sets the default values, reads the configuration file and environment variables, and handles deprecated configuration options. It has to be called before LoadServerConfig and LoadCLIConfig. The configuration is not validated and the caller should check for errors using a validation function.
Types ¶
type APIKey ¶
type APIKey struct { ID uint64 `gorm:"primary_key"` Prefix string `gorm:"uniqueIndex"` Hash []byte CreatedAt *time.Time Expiration *time.Time LastSeen *time.Time }
APIKey describes the datamodel for API keys used to remotely authenticate with headscale.
type Config ¶
type Config struct { ServerURL string Addr string MetricsAddr string GRPCAddr string GRPCAllowInsecure bool EphemeralNodeInactivityTimeout time.Duration PrefixV4 *netip.Prefix PrefixV6 *netip.Prefix IPAllocation IPAllocationStrategy NoisePrivateKeyPath string BaseDomain string Log LogConfig DisableUpdateCheck bool Database DatabaseConfig DERP DERPConfig TLS TLSConfig ACMEURL string ACMEEmail string // DNSConfig is the headscale representation of the DNS configuration. // It is kept in the config update for some settings that are // not directly converted into a tailcfg.DNSConfig. DNSConfig DNSConfig // TailcfgDNSConfig is the tailcfg representation of the DNS configuration, // it can be used directly when sending Netmaps to clients. TailcfgDNSConfig *tailcfg.DNSConfig UnixSocket string UnixSocketPermission fs.FileMode OIDC OIDCConfig LogTail LogTailConfig RandomizeClientPort bool CLI CLIConfig Policy PolicyConfig Tuning Tuning }
Config contains the initial Headscale configuration.
func LoadCLIConfig ¶
LoadCLIConfig returns the needed configuration for the CLI client of Headscale to connect to a Headscale server.
func LoadServerConfig ¶
LoadServerConfig returns the full Headscale configuration to host a Headscale server. This is called as part of `headscale serve`.
type DERPConfig ¶
type DERPConfig struct { ServerEnabled bool AutomaticallyAddEmbeddedDerpRegion bool ServerRegionID int ServerRegionCode string ServerRegionName string ServerPrivateKeyPath string STUNAddr string URLs []url.URL Paths []string DERPMap *tailcfg.DERPMap AutoUpdate bool UpdateFrequency time.Duration IPv4 string IPv6 string }
type DNSConfig ¶
type DNSConfig struct { MagicDNS bool `mapstructure:"magic_dns"` BaseDomain string `mapstructure:"base_domain"` Nameservers Nameservers SearchDomains []string `mapstructure:"search_domains"` ExtraRecords []tailcfg.DNSRecord `mapstructure:"extra_records"` ExtraRecordsPath string `mapstructure:"extra_records_path"` }
type DatabaseConfig ¶
type DatabaseConfig struct { // Type sets the database type, either "sqlite3" or "postgres" Type string Debug bool // Type sets the gorm configuration Gorm GormConfig Sqlite SqliteConfig Postgres PostgresConfig }
type FlexibleBoolean ¶ added in v0.24.0
type FlexibleBoolean bool
JumpCloud returns a JSON where email_verified is returned as a string "true" or "false" instead of a boolean. This maps bool to a specific type with a custom unmarshaler to ensure we can decode it from a string. https://github.com/juanfont/headscale/issues/2293
func (*FlexibleBoolean) UnmarshalJSON ¶ added in v0.24.0
func (bit *FlexibleBoolean) UnmarshalJSON(data []byte) error
type GormConfig ¶
type IPAllocationStrategy ¶
type IPAllocationStrategy string
const ( IPAllocationStrategySequential IPAllocationStrategy = "sequential" IPAllocationStrategyRandom IPAllocationStrategy = "random" )
type LetsEncryptConfig ¶
type LogTailConfig ¶
type LogTailConfig struct {
Enabled bool
}
type Nameservers ¶
type Node ¶
type Node struct { ID NodeID `gorm:"primary_key"` MachineKey key.MachinePublic `gorm:"serializer:text"` NodeKey key.NodePublic `gorm:"serializer:text"` DiscoKey key.DiscoPublic `gorm:"serializer:text"` Endpoints []netip.AddrPort `gorm:"serializer:json"` Hostinfo *tailcfg.Hostinfo `gorm:"column:host_info;serializer:json"` IPv4 *netip.Addr `gorm:"column:ipv4;serializer:text"` IPv6 *netip.Addr `gorm:"column:ipv6;serializer:text"` // Hostname represents the name given by the Tailscale // client during registration Hostname string // Givenname represents either: // a DNS normalized version of Hostname // a valid name set by the User // // GivenName is the name used in all DNS related // parts of headscale. GivenName string `gorm:"type:varchar(63);unique_index"` UserID uint User User `gorm:"constraint:OnDelete:CASCADE;"` RegisterMethod string ForcedTags []string `gorm:"serializer:json"` // TODO(kradalby): This seems like irrelevant information? AuthKeyID *uint64 `sql:"DEFAULT:NULL"` AuthKey *PreAuthKey `gorm:"constraint:OnDelete:SET NULL;"` LastSeen *time.Time Expiry *time.Time Routes []Route `gorm:"constraint:OnDelete:CASCADE;"` CreatedAt time.Time UpdatedAt time.Time DeletedAt *time.Time IsOnline *bool `gorm:"-"` }
Node is a Headscale client.
func (*Node) AppendToIPSet ¶
func (node *Node) AppendToIPSet(build *netipx.IPSetBuilder)
AppendToIPSet adds the individual ips in NodeAddresses to a given netipx.IPSetBuilder.
func (*Node) ApplyHostnameFromHostInfo ¶ added in v0.24.0
ApplyHostnameFromHostInfo takes a Hostinfo struct and updates the node.
func (*Node) ApplyPeerChange ¶
func (node *Node) ApplyPeerChange(change *tailcfg.PeerChange)
ApplyPeerChange takes a PeerChange struct and updates the node.
func (*Node) GivenNameHasBeenChanged ¶ added in v0.24.0
GivenNameHasBeenChanged returns whether the `givenName` can be automatically changed based on the `Hostname` of the node.
func (*Node) IPsAsString ¶
func (*Node) IsEphemeral ¶
IsEphemeral returns if the node is registered as an Ephemeral node. https://tailscale.com/kb/1111/ephemeral-nodes/
func (*Node) PeerChangeFromMapRequest ¶
func (node *Node) PeerChangeFromMapRequest(req tailcfg.MapRequest) tailcfg.PeerChange
PeerChangeFromMapRequest takes a MapRequest and compares it to the node to produce a PeerChange struct that can be used to updated the node and inform peers about smaller changes to the node. When a field is added to this function, remember to also add it to: - node.ApplyPeerChange - logTracePeerChange in poll.go.
func (*Node) RegisterMethodToV1Enum ¶
func (node *Node) RegisterMethodToV1Enum() v1.RegisterMethod
type NodeID ¶
type NodeID uint64
func (NodeID) StableID ¶
func (id NodeID) StableID() tailcfg.StableNodeID
type Nodes ¶
type Nodes []*Node
func (Nodes) ContainsNodeKey ¶ added in v0.24.0
func (nodes Nodes) ContainsNodeKey(nodeKey key.NodePublic) bool
type OIDCClaims ¶ added in v0.24.0
type OIDCClaims struct { // Sub is the user's unique identifier at the provider. Sub string `json:"sub"` Iss string `json:"iss"` // Name is the user's full name. Name string `json:"name,omitempty"` Groups []string `json:"groups,omitempty"` Email string `json:"email,omitempty"` EmailVerified FlexibleBoolean `json:"email_verified,omitempty"` ProfilePictureURL string `json:"picture,omitempty"` Username string `json:"preferred_username,omitempty"` }
func (*OIDCClaims) Identifier ¶ added in v0.24.0
func (c *OIDCClaims) Identifier() string
type OIDCConfig ¶
type OIDCConfig struct { OnlyStartIfOIDCIsAvailable bool Issuer string ClientID string ClientSecret string Scope []string ExtraParams map[string]string AllowedDomains []string AllowedUsers []string AllowedGroups []string StripEmaildomain bool Expiry time.Duration UseExpiryFromToken bool MapLegacyUsers bool PKCE PKCEConfig }
type PKCEConfig ¶ added in v0.24.0
type PolicyConfig ¶
type PolicyConfig struct { Path string Mode PolicyMode }
func (*PolicyConfig) IsEmpty ¶ added in v0.24.0
func (p *PolicyConfig) IsEmpty() bool
type PolicyMode ¶
type PolicyMode string
type PostgresConfig ¶
type PreAuthKey ¶
type PreAuthKey struct { ID uint64 `gorm:"primary_key"` Key string UserID uint User User `gorm:"constraint:OnDelete:CASCADE;"` Reusable bool Ephemeral bool `gorm:"default:false"` Used bool `gorm:"default:false"` Tags []string `gorm:"serializer:json"` CreatedAt *time.Time Expiration *time.Time }
PreAuthKey describes a pre-authorization key usable in a particular user.
func (*PreAuthKey) Proto ¶
func (key *PreAuthKey) Proto() *v1.PreAuthKey
type Route ¶
type Route struct { gorm.Model NodeID uint64 Node *Node // TODO(kradalby): change this custom type to netip.Prefix Prefix netip.Prefix `gorm:"serializer:text"` Advertised bool Enabled bool IsPrimary bool }
func (*Route) IsAnnouncable ¶
func (*Route) IsExitRoute ¶
type Routes ¶
type Routes []Route
type SqliteConfig ¶
type StateUpdate ¶
type StateUpdate struct { // The type of update Type StateUpdateType // ChangeNodes must be set when Type is StatePeerAdded // and StatePeerChanged and contains the full node // object for added nodes. ChangeNodes []NodeID // ChangePatches must be set when Type is StatePeerChangedPatch // and contains a populated PeerChange object. ChangePatches []*tailcfg.PeerChange // Removed must be set when Type is StatePeerRemoved and // contain a list of the nodes that has been removed from // the network. Removed []NodeID // DERPMap must be set when Type is StateDERPUpdated and // contain the new DERP Map. DERPMap *tailcfg.DERPMap // Additional message for tracking origin or what being // updated, useful for ambiguous updates like StatePeerChanged. Message string }
StateUpdate is an internal message containing information about a state change that has happened to the network. If type is StateFullUpdate, all fields are ignored.
func StateUpdateExpire ¶
func StateUpdateExpire(nodeID NodeID, expiry time.Time) StateUpdate
func (*StateUpdate) Empty ¶
func (su *StateUpdate) Empty() bool
Empty reports if there are any updates in the StateUpdate.
type StateUpdateType ¶
type StateUpdateType int
const ( StateFullUpdate StateUpdateType = iota // StatePeerChanged is used for updates that needs // to be calculated with all peers and all policy rules. // This would typically be things that include tags, routes // and similar. StatePeerChanged StatePeerChangedPatch StatePeerRemoved // StateSelfUpdate is used to indicate that the node // has changed in control, and the client needs to be // informed. // The updated node is inside the ChangeNodes field // which should have a length of one. StateSelfUpdate StateDERPUpdated )
func (StateUpdateType) String ¶
func (su StateUpdateType) String() string
type TLSConfig ¶
type TLSConfig struct { CertPath string KeyPath string LetsEncrypt LetsEncryptConfig }
type User ¶
type User struct { gorm.Model // Username for the user, is used if email is empty // Should not be used, please use Username(). Name string // Typically the full name of the user DisplayName string // Email of the user // Should not be used, please use Username(). Email string // Unique identifier of the user from OIDC, // comes from `sub` claim in the OIDC token // and is used to lookup the user. ProviderIdentifier sql.NullString // Provider is the origin of the user account, // same as RegistrationMethod, without authkey. Provider string ProfilePicURL string }
User is the way Headscale implements the concept of users in Tailscale
At the end of the day, users in Tailscale are some kind of 'bubbles' or users that contain our machines.
func (*User) DisplayNameOrUsername ¶ added in v0.24.0
DisplayNameOrUsername returns the DisplayName if it exists, otherwise it will return the Username.
func (*User) FromClaim ¶ added in v0.24.0
func (u *User) FromClaim(claims *OIDCClaims)
FromClaim overrides a User from OIDC claims. All fields will be updated, except for the ID.
func (*User) TailscaleLogin ¶
func (*User) TailscaleUser ¶
func (*User) TailscaleUserProfile ¶
func (u *User) TailscaleUserProfile() tailcfg.UserProfile
func (*User) Username ¶ added in v0.24.0
Username is the main way to get the username of a user, it will return the email if it exists, the name if it exists, the OIDCIdentifier if it exists, and the ID if nothing else exists. Email and OIDCIdentifier will be set when the user has headscale enabled with OIDC, which means that there is a domain involved which should be used throughout headscale, in information returned to the user and the Policy engine.