@ -17,6 +17,7 @@ package envknob
import (
"bufio"
"errors"
"fmt"
"io"
"log"
@ -503,7 +504,7 @@ func ApplyDiskConfigError() error { return applyDiskConfigErr }
//
// On macOS, use one of:
//
// - ~/Library/Containers/io.tailscale.ipn.macsys /Data/tailscaled-env.txt
// - /private/var/root/Library/Containers/io.tailscale.ipn.macsys.network-extension /Data/tailscaled-env.txt
// for standalone macOS GUI builds
// - ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data/tailscaled-env.txt
// for App Store builds
@ -533,44 +534,73 @@ func ApplyDiskConfig() (err error) {
return applyKeyValueEnv ( f )
}
name := getPlatformEnvFile ( )
if name == "" {
name s := getPlatformEnvFile s ( )
if len ( names ) == 0 {
return nil
}
f , err = os . Open ( name )
if os . IsNotExist ( err ) {
return nil
}
if err != nil {
return err
var errs [ ] error
for _ , name := range names {
f , err = os . Open ( name )
if os . IsNotExist ( err ) {
continue
}
if err != nil {
errs = append ( errs , err )
continue
}
defer f . Close ( )
return applyKeyValueEnv ( f )
}
defer f . Close ( )
return applyKeyValueEnv ( f )
// If we have any errors, return them; if all errors are such that
// os.IsNotExist(err) returns true, then errs is empty and we will
// return nil.
return errors . Join ( errs ... )
}
// getPlatformEnvFile returns the current platform's path to an optional
// tailscaled-env.txt file. It returns an empty string if none is defined
// for the platform.
func getPlatformEnvFile ( ) string {
// getPlatformEnvFile s returns a list of paths to the current platform's
// optional tailscaled-env.txt file. It returns an empty li st if none is
// defined for the platform.
func getPlatformEnvFile s ( ) [ ] string {
switch runtime . GOOS {
case "windows" :
return filepath . Join ( os . Getenv ( "ProgramData" ) , "Tailscale" , "tailscaled-env.txt" )
return [ ] string {
filepath . Join ( os . Getenv ( "ProgramData" ) , "Tailscale" , "tailscaled-env.txt" ) ,
}
case "linux" :
if distro . Get ( ) == distro . Synology {
return "/etc/tailscale/tailscaled-env.txt"
return [ ] string { "/etc/tailscale/tailscaled-env.txt" }
}
case "darwin" :
if version . IsSandboxedMacOS ( ) { // the two GUI variants (App Store or separate download)
// This will be user-visible as ~/Library/Containers/$VARIANT/Data/tailscaled-env.txt
// where $VARIANT is "io.tailscale.ipn.macsys" for macsys (downloadable mac GUI builds)
// or "io.tailscale.ipn.macos.network-extension" for App Store builds.
return filepath . Join ( os . Getenv ( "HOME" ) , "tailscaled-env.txt" )
// On the App Store variant, the home directory is set
// to something like:
// ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data
//
// On the macsys (downloadable Mac GUI) variant, the
// home directory can be unset, but we have a working
// directory that looks like:
// /private/var/root/Library/Containers/io.tailscale.ipn.macsys.network-extension/Data
//
// Try both and see if we can find the file in either
// location.
var candidates [ ] string
if home := os . Getenv ( "HOME" ) ; home != "" {
candidates = append ( candidates , filepath . Join ( home , "tailscaled-env.txt" ) )
}
if wd , err := os . Getwd ( ) ; err == nil {
candidates = append ( candidates , filepath . Join ( wd , "tailscaled-env.txt" ) )
}
return candidates
} else {
// Open source / homebrew variable, running tailscaled-on-macOS.
return "/etc/tailscale/tailscaled-env.txt"
return [ ] string { "/etc/tailscale/tailscaled-env.txt" }
}
}
return ""
return nil
}
// applyKeyValueEnv reads key=value lines r and calls Setenv for each.