mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/main' into ipv6
This commit is contained in:
		
						commit
						c0c3b7d511
					
				
							
								
								
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -18,7 +18,7 @@ jobs: | |||||||
|       - name: Setup Go |       - name: Setup Go | ||||||
|         uses: actions/setup-go@v2 |         uses: actions/setup-go@v2 | ||||||
|         with: |         with: | ||||||
|           go-version: "1.17.3" |           go-version: "1.17" | ||||||
| 
 | 
 | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         run: | |         run: | | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							| @ -14,6 +14,12 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           version: latest |           version: latest | ||||||
| 
 | 
 | ||||||
|  |           # Only block PRs on new problems. | ||||||
|  |           # If this is not enabled, we will end up having PRs | ||||||
|  |           # blocked because new linters has appared and other | ||||||
|  |           # parts of the code is affected. | ||||||
|  |           only-new-issues: true | ||||||
|  | 
 | ||||||
|   prettier-lint: |   prettier-lint: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.github/workflows/test-integration.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/test-integration.yml
									
									
									
									
										vendored
									
									
								
							| @ -17,7 +17,7 @@ jobs: | |||||||
|       - name: Setup Go |       - name: Setup Go | ||||||
|         uses: actions/setup-go@v2 |         uses: actions/setup-go@v2 | ||||||
|         with: |         with: | ||||||
|           go-version: "1.17.3" |           go-version: "1.17" | ||||||
| 
 | 
 | ||||||
|       - name: Run Integration tests |       - name: Run Integration tests | ||||||
|         run: go test -tags integration -timeout 30m |         run: go test -tags integration -timeout 30m | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @ -17,7 +17,7 @@ jobs: | |||||||
|       - name: Setup Go |       - name: Setup Go | ||||||
|         uses: actions/setup-go@v2 |         uses: actions/setup-go@v2 | ||||||
|         with: |         with: | ||||||
|           go-version: "1.17.3" # The Go version to download (if necessary) and use. |           go-version: "1.17" # The Go version to download (if necessary) and use. | ||||||
| 
 | 
 | ||||||
|       # Install all the dependencies |       # Install all the dependencies | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|  | |||||||
| @ -2,6 +2,9 @@ | |||||||
| 
 | 
 | ||||||
| **TBD (TBD):** | **TBD (TBD):** | ||||||
| 
 | 
 | ||||||
|  | - Fixed issue where hosts deleted from control server may be written back to the database, as long as they are connected to the control server [#278](https://github.com/juanfont/headscale/pull/278) | ||||||
|  |   ) | ||||||
|  | 
 | ||||||
| **0.12.3 (2022-01-13):** | **0.12.3 (2022-01-13):** | ||||||
| 
 | 
 | ||||||
| **Changes**: | **Changes**: | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ RUN go mod download | |||||||
| COPY . . | COPY . . | ||||||
| 
 | 
 | ||||||
| RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale | RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale | ||||||
|  | RUN strip /go/bin/headscale | ||||||
| RUN test -e /go/bin/headscale | RUN test -e /go/bin/headscale | ||||||
| 
 | 
 | ||||||
| # Production image | # Production image | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ RUN go mod download | |||||||
| COPY . . | COPY . . | ||||||
| 
 | 
 | ||||||
| RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale | RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale | ||||||
|  | RUN strip /go/bin/headscale | ||||||
| RUN test -e /go/bin/headscale | RUN test -e /go/bin/headscale | ||||||
| 
 | 
 | ||||||
| # Production image | # Production image | ||||||
|  | |||||||
| @ -65,7 +65,7 @@ To contribute to Headscale you would need the lastest version of [Go](https://go | |||||||
| 
 | 
 | ||||||
| ### Code style | ### Code style | ||||||
| 
 | 
 | ||||||
| To ensure we have some consistency with a growing number of contributes, this project has adopted linting and style/formatting rules: | To ensure we have some consistency with a growing number of contributions, this project has adopted linting and style/formatting rules: | ||||||
| 
 | 
 | ||||||
| The **Go** code is linted with [`golangci-lint`](https://golangci-lint.run) and | The **Go** code is linted with [`golangci-lint`](https://golangci-lint.run) and | ||||||
| formatted with [`golines`](https://github.com/segmentio/golines) (width 88) and | formatted with [`golines`](https://github.com/segmentio/golines) (width 88) and | ||||||
| @ -76,7 +76,7 @@ run `make lint` and `make fmt` before committing any code. | |||||||
| The **Proto** code is linted with [`buf`](https://docs.buf.build/lint/overview) and | The **Proto** code is linted with [`buf`](https://docs.buf.build/lint/overview) and | ||||||
| formatted with [`clang-format`](https://clang.llvm.org/docs/ClangFormat.html). | formatted with [`clang-format`](https://clang.llvm.org/docs/ClangFormat.html). | ||||||
| 
 | 
 | ||||||
| The **rest** (markdown, yaml, etc) is formatted with [`prettier`](https://prettier.io). | The **rest** (Markdown, YAML, etc) is formatted with [`prettier`](https://prettier.io). | ||||||
| 
 | 
 | ||||||
| Check out the `.golangci.yaml` and `Makefile` to see the specific configuration. | Check out the `.golangci.yaml` and `Makefile` to see the specific configuration. | ||||||
| 
 | 
 | ||||||
| @ -92,7 +92,7 @@ make install-protobuf-plugins | |||||||
| 
 | 
 | ||||||
| ### Testing and building | ### Testing and building | ||||||
| 
 | 
 | ||||||
| Some parts of the project requires the generation of Go code from Protobuf (if changes is made in `proto/`) and it must be (re-)generated with: | Some parts of the project require the generation of Go code from Protobuf (if changes are made in `proto/`) and it must be (re-)generated with: | ||||||
| 
 | 
 | ||||||
| ```shell | ```shell | ||||||
| make generate | make generate | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								app.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								app.go
									
									
									
									
									
								
							| @ -722,7 +722,8 @@ func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) { | |||||||
| 		return nil, fmt.Errorf("failed to read private key file: %w", err) | 		return nil, fmt.Errorf("failed to read private key file: %w", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	privateKeyEnsurePrefix := PrivateKeyEnsurePrefix(string(privateKey)) | 	trimmedPrivateKey := strings.TrimSpace(string(privateKey)) | ||||||
|  | 	privateKeyEnsurePrefix := PrivateKeyEnsurePrefix(trimmedPrivateKey) | ||||||
| 
 | 
 | ||||||
| 	var machineKey key.MachinePrivate | 	var machineKey key.MachinePrivate | ||||||
| 	if err = machineKey.UnmarshalText([]byte(privateKeyEnsurePrefix)); err != nil { | 	if err = machineKey.UnmarshalText([]byte(privateKeyEnsurePrefix)); err != nil { | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ wget --output-document=/usr/local/bin/headscale \ | |||||||
| chmod +x /usr/local/bin/headscale | chmod +x /usr/local/bin/headscale | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| 3. Prepare a direction to hold `headscale` configuration and the [SQLite](https://www.sqlite.org/) database: | 3. Prepare a directory to hold `headscale` configuration and the [SQLite](https://www.sqlite.org/) database: | ||||||
| 
 | 
 | ||||||
| ```shell | ```shell | ||||||
| # Directory for configuration | # Directory for configuration | ||||||
| @ -32,7 +32,7 @@ mkdir -p /etc/headscale | |||||||
| mkdir -p /var/lib/headscale | mkdir -p /var/lib/headscale | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| 4. Create an empty SQlite datebase: | 4. Create an empty SQLite database: | ||||||
| 
 | 
 | ||||||
| ```shell | ```shell | ||||||
| touch /var/lib/headscale/db.sqlite | touch /var/lib/headscale/db.sqlite | ||||||
| @ -106,7 +106,7 @@ tailscale up --login-server <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY> | |||||||
| 
 | 
 | ||||||
| ## Running `headscale` in the background with SystemD | ## Running `headscale` in the background with SystemD | ||||||
| 
 | 
 | ||||||
| In this section it will be demonstrated how to run `headscale` as a service in the background with [SystemD](https://www.freedesktop.org/wiki/Software/systemd/). | This section demonstrates how to run `headscale` as a service in the background with [SystemD](https://www.freedesktop.org/wiki/Software/systemd/). | ||||||
| This should work on most modern Linux distributions. | This should work on most modern Linux distributions. | ||||||
| 
 | 
 | ||||||
| 1. Create a SystemD service configuration at `/etc/systemd/system/headscale.service` containing: | 1. Create a SystemD service configuration at `/etc/systemd/system/headscale.service` containing: | ||||||
|  | |||||||
| @ -362,6 +362,14 @@ func (h *Headscale) DeleteMachine(machine *Machine) error { | |||||||
| 	return h.RequestMapUpdates(namespaceID) | 	return h.RequestMapUpdates(namespaceID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (h *Headscale) TouchMachine(machine *Machine) error { | ||||||
|  | 	return h.db.Updates(Machine{ | ||||||
|  | 		ID:                   machine.ID, | ||||||
|  | 		LastSeen:             machine.LastSeen, | ||||||
|  | 		LastSuccessfulUpdate: machine.LastSuccessfulUpdate, | ||||||
|  | 	}).Error | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // HardDeleteMachine hard deletes a Machine from the database.
 | // HardDeleteMachine hard deletes a Machine from the database.
 | ||||||
| func (h *Headscale) HardDeleteMachine(machine *Machine) error { | func (h *Headscale) HardDeleteMachine(machine *Machine) error { | ||||||
| 	err := h.RemoveSharedMachineFromAllNamespaces(machine) | 	err := h.RemoveSharedMachineFromAllNamespaces(machine) | ||||||
|  | |||||||
							
								
								
									
										62
									
								
								poll.go
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								poll.go
									
									
									
									
									
								
							| @ -76,6 +76,8 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { | |||||||
| 			Str("handler", "PollNetMap"). | 			Str("handler", "PollNetMap"). | ||||||
| 			Msgf("Failed to fetch machine from the database with Machine key: %s", machineKey.String()) | 			Msgf("Failed to fetch machine from the database with Machine key: %s", machineKey.String()) | ||||||
| 		ctx.String(http.StatusInternalServerError, "") | 		ctx.String(http.StatusInternalServerError, "") | ||||||
|  | 
 | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
| 	log.Trace(). | 	log.Trace(). | ||||||
| 		Str("handler", "PollNetMap"). | 		Str("handler", "PollNetMap"). | ||||||
| @ -102,7 +104,7 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { | |||||||
| 		machine.Endpoints = datatypes.JSON(endpoints) | 		machine.Endpoints = datatypes.JSON(endpoints) | ||||||
| 		machine.LastSeen = &now | 		machine.LastSeen = &now | ||||||
| 	} | 	} | ||||||
| 	h.db.Save(&machine) | 	h.db.Updates(machine) | ||||||
| 
 | 
 | ||||||
| 	data, err := h.getMapResponse(machineKey, req, machine) | 	data, err := h.getMapResponse(machineKey, req, machine) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -313,6 +315,10 @@ func (h *Headscale) PollNetMapStream( | |||||||
| 					Str("channel", "pollData"). | 					Str("channel", "pollData"). | ||||||
| 					Err(err). | 					Err(err). | ||||||
| 					Msg("Cannot update machine from database") | 					Msg("Cannot update machine from database") | ||||||
|  | 
 | ||||||
|  | 				// client has been removed from database
 | ||||||
|  | 				// since the stream opened, terminate connection.
 | ||||||
|  | 				return false | ||||||
| 			} | 			} | ||||||
| 			now := time.Now().UTC() | 			now := time.Now().UTC() | ||||||
| 			machine.LastSeen = &now | 			machine.LastSeen = &now | ||||||
| @ -321,13 +327,22 @@ func (h *Headscale) PollNetMapStream( | |||||||
| 				Set(float64(now.Unix())) | 				Set(float64(now.Unix())) | ||||||
| 			machine.LastSuccessfulUpdate = &now | 			machine.LastSuccessfulUpdate = &now | ||||||
| 
 | 
 | ||||||
| 			h.db.Save(&machine) | 			err = h.TouchMachine(machine) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error(). | ||||||
|  | 					Str("handler", "PollNetMapStream"). | ||||||
|  | 					Str("machine", machine.Name). | ||||||
|  | 					Str("channel", "pollData"). | ||||||
|  | 					Err(err). | ||||||
|  | 					Msg("Cannot update machine LastSuccessfulUpdate") | ||||||
|  | 			} else { | ||||||
| 				log.Trace(). | 				log.Trace(). | ||||||
| 					Str("handler", "PollNetMapStream"). | 					Str("handler", "PollNetMapStream"). | ||||||
| 					Str("machine", machine.Name). | 					Str("machine", machine.Name). | ||||||
| 					Str("channel", "pollData"). | 					Str("channel", "pollData"). | ||||||
| 					Int("bytes", len(data)). | 					Int("bytes", len(data)). | ||||||
| 					Msg("Machine entry in database updated successfully after sending pollData") | 					Msg("Machine entry in database updated successfully after sending pollData") | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			return true | 			return true | ||||||
| 
 | 
 | ||||||
| @ -366,16 +381,29 @@ func (h *Headscale) PollNetMapStream( | |||||||
| 					Str("channel", "keepAlive"). | 					Str("channel", "keepAlive"). | ||||||
| 					Err(err). | 					Err(err). | ||||||
| 					Msg("Cannot update machine from database") | 					Msg("Cannot update machine from database") | ||||||
|  | 
 | ||||||
|  | 				// client has been removed from database
 | ||||||
|  | 				// since the stream opened, terminate connection.
 | ||||||
|  | 				return false | ||||||
| 			} | 			} | ||||||
| 			now := time.Now().UTC() | 			now := time.Now().UTC() | ||||||
| 			machine.LastSeen = &now | 			machine.LastSeen = &now | ||||||
| 			h.db.Save(&machine) | 			err = h.TouchMachine(machine) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error(). | ||||||
|  | 					Str("handler", "PollNetMapStream"). | ||||||
|  | 					Str("machine", machine.Name). | ||||||
|  | 					Str("channel", "keepAlive"). | ||||||
|  | 					Err(err). | ||||||
|  | 					Msg("Cannot update machine LastSeen") | ||||||
|  | 			} else { | ||||||
| 				log.Trace(). | 				log.Trace(). | ||||||
| 					Str("handler", "PollNetMapStream"). | 					Str("handler", "PollNetMapStream"). | ||||||
| 					Str("machine", machine.Name). | 					Str("machine", machine.Name). | ||||||
| 					Str("channel", "keepAlive"). | 					Str("channel", "keepAlive"). | ||||||
| 					Int("bytes", len(data)). | 					Int("bytes", len(data)). | ||||||
| 					Msg("Machine updated successfully after sending keep alive") | 					Msg("Machine updated successfully after sending keep alive") | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			return true | 			return true | ||||||
| 
 | 
 | ||||||
| @ -443,6 +471,10 @@ func (h *Headscale) PollNetMapStream( | |||||||
| 						Str("channel", "update"). | 						Str("channel", "update"). | ||||||
| 						Err(err). | 						Err(err). | ||||||
| 						Msg("Cannot update machine from database") | 						Msg("Cannot update machine from database") | ||||||
|  | 
 | ||||||
|  | 					// client has been removed from database
 | ||||||
|  | 					// since the stream opened, terminate connection.
 | ||||||
|  | 					return false | ||||||
| 				} | 				} | ||||||
| 				now := time.Now().UTC() | 				now := time.Now().UTC() | ||||||
| 
 | 
 | ||||||
| @ -450,7 +482,15 @@ func (h *Headscale) PollNetMapStream( | |||||||
| 					Set(float64(now.Unix())) | 					Set(float64(now.Unix())) | ||||||
| 				machine.LastSuccessfulUpdate = &now | 				machine.LastSuccessfulUpdate = &now | ||||||
| 
 | 
 | ||||||
| 				h.db.Save(&machine) | 				err = h.TouchMachine(machine) | ||||||
|  | 				if err != nil { | ||||||
|  | 					log.Error(). | ||||||
|  | 						Str("handler", "PollNetMapStream"). | ||||||
|  | 						Str("machine", machine.Name). | ||||||
|  | 						Str("channel", "update"). | ||||||
|  | 						Err(err). | ||||||
|  | 						Msg("Cannot update machine LastSuccessfulUpdate") | ||||||
|  | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				var lastUpdate time.Time | 				var lastUpdate time.Time | ||||||
| 				if machine.LastSuccessfulUpdate != nil { | 				if machine.LastSuccessfulUpdate != nil { | ||||||
| @ -482,10 +522,22 @@ func (h *Headscale) PollNetMapStream( | |||||||
| 					Str("channel", "Done"). | 					Str("channel", "Done"). | ||||||
| 					Err(err). | 					Err(err). | ||||||
| 					Msg("Cannot update machine from database") | 					Msg("Cannot update machine from database") | ||||||
|  | 
 | ||||||
|  | 				// client has been removed from database
 | ||||||
|  | 				// since the stream opened, terminate connection.
 | ||||||
|  | 				return false | ||||||
| 			} | 			} | ||||||
| 			now := time.Now().UTC() | 			now := time.Now().UTC() | ||||||
| 			machine.LastSeen = &now | 			machine.LastSeen = &now | ||||||
| 			h.db.Save(&machine) | 			err = h.TouchMachine(machine) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Error(). | ||||||
|  | 					Str("handler", "PollNetMapStream"). | ||||||
|  | 					Str("machine", machine.Name). | ||||||
|  | 					Str("channel", "Done"). | ||||||
|  | 					Err(err). | ||||||
|  | 					Msg("Cannot update machine LastSeen") | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			return false | 			return false | ||||||
| 		} | 		} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user