diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f0902132..d989a84c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,6 +6,8 @@ labels: ["bug"] assignees: "" --- + + **Bug description** + **Feature request** diff --git a/.github/ISSUE_TEMPLATE/other_issue.md b/.github/ISSUE_TEMPLATE/other_issue.md index 76811e67..3004a97c 100644 --- a/.github/ISSUE_TEMPLATE/other_issue.md +++ b/.github/ISSUE_TEMPLATE/other_issue.md @@ -6,6 +6,8 @@ labels: ["bug"] assignees: "" --- + + **Issue description** diff --git a/.gitignore b/.gitignore index d047cbfd..5556580d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ derp.yaml .idea test_output/ + +# Nix and direnv +.direnv/ +result diff --git a/CHANGELOG.md b/CHANGELOG.md index d3aa8d53..359ace64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,9 @@ ### Changes +- Headscale fails to serve if the ACL policy file cannot be parsed [#537](https://github.com/juanfont/headscale/pull/537) - Fix labels cardinality error when registering unknown pre-auth key [#519](https://github.com/juanfont/headscale/pull/519) +- Fix send on closed channel crash in polling [#542](https://github.com/juanfont/headscale/pull/542) ## 0.15.0 (2022-03-20) diff --git a/Makefile b/Makefile index 66d9ed81..35338ac8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Calculate version -version = $(shell ./scripts/version-at-commit.sh) +version = $(git describe --always --tags --dirty) rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) @@ -10,7 +10,7 @@ PROTO_SOURCES = $(call rwildcard,,*.proto) build: - GGO_ENABLED=0 go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go + CGO_ENABLED=0 go build -trimpath -buildmode=pie -mod=readonly -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go dev: lint test build diff --git a/README.md b/README.md index 74abc85b..b64482d1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An open source, self-hosted implementation of the Tailscale control server. -Join our [Discord](https://discord.gg/XcQxk2VHjx) server for a chat. +Join our [Discord](https://discord.gg/c84AZQhmpx) server for a chat. **Note:** Always select the same GitHub tag as the released version you use to ensure you have the correct example configuration and documentation. @@ -206,6 +206,13 @@ make build Alessandro (Ale) Segala + + + Nico/ +
+ Nico +
+ unreality/ @@ -214,10 +221,10 @@ make build - - Nico/ + + Moritz
- Nico + Moritz Poldrack
@@ -227,6 +234,8 @@ make build Niek van der Maas + + Eugen @@ -234,8 +243,6 @@ make build Eugen Biegler - - Aaron @@ -271,6 +278,8 @@ make build Michael G. + + Paul @@ -278,8 +287,6 @@ make build Paul Tötterman - - Artem @@ -315,6 +322,8 @@ make build lachy2849 + + thomas/ @@ -322,8 +331,6 @@ make build thomas - - Abraham @@ -359,6 +366,8 @@ make build Carson Yang + + Felix @@ -366,8 +375,6 @@ make build Felix Kronlage-Dammers - - Felix @@ -403,6 +410,8 @@ make build Pierre Carru + + rcursaru/ @@ -410,8 +419,6 @@ make build rcursaru - - WhiteSource @@ -447,6 +454,8 @@ make build Teteros + + The @@ -454,8 +463,6 @@ make build The Gitter Badger - - Tianon @@ -491,6 +498,8 @@ make build ZiYuan + + bravechamp/ @@ -498,8 +507,6 @@ make build bravechamp - - derelm/ @@ -535,6 +542,8 @@ make build pernila + + Wakeful-Cloud/ @@ -542,8 +551,6 @@ make build Wakeful-Cloud - - zy/ diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 768a9713..992d1254 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -408,7 +408,7 @@ func getHeadscaleApp() (*headscale.Headscale, error) { aclPath := absPath(viper.GetString("acl_policy_path")) err = app.LoadACLPolicy(aclPath) if err != nil { - log.Error(). + log.Fatal(). Str("path", aclPath). Err(err). Msg("Could not load the ACL policy") diff --git a/docs/README.md b/docs/README.md index 7a3080e3..459a6c21 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@ This page contains the official and community contributed documentation for `headscale`. If you are having trouble with following the documentation or get unexpected results, -please ask on [Discord](https://discord.gg/XcQxk2VHjx) instead of opening an Issue. +please ask on [Discord](https://discord.gg/c84AZQhmpx) instead of opening an Issue. ## Official documentation diff --git a/docs/running-headscale-linux.md b/docs/running-headscale-linux.md index 98a67f1d..89d02e87 100644 --- a/docs/running-headscale-linux.md +++ b/docs/running-headscale-linux.md @@ -30,6 +30,14 @@ mkdir -p /etc/headscale # Directory for Database, and other variable data (like certificates) mkdir -p /var/lib/headscale +# or if you create a headscale user: +useradd \ + --create-home \ + --home-dir /var/lib/headscale/ \ + --system \ + --user-group \ + --shell /usr/bin/nologin \ + headscale ``` 4. Create an empty SQLite database: @@ -50,7 +58,7 @@ from the [headscale repository](../) 6. Start the headscale server: ```shell - headscale serve +headscale serve ``` This command will start `headscale` in the current terminal session. @@ -150,7 +158,7 @@ or run all headscale commands as the headscale user: su - headscale ``` -2. In `/etc/headscale/config.yaml`, override the default `headscale` unix socket with a SystemD friendly path: +2. In `/etc/headscale/config.yaml`, override the default `headscale` unix socket with path that is writable by the `headscale` user or group: ```yaml unix_socket: /var/run/headscale/headscale.sock @@ -165,8 +173,7 @@ systemctl daemon-reload 4. Enable and start the new `headscale` service: ```shell -systemctl enable headscale -systemctl start headscale +systemctl enable --now headscale ``` 5. Verify the headscale service: diff --git a/poll.go b/poll.go index 15945a9b..3bad0b89 100644 --- a/poll.go +++ b/poll.go @@ -175,32 +175,13 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Loading or creating update channel") - // TODO: could probably remove all that duplication once generics land. - closeChanWithLog := func(channel interface{}, name string) { - log.Trace(). - Str("handler", "PollNetMap"). - Str("machine", machine.Name). - Str("channel", "Done"). - Msg(fmt.Sprintf("Closing %s channel", name)) - - switch c := channel.(type) { - case (chan struct{}): - close(c) - - case (chan []byte): - close(c) - } - } - const chanSize = 8 updateChan := make(chan struct{}, chanSize) - defer closeChanWithLog(updateChan, "updateChan") pollDataChan := make(chan []byte, chanSize) - defer closeChanWithLog(pollDataChan, "pollDataChan") + defer closeChanWithLog(pollDataChan, machine.Name, "pollDataChan") keepAliveChan := make(chan []byte) - defer closeChanWithLog(keepAliveChan, "keepAliveChan") if req.OmitPeers && !req.Stream { log.Info(). @@ -273,7 +254,27 @@ func (h *Headscale) PollNetMapStream( updateChan chan struct{}, ) { { - ctx, cancel := context.WithCancel(ctx.Request.Context()) + machine, err := h.GetMachineByMachineKey(machineKey) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Warn(). + Str("handler", "PollNetMap"). + Msgf("Ignoring request, cannot find machine with key %s", machineKey.String()) + ctx.String(http.StatusUnauthorized, "") + + return + } + log.Error(). + Str("handler", "PollNetMap"). + Msgf("Failed to fetch machine from the database with Machine key: %s", machineKey.String()) + ctx.String(http.StatusInternalServerError, "") + + return + } + + ctx := context.WithValue(ctx.Request.Context(), "machineName", machine.Name) + + ctx, cancel := context.WithCancel(ctx) defer cancel() go h.scheduledPollWorker( @@ -564,8 +565,8 @@ func (h *Headscale) PollNetMapStream( func (h *Headscale) scheduledPollWorker( ctx context.Context, - updateChan chan<- struct{}, - keepAliveChan chan<- []byte, + updateChan chan struct{}, + keepAliveChan chan []byte, machineKey key.MachinePublic, mapRequest tailcfg.MapRequest, machine *Machine, @@ -573,6 +574,17 @@ func (h *Headscale) scheduledPollWorker( keepAliveTicker := time.NewTicker(keepAliveInterval) updateCheckerTicker := time.NewTicker(updateCheckInterval) + defer closeChanWithLog( + updateChan, + fmt.Sprint(ctx.Value("machineName")), + "updateChan", + ) + defer closeChanWithLog( + keepAliveChan, + fmt.Sprint(ctx.Value("machineName")), + "updateChan", + ) + for { select { case <-ctx.Done(): @@ -606,3 +618,13 @@ func (h *Headscale) scheduledPollWorker( } } } + +func closeChanWithLog[C chan []byte | chan struct{}](channel C, machine, name string) { + log.Trace(). + Str("handler", "PollNetMap"). + Str("machine", machine). + Str("channel", "Done"). + Msg(fmt.Sprintf("Closing %s channel", name)) + + close(channel) +} diff --git a/scripts/version-at-commit.sh b/scripts/version-at-commit.sh deleted file mode 100755 index 2f7fab84..00000000 --- a/scripts/version-at-commit.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -set -e -o pipefail -commit="$1" -versionglob="v[0-9].[0-9]*.[0-9]*" -devsuffix=".dev" -if [ -z "$commit" ]; then - commit=`git log -n1 --first-parent "--format=format:%h"` -fi - -# automatically assign version -# -# handles the following cases: -# -# 0. no tags on the repository. Print "dev". -# -# 1. no local modifications and commit is directly tagged. Print tag. -# -# 2. no local modifications and commit is not tagged. Take greatest version tag in repo X.Y.Z and assign X.Y.(Z+1). Print that + $devsuffix + $timestamp. -# -# 3. local modifications. Print "dev". - -tags=$(git tag) -if [[ -z "$tags" ]]; then - echo "dev" -elif `git diff --quiet 2>/dev/null`; then - tagged=$(git tag --points-at "$commit") - if [[ -n "$tagged" ]] ; then - echo $tagged - else - nearest_tag=$(git describe --tags --abbrev=0 --match "$versionglob" "$commit") - v=$(echo $nearest_tag | perl -pe 's/(\d+)$/$1+1/e') - isodate=$(TZ=UTC git log -n1 --format=%cd --date=iso "$commit") - ts=$(TZ=UTC date --date="$isodate" "+%Y%m%d%H%M%S") - echo "${v}${devsuffix}${ts}" - fi -else - echo "dev" -fi