diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e916056..1c63ae49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,11 +30,10 @@ - Add -c option to specify config file from command line [#285](https://github.com/juanfont/headscale/issues/285) [#612](https://github.com/juanfont/headscale/pull/601) - Add configuration option to allow Tailscale clients to use a random WireGuard port. [kb/1181/firewalls](https://tailscale.com/kb/1181/firewalls) [#624](https://github.com/juanfont/headscale/pull/624) - Improve obtuse UX regarding missing configuration (`ephemeral_node_inactivity_timeout` not set) [#639](https://github.com/juanfont/headscale/pull/639) -- Fix nodes being shown as 'offline' in `tailscale status` [648](https://github.com/juanfont/headscale/pull/648) - Fix nodes being shown as 'offline' in `tailscale status` [#648](https://github.com/juanfont/headscale/pull/648) - Improve shutdown behaviour [#651](https://github.com/juanfont/headscale/pull/651) - Drop Gin as web framework in Headscale [648](https://github.com/juanfont/headscale/pull/648) - +- Make tailnet node updates check interval configurable [#675](https://github.com/juanfont/headscale/pull/675) ## 0.15.0 (2022-03-20) diff --git a/config-example.yaml b/config-example.yaml index 9740f3ad..d3d155e2 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -103,6 +103,12 @@ disable_check_updates: false # Time before an inactive ephemeral node is deleted? ephemeral_node_inactivity_timeout: 30m +# Period to check for node updates in the tailnet. A value too low will severily affect +# CPU consumption of Headscale. A value too high (over 60s) will cause problems +# to the nodes, as they won't get updates or keep alive messages in time. +# In case of doubts, do not touch the default 10s. +node_update_check_interval: 10s + # SQLite config db_type: sqlite3 db_path: /var/lib/headscale/db.sqlite diff --git a/config.go b/config.go index 9e71a750..6789f6f0 100644 --- a/config.go +++ b/config.go @@ -26,6 +26,7 @@ type Config struct { GRPCAddr string GRPCAllowInsecure bool EphemeralNodeInactivityTimeout time.Duration + NodeUpdateCheckInterval time.Duration IPPrefixes []netaddr.IPPrefix PrivateKeyPath string BaseDomain string @@ -162,6 +163,8 @@ func LoadConfig(path string, isFile bool) error { viper.SetDefault("ephemeral_node_inactivity_timeout", "120s") + viper.SetDefault("node_update_check_interval", "10s") + if err := viper.ReadInConfig(); err != nil { log.Warn().Err(err).Msg("Failed to read configuration from disk") @@ -217,6 +220,15 @@ func LoadConfig(path string, isFile bool) error { ) } + maxNodeUpdateCheckInterval, _ := time.ParseDuration("60s") + if viper.GetDuration("node_update_check_interval") > maxNodeUpdateCheckInterval { + errorText += fmt.Sprintf( + "Fatal config error: node_update_check_interval (%s) is set too high, must be less than %s", + viper.GetString("node_update_check_interval"), + maxNodeUpdateCheckInterval, + ) + } + if errorText != "" { //nolint return errors.New(strings.TrimSuffix(errorText, "\n")) @@ -478,6 +490,10 @@ func GetHeadscaleConfig() (*Config, error) { "ephemeral_node_inactivity_timeout", ), + NodeUpdateCheckInterval: viper.GetDuration( + "node_update_check_interval", + ), + DBtype: viper.GetString("db_type"), DBpath: AbsolutePathFromConfigPath(viper.GetString("db_path")), DBhost: viper.GetString("db_host"), diff --git a/integration_test/etc/alt-config.dump.gold.yaml b/integration_test/etc/alt-config.dump.gold.yaml index a3d7adb0..e8934230 100644 --- a/integration_test/etc/alt-config.dump.gold.yaml +++ b/integration_test/etc/alt-config.dump.gold.yaml @@ -20,6 +20,7 @@ dns_config: nameservers: - 1.1.1.1 ephemeral_node_inactivity_timeout: 30m +node_update_check_interval: 10s grpc_allow_insecure: false grpc_listen_addr: :50443 ip_prefixes: diff --git a/integration_test/etc/alt-config.yaml b/integration_test/etc/alt-config.yaml index 8de9a828..fa1bfcb3 100644 --- a/integration_test/etc/alt-config.yaml +++ b/integration_test/etc/alt-config.yaml @@ -2,6 +2,7 @@ log_level: trace acl_policy_path: "" db_type: sqlite3 ephemeral_node_inactivity_timeout: 30m +node_update_check_interval: 10s ip_prefixes: - fd7a:115c:a1e0::/48 - 100.64.0.0/10 diff --git a/integration_test/etc/config.dump.gold.yaml b/integration_test/etc/config.dump.gold.yaml index 4d03d74e..17bb0ca0 100644 --- a/integration_test/etc/config.dump.gold.yaml +++ b/integration_test/etc/config.dump.gold.yaml @@ -20,6 +20,7 @@ dns_config: nameservers: - 1.1.1.1 ephemeral_node_inactivity_timeout: 30m +node_update_check_interval: 10s grpc_allow_insecure: false grpc_listen_addr: :50443 ip_prefixes: diff --git a/integration_test/etc/config.yaml b/integration_test/etc/config.yaml index f055b4ca..e6b34afa 100644 --- a/integration_test/etc/config.yaml +++ b/integration_test/etc/config.yaml @@ -2,6 +2,7 @@ log_level: trace acl_policy_path: "" db_type: sqlite3 ephemeral_node_inactivity_timeout: 30m +node_update_check_interval: 10s ip_prefixes: - fd7a:115c:a1e0::/48 - 100.64.0.0/10 diff --git a/integration_test/etc_embedded_derp/config.yaml b/integration_test/etc_embedded_derp/config.yaml index a8b57af5..e6ad3b00 100644 --- a/integration_test/etc_embedded_derp/config.yaml +++ b/integration_test/etc_embedded_derp/config.yaml @@ -2,6 +2,7 @@ log_level: trace acl_policy_path: "" db_type: sqlite3 ephemeral_node_inactivity_timeout: 30m +node_update_check_interval: 10s ip_prefixes: - fd7a:115c:a1e0::/48 - 100.64.0.0/10 diff --git a/poll.go b/poll.go index 9218495d..6628a179 100644 --- a/poll.go +++ b/poll.go @@ -16,8 +16,7 @@ import ( ) const ( - keepAliveInterval = 60 * time.Second - updateCheckInterval = 10 * time.Second + keepAliveInterval = 60 * time.Second ) type contextKey string @@ -640,7 +639,7 @@ func (h *Headscale) scheduledPollWorker( machine *Machine, ) { keepAliveTicker := time.NewTicker(keepAliveInterval) - updateCheckerTicker := time.NewTicker(updateCheckInterval) + updateCheckerTicker := time.NewTicker(h.cfg.NodeUpdateCheckInterval) defer closeChanWithLog( updateChan,