mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-26 08:53:05 +00:00
improve errors for missing directories (#1765)
* improve errors for missing directories Fixes #1761 Updates #1760 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * update container docs Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * update changelog with /var changes Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
c73e8476b9
commit
b60ee9db54
5 changed files with 51 additions and 2 deletions
|
@ -36,6 +36,7 @@ after improving the test harness as part of adopting [#1460](https://github.com/
|
||||||
- Add a filepath entry to [`derp.server.private_key_path`](https://github.com/juanfont/headscale/blob/b35993981297e18393706b2c963d6db882bba6aa/config-example.yaml#L95)
|
- Add a filepath entry to [`derp.server.private_key_path`](https://github.com/juanfont/headscale/blob/b35993981297e18393706b2c963d6db882bba6aa/config-example.yaml#L95)
|
||||||
- Docker images are now built with goreleaser (ko) [#1716](https://github.com/juanfont/headscale/pull/1716) [#1763](https://github.com/juanfont/headscale/pull/1763)
|
- Docker images are now built with goreleaser (ko) [#1716](https://github.com/juanfont/headscale/pull/1716) [#1763](https://github.com/juanfont/headscale/pull/1763)
|
||||||
- Entrypoint of container image has changed from shell to headscale, require change from `headscale serve` to `serve`
|
- Entrypoint of container image has changed from shell to headscale, require change from `headscale serve` to `serve`
|
||||||
|
- `/var/lib/headscale` and `/var/run/headscale` is no longer created automatically, see [container docs](./docs/running-headscale-container.md)
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
|
|
|
@ -57,15 +57,22 @@ server_url: http://your-host-name:8080
|
||||||
# Listen to 0.0.0.0 so it's accessible outside the container
|
# Listen to 0.0.0.0 so it's accessible outside the container
|
||||||
metrics_listen_addr: 0.0.0.0:9090
|
metrics_listen_addr: 0.0.0.0:9090
|
||||||
# The default /var/lib/headscale path is not writable in the container
|
# The default /var/lib/headscale path is not writable in the container
|
||||||
private_key_path: /etc/headscale/private.key
|
|
||||||
# The default /var/lib/headscale path is not writable in the container
|
|
||||||
noise:
|
noise:
|
||||||
private_key_path: /etc/headscale/noise_private.key
|
private_key_path: /etc/headscale/noise_private.key
|
||||||
|
# The default /var/lib/headscale path is not writable in the container
|
||||||
|
derp:
|
||||||
|
private_key_path: /etc/headscale/private.key
|
||||||
|
# The default /var/run/headscale path is not writable in the container
|
||||||
|
unix_socket: /etc/headscale/headscale.sock
|
||||||
# The default /var/lib/headscale path is not writable in the container
|
# The default /var/lib/headscale path is not writable in the container
|
||||||
database.type: sqlite3
|
database.type: sqlite3
|
||||||
database.sqlite.path: /etc/headscale/db.sqlite
|
database.sqlite.path: /etc/headscale/db.sqlite
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Alternatively, you can mount `/var/lib` and `/var/run` from your host system by adding
|
||||||
|
`--volume $(pwd)/lib:/var/lib/headscale` and `--volume $(pwd)/run:/var/run/headscale`
|
||||||
|
in the next step.
|
||||||
|
|
||||||
4. Start the headscale server while working in the host headscale directory:
|
4. Start the headscale server while working in the host headscale directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
_ "net/http/pprof" //nolint
|
_ "net/http/pprof" //nolint
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -69,6 +70,7 @@ const (
|
||||||
AuthPrefix = "Bearer "
|
AuthPrefix = "Bearer "
|
||||||
updateInterval = 5000
|
updateInterval = 5000
|
||||||
privateKeyFileMode = 0o600
|
privateKeyFileMode = 0o600
|
||||||
|
headscaleDirPerm = 0o700
|
||||||
|
|
||||||
registerCacheExpiration = time.Minute * 15
|
registerCacheExpiration = time.Minute * 15
|
||||||
registerCacheCleanup = time.Minute * 20
|
registerCacheCleanup = time.Minute * 20
|
||||||
|
@ -552,6 +554,12 @@ func (h *Headscale) Serve() error {
|
||||||
return fmt.Errorf("unable to remove old socket file: %w", err)
|
return fmt.Errorf("unable to remove old socket file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socketDir := filepath.Dir(h.cfg.UnixSocket)
|
||||||
|
err = util.EnsureDir(socketDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("setting up unix socket: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
socketListener, err := net.Listen("unix", h.cfg.UnixSocket)
|
socketListener, err := net.Listen("unix", h.cfg.UnixSocket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to set up gRPC socket: %w", err)
|
return fmt.Errorf("failed to set up gRPC socket: %w", err)
|
||||||
|
@ -919,6 +927,12 @@ func notFoundHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) {
|
func readOrCreatePrivateKey(path string) (*key.MachinePrivate, error) {
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
err := util.EnsureDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("ensuring private key directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
privateKey, err := os.ReadFile(path)
|
privateKey, err := os.ReadFile(path)
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
log.Info().Str("path", path).Msg("No private key file at path, creating...")
|
log.Info().Str("path", path).Msg("No private key file at path, creating...")
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -344,6 +345,12 @@ func openDB(cfg types.DatabaseConfig) (*gorm.DB, error) {
|
||||||
|
|
||||||
switch cfg.Type {
|
switch cfg.Type {
|
||||||
case types.DatabaseSqlite:
|
case types.DatabaseSqlite:
|
||||||
|
dir := filepath.Dir(cfg.Sqlite.Path)
|
||||||
|
err := util.EnsureDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("creating directory for sqlite: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
db, err := gorm.Open(
|
db, err := gorm.Open(
|
||||||
sqlite.Open(cfg.Sqlite.Path+"?_synchronous=1&_journal_mode=WAL"),
|
sqlite.Open(cfg.Sqlite.Path+"?_synchronous=1&_journal_mode=WAL"),
|
||||||
&gorm.Config{
|
&gorm.Config{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -42,3 +44,21 @@ func GetFileMode(key string) fs.FileMode {
|
||||||
|
|
||||||
return fs.FileMode(mode)
|
return fs.FileMode(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EnsureDir(dir string) error {
|
||||||
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
|
err := os.MkdirAll(dir, PermissionFallback)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, os.ErrPermission) {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"creating directory %s, failed with permission error, is it located somewhere Headscale can write?",
|
||||||
|
dir,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("creating directory %s: %w", dir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue