paths.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package paths returns platform and user-specific default paths to
  4. // Tailscale files and directories.
  5. package paths
  6. import (
  7. "log"
  8. "os"
  9. "path/filepath"
  10. "runtime"
  11. "tailscale.com/syncs"
  12. "tailscale.com/version/distro"
  13. )
  14. // AppSharedDir is a string set by the iOS or Android app on start
  15. // containing a directory we can read/write in.
  16. var AppSharedDir syncs.AtomicValue[string]
  17. // DefaultTailscaledSocket returns the path to the tailscaled Unix socket
  18. // or the empty string if there's no reasonable default.
  19. func DefaultTailscaledSocket() string {
  20. if runtime.GOOS == "windows" {
  21. return `\\.\pipe\ProtectedPrefix\Administrators\Tailscale\tailscaled`
  22. }
  23. if runtime.GOOS == "darwin" {
  24. return "/var/run/tailscaled.socket"
  25. }
  26. if runtime.GOOS == "plan9" {
  27. return "/srv/tailscaled.sock"
  28. }
  29. switch distro.Get() {
  30. case distro.Synology:
  31. if distro.DSMVersion() == 6 {
  32. return "/var/packages/Tailscale/etc/tailscaled.sock"
  33. }
  34. // DSM 7 (and higher? or failure to detect.)
  35. return "/var/packages/Tailscale/var/tailscaled.sock"
  36. case distro.Gokrazy:
  37. return "/perm/tailscaled/tailscaled.sock"
  38. case distro.QNAP:
  39. return "/tmp/tailscale/tailscaled.sock"
  40. }
  41. if fi, err := os.Stat("/var/run"); err == nil && fi.IsDir() {
  42. return "/var/run/tailscale/tailscaled.sock"
  43. }
  44. return "tailscaled.sock"
  45. }
  46. // Overridden in init by OS-specific files.
  47. var (
  48. stateFileFunc func() string
  49. // ensureStateDirPerms applies a restrictive ACL/chmod
  50. // to the provided directory.
  51. ensureStateDirPerms = func(string) error { return nil }
  52. )
  53. // DefaultTailscaledStateFile returns the default path to the
  54. // tailscaled state file, or the empty string if there's no reasonable
  55. // default value.
  56. func DefaultTailscaledStateFile() string {
  57. if f := stateFileFunc; f != nil {
  58. return f()
  59. }
  60. if runtime.GOOS == "windows" {
  61. return filepath.Join(os.Getenv("ProgramData"), "Tailscale", "server-state.conf")
  62. }
  63. return ""
  64. }
  65. // DefaultTailscaledStateDir returns the default state directory
  66. // to use for tailscaled, for use when the user provided neither
  67. // a state directory or state file path to use.
  68. //
  69. // It returns the empty string if there's no reasonable default.
  70. func DefaultTailscaledStateDir() string {
  71. if runtime.GOOS == "plan9" {
  72. home, err := os.UserHomeDir()
  73. if err != nil {
  74. log.Fatalf("failed to get home directory: %v", err)
  75. }
  76. return filepath.Join(home, "tailscale-state")
  77. }
  78. return filepath.Dir(DefaultTailscaledStateFile())
  79. }
  80. // MakeAutomaticStateDir reports whether the platform
  81. // automatically creates the state directory for tailscaled
  82. // when it's absent.
  83. func MakeAutomaticStateDir() bool {
  84. switch runtime.GOOS {
  85. case "plan9":
  86. return true
  87. case "linux":
  88. if distro.Get() == distro.JetKVM {
  89. return true
  90. }
  91. }
  92. return false
  93. }
  94. // MkStateDir ensures that dirPath, the daemon's configuration directory
  95. // containing machine keys etc, both exists and has the correct permissions.
  96. // We want it to only be accessible to the user the daemon is running under.
  97. func MkStateDir(dirPath string) error {
  98. if err := os.MkdirAll(dirPath, 0700); err != nil {
  99. return err
  100. }
  101. return ensureStateDirPerms(dirPath)
  102. }
  103. // LegacyStateFilePath returns the legacy path to the state file when
  104. // it was stored under the current user's %LocalAppData%.
  105. //
  106. // It is only called on Windows.
  107. func LegacyStateFilePath() string {
  108. if runtime.GOOS == "windows" {
  109. return filepath.Join(os.Getenv("LocalAppData"), "Tailscale", "server-state.conf")
  110. }
  111. return ""
  112. }