diff --git a/platform_config.go b/platform_config.go index 7bceb0c9..eb11084f 100644 --- a/platform_config.go +++ b/platform_config.go @@ -2,6 +2,7 @@ package headscale import ( "bytes" + _ "embed" "html/template" "net/http" textTemplate "text/template" @@ -11,51 +12,18 @@ import ( "github.com/rs/zerolog/log" ) +//go:embed templates/apple.html +var appleTemplate string + +//go:embed templates/windows.html +var windowsTemplate string + // WindowsConfigMessage shows a simple message in the browser for how to configure the Windows Tailscale client. func (h *Headscale) WindowsConfigMessage( writer http.ResponseWriter, req *http.Request, ) { - winTemplate := template.Must(template.New("windows").Parse(` - - -

headscale

-

Windows registry configuration

-

- This page provides Windows registry information for the official Windows Tailscale client. -

-

- The registry file will configure Tailscale to use {{.URL}} as its control server. -

-

Caution

-

You should always download and inspect the registry file before installing it:

-
curl {{.URL}}/windows/tailscale.reg
- -

Installation

-

Headscale can be set to the default server by running the registry file:

- -

- Windows registry file -

- -
    -
  1. Download the registry file, then run it
  2. -
  3. Follow the prompts
  4. -
  5. Install and run the official windows Tailscale client
  6. -
  7. When the installation has finished, start Tailscale, and log in by clicking the icon in the system tray
  8. -
-

Or

-

Open command prompt with Administrator rights. Issue the following commands to add the required registry entries:

-
-REG ADD "HKLM\Software\Tailscale IPN" /v UnattendedMode /t REG_SZ /d always
-REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}"
-

- Restart Tailscale and log in. -

- - -`)) - + winTemplate := template.Must(template.New("windows").Parse(windowsTemplate)) config := map[string]interface{}{ "URL": h.cfg.ServerURL, } @@ -136,55 +104,7 @@ func (h *Headscale) AppleConfigMessage( writer http.ResponseWriter, req *http.Request, ) { - appleTemplate := template.Must(template.New("apple").Parse(` - - -

headscale

-

Apple configuration profiles

-

- This page provides configuration profiles for the official Tailscale clients for iOS and macOS. -

-

- The profiles will configure Tailscale.app to use {{.URL}} as its control server. -

- -

Caution

-

You should always download and inspect the profile before installing it:

- -
curl {{.URL}}/apple/macos
- -

Profiles

- - - -

macOS

-

Headscale can be set to the default server by installing a Headscale configuration profile:

-

- macOS profile -

- -
    -
  1. Download the profile, then open it. When it has been opened, there should be a notification that a profile can be installed
  2. -
  3. Open System Preferences and go to "Profiles"
  4. -
  5. Find and install the Headscale profile
  6. -
  7. Restart Tailscale.app and log in
  8. -
- -

Or

-

Use your terminal to configure the default setting for Tailscale by issuing:

- defaults write io.tailscale.ipn.macos ControlURL {{.URL}} - -

Restart Tailscale.app and log in.

- - -`)) + appleTemplate := template.Must(template.New("apple").Parse(appleTemplate)) config := map[string]interface{}{ "URL": h.cfg.ServerURL, @@ -282,24 +202,33 @@ func (h *Headscale) ApplePlatformConfig( } var payload bytes.Buffer + handleMacError := func(ierr error) { + log.Error(). + Str("handler", "ApplePlatformConfig"). + Err(ierr). + Msg("Could not render Apple macOS template") + + writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + writer.WriteHeader(http.StatusInternalServerError) + _, err := writer.Write([]byte("Could not render Apple macOS template")) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Failed to write response") + } + } switch platform { - case "macos": - if err := macosTemplate.Execute(&payload, platformConfig); err != nil { - log.Error(). - Str("handler", "ApplePlatformConfig"). - Err(err). - Msg("Could not render Apple macOS template") + case "macos-standlone": + if err := macosStandloneTemplate.Execute(&payload, platformConfig); err != nil { + handleMacError(err) - writer.Header().Set("Content-Type", "text/plain; charset=utf-8") - writer.WriteHeader(http.StatusInternalServerError) - _, err := writer.Write([]byte("Could not render Apple macOS template")) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Failed to write response") - } + return + } + case "macos-app-store": + if err := macosAppStoreTemplate.Execute(&payload, platformConfig); err != nil { + handleMacError(err) return } @@ -444,7 +373,7 @@ var iosTemplate = textTemplate.Must(textTemplate.New("iosTemplate").Parse(` `)) -var macosTemplate = template.Must(template.New("macosTemplate").Parse(` +var macosAppStoreTemplate = template.Must(template.New("macosTemplate").Parse(` PayloadType io.tailscale.ipn.macos @@ -456,7 +385,23 @@ var macosTemplate = template.Must(template.New("macosTemplate").Parse(` 1 PayloadEnabled - + ControlURL + {{.URL}} + +`)) + +var macosStandloneTemplate = template.Must(template.New("macosStandloneTemplate").Parse(` + + PayloadType + io.tailscale.ipn.macsys + PayloadUUID + {{.UUID}} + PayloadIdentifier + com.github.juanfont.headscale + PayloadVersion + 1 + PayloadEnabled + ControlURL {{.URL}} diff --git a/templates/apple.html b/templates/apple.html new file mode 100644 index 00000000..d21ff276 --- /dev/null +++ b/templates/apple.html @@ -0,0 +1,102 @@ + + + + + + + Document + + + +

headscale

+

Apple configuration profiles

+

+ This page provides + + configuration profiles + + for the official Tailscale clients for +

+ +

+ The profiles will configure Tailscale.app to use {{.URL}} as + its control server. +

+ +

Caution

+

+ You should always download and inspect the profile before installing it: +

+ +
curl {{.URL}}/apple/macos
+ +

Profiles

+ + + +

macOS

+

+ Headscale can be set to the default server by installing a Headscale + configuration profile: +

+

+ macOS AppStore profile + macOS Standalone profile +

+ +
    +
  1. + Download the profile, then open it. When it has been opened, there + should be a notification that a profile can be installed +
  2. +
  3. Open System Preferences and go to "Profiles"
  4. +
  5. Find and install the Headscale profile
  6. +
  7. Restart Tailscale.app and log in
  8. +
+ +

Or

+

+ Use your terminal to configure the default setting for Tailscale by + issuing: +

+ + +

Restart Tailscale.app and log in.

+ + diff --git a/templates/windows.html b/templates/windows.html new file mode 100644 index 00000000..5e13a72c --- /dev/null +++ b/templates/windows.html @@ -0,0 +1,64 @@ + + + + + + + Document + + + +

headscale

+

Windows registry configuration

+

+ This page provides Windows registry information for the official Windows + Tailscale client. +

+ +

+

+ The registry file will configure Tailscale to use {{.URL}} as + its control server. +

+ +

+

Caution

+

+ You should always download and inspect the registry file before installing + it: +

+
curl {{.URL}}/windows/tailscale.reg
+ +

Installation

+

+ Headscale can be set to the default server by running the registry file: +

+ +

+ Windows registry file +

+ +
    +
  1. Download the registry file, then run it
  2. +
  3. Follow the prompts
  4. +
  5. Install and run the official windows Tailscale client
  6. +
  7. + When the installation has finished, start Tailscale, and log in by + clicking the icon in the system tray +
  8. +
+

Or

+

+ Open command prompt with Administrator rights. Issue the following + commands to add the required registry entries: +

+
+REG ADD "HKLM\Software\Tailscale IPN" /v UnattendedMode /t REG_SZ /d always
+REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}"
+

Restart Tailscale and log in.

+ +

+ + diff --git a/utils.go b/utils.go index fc1fafa2..c0599c99 100644 --- a/utils.go +++ b/utils.go @@ -347,7 +347,7 @@ func IsStringInSlice(slice []string, str string) bool { } func AbsolutePathFromConfigPath(path string) string { - // If a relative path is provided, prefix it with the the directory where + // If a relative path is provided, prefix it with the directory where // the config file was found. if (path != "") && !strings.HasPrefix(path, string(os.PathSeparator)) { dir, _ := filepath.Split(viper.ConfigFileUsed())