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(` - -
-- 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.
-
-
You should always download and inspect the registry file before installing it:
-curl {{.URL}}/windows/tailscale.reg
-
- Headscale can be set to the default server by running the registry file:
- - - -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(` - -
-- 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.
-
You should always download and inspect the profile before installing it:
- -curl {{.URL}}/apple/macos
-
- Headscale can be set to the default server by installing a Headscale configuration profile:
-- macOS profile -
- -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(`+ This page provides + + configuration profiles + + for the official Tailscale clients for +
+
+ The profiles will configure Tailscale.app to use {{.URL}}
as
+ its control server.
+
+ You should always download and inspect the profile before installing it: +
+ +curl {{.URL}}/apple/macos
+
+ + Headscale can be set to the default server by installing a Headscale + configuration profile: +
++ macOS AppStore profile + macOS Standalone profile +
+ +Or
++ Use your terminal to configure the default setting for Tailscale by + issuing: +
+defaults write io.tailscale.ipn.macos ControlURL {{.URL}}
+ defaults write io.tailscale.ipn.macsys ControlURL {{.URL}}
+ 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 @@ + + + + + + ++ 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.
+
+ You should always download and inspect the registry file before installing + it: +
+curl {{.URL}}/windows/tailscale.reg
+
+ + Headscale can be set to the default server by running the registry file: +
+ + + +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())