envknob: support disk-based envknobs on the macsys build

Per my investigation just now, the $HOME environment variable is unset
on the macsys (standalone macOS GUI) variant, but the current working
directory is valid. Look for the environment variable file in that
location in addition to inside the home directory.

Updates #3707

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I481ae2e0d19b316244373e06865e3b5c3a9f3b88
pull/13693/head
Andrew Dunham 2 months ago
parent 4ad3f01225
commit 12f1bc7c77

@ -17,6 +17,7 @@ package envknob
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -503,7 +504,7 @@ func ApplyDiskConfigError() error { return applyDiskConfigErr }
// //
// On macOS, use one of: // 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 // for standalone macOS GUI builds
// - ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data/tailscaled-env.txt // - ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data/tailscaled-env.txt
// for App Store builds // for App Store builds
@ -533,44 +534,73 @@ func ApplyDiskConfig() (err error) {
return applyKeyValueEnv(f) return applyKeyValueEnv(f)
} }
name := getPlatformEnvFile() names := getPlatformEnvFiles()
if name == "" { if len(names) == 0 {
return nil return nil
} }
f, err = os.Open(name)
if os.IsNotExist(err) { var errs []error
return nil for _, name := range names {
} f, err = os.Open(name)
if err != nil { if os.IsNotExist(err) {
return 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 // getPlatformEnvFiles returns a list of paths to the current platform's
// tailscaled-env.txt file. It returns an empty string if none is defined // optional tailscaled-env.txt file. It returns an empty list if none is
// for the platform. // defined for the platform.
func getPlatformEnvFile() string { func getPlatformEnvFiles() []string {
switch runtime.GOOS { switch runtime.GOOS {
case "windows": 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": case "linux":
if distro.Get() == distro.Synology { if distro.Get() == distro.Synology {
return "/etc/tailscale/tailscaled-env.txt" return []string{"/etc/tailscale/tailscaled-env.txt"}
} }
case "darwin": case "darwin":
if version.IsSandboxedMacOS() { // the two GUI variants (App Store or separate download) 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 // On the App Store variant, the home directory is set
// where $VARIANT is "io.tailscale.ipn.macsys" for macsys (downloadable mac GUI builds) // to something like:
// or "io.tailscale.ipn.macos.network-extension" for App Store builds. // ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data
return filepath.Join(os.Getenv("HOME"), "tailscaled-env.txt") //
// 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 { } else {
// Open source / homebrew variable, running tailscaled-on-macOS. // 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. // applyKeyValueEnv reads key=value lines r and calls Setenv for each.

Loading…
Cancel
Save