Merge remote-tracking branch 'origin/main' into ipv6
This commit is contained in:
commit
c0c3b7d511
|
@ -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: |
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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