diff --git a/.goreleaser.yml b/.goreleaser.yml index e776b5a7..d4c12c88 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -20,6 +20,8 @@ builds: - -mod=readonly ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} + tags: + - ts2019 - id: darwin-arm64 main: ./cmd/headscale/headscale.go @@ -34,6 +36,8 @@ builds: - -mod=readonly ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} + tags: + - ts2019 - id: linux-amd64 mod_timestamp: "{{ .CommitTimestamp }}" @@ -46,6 +50,8 @@ builds: main: ./cmd/headscale/headscale.go ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} + tags: + - ts2019 - id: linux-arm64 mod_timestamp: "{{ .CommitTimestamp }}" @@ -58,6 +64,8 @@ builds: main: ./cmd/headscale/headscale.go ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} + tags: + - ts2019 archives: - id: golang-cross diff --git a/CHANGELOG.md b/CHANGELOG.md index d6836bf0..8eafa7f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - Remove `ip_prefix` configuration option and warning [#899](https://github.com/juanfont/headscale/pull/899) - Add `dns_config.override_local_dns` option [#905](https://github.com/juanfont/headscale/pull/905) - Fix some DNS config issues [#660](https://github.com/juanfont/headscale/issues/660) +- Make it possible to disable TS2019 with build flag [#928](https://github.com/juanfont/headscale/pull/928) ## 0.16.4 (2022-08-21) diff --git a/Dockerfile b/Dockerfile index 4a83c462..da2d07e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ RUN go mod download COPY . . -RUN CGO_ENABLED=0 GOOS=linux go install -ldflags="-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$VERSION" -a ./cmd/headscale +RUN CGO_ENABLED=0 GOOS=linux go install -tags ts2019 -ldflags="-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$VERSION" -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.debug b/Dockerfile.debug index a6003c64..7fbaef61 100644 --- a/Dockerfile.debug +++ b/Dockerfile.debug @@ -9,7 +9,7 @@ RUN go mod download COPY . . -RUN CGO_ENABLED=0 GOOS=linux go install -ldflags="-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$VERSION" -a ./cmd/headscale +RUN CGO_ENABLED=0 GOOS=linux go install -tags ts2019 -ldflags="-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$VERSION" -a ./cmd/headscale RUN test -e /go/bin/headscale # Debug image diff --git a/Makefile b/Makefile index bc5a9c4e..48ab8215 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,8 @@ ifeq ($(filter $(GOOS), openbsd netbsd soloaris plan9), ) else endif +TAGS = -tags ts2019 + # GO_SOURCES = $(wildcard *.go) # PROTO_SOURCES = $(wildcard **/*.proto) GO_SOURCES = $(call rwildcard,,*.go) @@ -17,12 +19,12 @@ PROTO_SOURCES = $(call rwildcard,,*.proto) build: - GOOS=$(GOOS) CGO_ENABLED=0 go build -trimpath $(pieflags) -mod=readonly -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go + nix build dev: lint test build test: - @go test -short -coverprofile=coverage.out ./... + @go test $(TAGS) -short -coverprofile=coverage.out ./... test_integration: test_integration_cli test_integration_derp test_integration_oidc test_integration_v2_general @@ -34,7 +36,7 @@ test_integration_cli: -v ~/.cache/hs-integration-go:/go \ -v $$PWD:$$PWD -w $$PWD \ -v /var/run/docker.sock:/var/run/docker.sock golang:1 \ - go test -failfast -timeout 30m -count=1 -run IntegrationCLI ./... + go test $(TAGS) -failfast -timeout 30m -count=1 -run IntegrationCLI ./... test_integration_derp: docker network rm $$(docker network ls --filter name=headscale --quiet) || true @@ -44,7 +46,7 @@ test_integration_derp: -v ~/.cache/hs-integration-go:/go \ -v $$PWD:$$PWD -w $$PWD \ -v /var/run/docker.sock:/var/run/docker.sock golang:1 \ - go test -failfast -timeout 30m -count=1 -run IntegrationDERP ./... + go test $(TAGS) -failfast -timeout 30m -count=1 -run IntegrationDERP ./... test_integration_oidc: docker network rm $$(docker network ls --filter name=headscale --quiet) || true @@ -54,7 +56,7 @@ test_integration_oidc: -v ~/.cache/hs-integration-go:/go \ -v $$PWD:$$PWD -w $$PWD \ -v /var/run/docker.sock:/var/run/docker.sock golang:1 \ - go test -failfast -timeout 30m -count=1 -run IntegrationOIDC ./... + go test $(TAGS) -failfast -timeout 30m -count=1 -run IntegrationOIDC ./... test_integration_v2_general: docker run \ @@ -64,7 +66,7 @@ test_integration_v2_general: -v $$PWD:$$PWD -w $$PWD/integration \ -v /var/run/docker.sock:/var/run/docker.sock \ golang:1 \ - go test ./... -timeout 60m -parallel 6 + go test $(TAGS) -failfast ./... -timeout 60m -parallel 6 test_integration_v2_auth_web_flow: diff --git a/app.go b/app.go index 38807c72..7a67e4a3 100644 --- a/app.go +++ b/app.go @@ -454,9 +454,8 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *mux.Router { router.HandleFunc("/health", h.HealthHandler).Methods(http.MethodGet) router.HandleFunc("/key", h.KeyHandler).Methods(http.MethodGet) router.HandleFunc("/register/{nkey}", h.RegisterWebAPI).Methods(http.MethodGet) - router.HandleFunc("/machine/{mkey}/map", h.PollNetMapHandler). - Methods(http.MethodPost) - router.HandleFunc("/machine/{mkey}", h.RegistrationHandler).Methods(http.MethodPost) + h.addLegacyHandlers(router) + router.HandleFunc("/oidc/register/{nkey}", h.RegisterOIDC).Methods(http.MethodGet) router.HandleFunc("/oidc/callback", h.OIDCCallback).Methods(http.MethodGet) router.HandleFunc("/apple", h.AppleConfigMessage).Methods(http.MethodGet) diff --git a/flake.nix b/flake.nix index 7b6c7866..595c8dc6 100644 --- a/flake.nix +++ b/flake.nix @@ -26,6 +26,8 @@ version = headscaleVersion; src = pkgs.lib.cleanSource self; + tags = ["ts2019"]; + # Only run unit tests when testing a build checkFlags = ["-short"]; @@ -135,7 +137,7 @@ buildInputs = devDeps; shellHook = '' - export GOFLAGS=-tags="integration,integration_general,integration_oidc,integration_cli,integration_derp" + export GOFLAGS=-tags="ts2019" ''; }; diff --git a/handler_legacy.go b/handler_legacy.go new file mode 100644 index 00000000..8911d430 --- /dev/null +++ b/handler_legacy.go @@ -0,0 +1,15 @@ +//go:build ts2019 + +package headscale + +import ( + "net/http" + + "github.com/gorilla/mux" +) + +func (h *Headscale) addLegacyHandlers(router *mux.Router) { + router.HandleFunc("/machine/{mkey}/map", h.PollNetMapHandler). + Methods(http.MethodPost) + router.HandleFunc("/machine/{mkey}", h.RegistrationHandler).Methods(http.MethodPost) +} diff --git a/handler_placeholder.go b/handler_placeholder.go new file mode 100644 index 00000000..25fe9c65 --- /dev/null +++ b/handler_placeholder.go @@ -0,0 +1,8 @@ +//go:build !ts2019 + +package headscale + +import "github.com/gorilla/mux" + +func (h *Headscale) addLegacyHandlers(router *mux.Router) { +} 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/protocol_legacy.go b/protocol_legacy.go index 4e75d127..f636c175 100644 --- a/protocol_legacy.go +++ b/protocol_legacy.go @@ -1,3 +1,5 @@ +//go:build ts2019 + package headscale import ( diff --git a/protocol_legacy_poll.go b/protocol_legacy_poll.go index f27ee4e3..a8d9343a 100644 --- a/protocol_legacy_poll.go +++ b/protocol_legacy_poll.go @@ -1,3 +1,5 @@ +//go:build ts2019 + package headscale import ( 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())