From 75a0155f738472f0106bf07118f3df3ebb50d038 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 15:45:38 +0800 Subject: [PATCH 01/12] add openbsd doc --- docs/README.md | 1 + docs/running-headscale-openbsd.md | 197 ++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 docs/running-headscale-openbsd.md diff --git a/docs/README.md b/docs/README.md index 459a6c21..9f8e681a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,6 +27,7 @@ written by community members. It is _not_ verified by `headscale` developers. **It might be outdated and it might miss necessary steps**. - [Running headscale in a container](running-headscale-container.md) +- [Running headscale on OpenBSD](running-headscale-openbsd.md) ## Misc diff --git a/docs/running-headscale-openbsd.md b/docs/running-headscale-openbsd.md new file mode 100644 index 00000000..9e035c76 --- /dev/null +++ b/docs/running-headscale-openbsd.md @@ -0,0 +1,197 @@ +# Running headscale on OpenBSD + +## Goal + +This documentation has the goal of showing a user how-to install and run `headscale` on OpenBSD 7.1. +In additional to the "get up and running section", there is an optional [rc.d section](#running-headscale-in-the-background-with-rc.d) +describing how to make `headscale` run properly in a server environment. + +## Install `headscale` +1. Install from ports (Not Recommend) + + As of OpenBSD 7.1, there's a headscale in ports collection, however, it's severely outdated(v0.12.4). + You can install it via `pkg_add headscale`. + +2. Install from source on OpenBSD 7.1 + +``` shell +# Install prerequistes +# 1. go v1.18+: headscale newer than 0.15 needs go 1.18+ to compile +# 2. gmake: Makefile in the headscale repo is written in GNU make syntax +pkg_add -D snap go +pkg_add gmake + +git clone https://github.com/juanfont/headscale.git + +cd headscale + +# optionally checkout a release +git checkout v0.16.0-beta1 + +gmake build + +# make it executable +chmod a+x headscale + +# copy it to /usr/local/sbin +cp headscale /usr/local/sbin +``` + +3. Install from source via cross compile + +``` shell +# Install prerequistes +# 1. go v1.18+: headscale newer than 0.15 needs go 1.18+ to compile +# 2. gmake: Makefile in the headscale repo is written in GNU make syntax + +git clone https://github.com/juanfont/headscale.git + +cd headscale + +# optionally checkout a release +git checkout v0.16.0-beta1 + +make build GOOS=openbsd + +# copy headscale to openbsd machine and put it in /usr/local/sbin +``` + +## Configure and run `headscale` + +1. Prepare a directory to hold `headscale` configuration and the [SQLite](https://www.sqlite.org/) database: + +```shell +# Directory for configuration + +mkdir -p /etc/headscale + +# Directory for Database, and other variable data (like certificates) +mkdir -p /var/lib/headscale +``` + +2. Create an empty SQLite database: + +```shell +touch /var/lib/headscale/db.sqlite +``` + +3. Create a `headscale` configuration: + +```shell +touch /etc/headscale/config.yaml +``` + +It is **strongly recommended** to copy and modify the [example configuration](../config-example.yaml) +from the [headscale repository](../) + +4. Start the headscale server: + +```shell +headscale serve +``` + +This command will start `headscale` in the current terminal session. + +--- + +To continue the tutorial, open a new terminal and let it run in the background. +Alternatively use terminal emulators like [tmux](https://github.com/tmux/tmux). + +To run `headscale` in the background, please follow the steps in the [rc.d section](#running-headscale-in-the-background-with-rc.d) before continuing. + +5. Verify `headscale` is running: + +Verify `headscale` is available: + +```shell +curl http://127.0.0.1:9090/metrics +``` + +6. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)): + +```shell +headscale namespaces create myfirstnamespace +``` + +### Register a machine (normal login) + +On a client machine, execute the `tailscale` login command: + +```shell +tailscale up --login-server YOUR_HEADSCALE_URL +``` + +Register the machine: + +```shell +headscale --namespace myfirstnamespace nodes register --key +``` + +### Register machine using a pre authenticated key + +Generate a key using the command line: + +```shell +headscale --namespace myfirstnamespace preauthkeys create --reusable --expiration 24h +``` + +This will return a pre-authenticated key that can be used to connect a node to `headscale` during the `tailscale` command: + +```shell +tailscale up --login-server --authkey +``` + +## Running `headscale` in the background with rc.d + +This section demonstrates how to run `headscale` as a service in the background with [rc.d](https://man.openbsd.org/rc.d). + +1. Create a rc.d service at `/etc/rc.d/headscale` containing: + +```shell +#!/bin/ksh + +daemon="/usr/local/sbin/headscale" +daemon_logger="daemon.info" +daemon_user="root" +daemon_flags="serve" +daemon_timeout=60 + +. /etc/rc.d/rc.subr + +rc_bg=YES +rc_reload=NO + +rc_cmd $1 +``` + +2. `/etc/rc.d/headscale` needs execute permission: + +```shell +chmod a+x /etc/rc.d/headscale +``` + +3. Start `headscale` service: + +```shell +rcctl start headscale +``` + +4. Make `headscale` service start at boot: + +```shell +rcctl enable headscale +``` + +5. Verify the headscale service: + +```shell +rcctl check headscale +``` + +Verify `headscale` is available: + +```shell +curl http://127.0.0.1:9090/metrics +``` + +`headscale` will now run in the background and start at boot. From 1de29fd4e66641fc512080db2ddee633336f6695 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 15:49:24 +0800 Subject: [PATCH 02/12] fix rcd link --- docs/running-headscale-openbsd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/running-headscale-openbsd.md b/docs/running-headscale-openbsd.md index 9e035c76..7c25ed03 100644 --- a/docs/running-headscale-openbsd.md +++ b/docs/running-headscale-openbsd.md @@ -3,7 +3,7 @@ ## Goal This documentation has the goal of showing a user how-to install and run `headscale` on OpenBSD 7.1. -In additional to the "get up and running section", there is an optional [rc.d section](#running-headscale-in-the-background-with-rc.d) +In additional to the "get up and running section", there is an optional [rc.d section](#running-headscale-in-the-background-with-rcd) describing how to make `headscale` run properly in a server environment. ## Install `headscale` @@ -97,7 +97,7 @@ This command will start `headscale` in the current terminal session. To continue the tutorial, open a new terminal and let it run in the background. Alternatively use terminal emulators like [tmux](https://github.com/tmux/tmux). -To run `headscale` in the background, please follow the steps in the [rc.d section](#running-headscale-in-the-background-with-rc.d) before continuing. +To run `headscale` in the background, please follow the steps in the [rc.d section](#running-headscale-in-the-background-with-rcd) before continuing. 5. Verify `headscale` is running: From c8a14ccabb241b7368ef044a44028cb165afaec6 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 15:58:55 +0800 Subject: [PATCH 03/12] fix prettier --- docs/running-headscale-openbsd.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/running-headscale-openbsd.md b/docs/running-headscale-openbsd.md index 7c25ed03..9d4d3117 100644 --- a/docs/running-headscale-openbsd.md +++ b/docs/running-headscale-openbsd.md @@ -7,6 +7,7 @@ In additional to the "get up and running section", there is an optional [rc.d se describing how to make `headscale` run properly in a server environment. ## Install `headscale` + 1. Install from ports (Not Recommend) As of OpenBSD 7.1, there's a headscale in ports collection, however, it's severely outdated(v0.12.4). @@ -14,7 +15,7 @@ describing how to make `headscale` run properly in a server environment. 2. Install from source on OpenBSD 7.1 -``` shell +```shell # Install prerequistes # 1. go v1.18+: headscale newer than 0.15 needs go 1.18+ to compile # 2. gmake: Makefile in the headscale repo is written in GNU make syntax @@ -39,7 +40,7 @@ cp headscale /usr/local/sbin 3. Install from source via cross compile -``` shell +```shell # Install prerequistes # 1. go v1.18+: headscale newer than 0.15 needs go 1.18+ to compile # 2. gmake: Makefile in the headscale repo is written in GNU make syntax From 0363e58467eafd067c705b1fa617186df3256381 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 17:55:27 +0800 Subject: [PATCH 04/12] cli.LoadConfig accepts config file now --- cmd/headscale/cli/utils.go | 20 ++++++++----- cmd/headscale/headscale.go | 2 +- cmd/headscale/headscale_test.go | 53 ++++++++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index af4391a3..593fbd49 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -33,15 +33,19 @@ const ( HeadscaleDateTimeFormat = "2006-01-02 15:04:05" ) -func LoadConfig(path string) error { - viper.SetConfigName("config") - if path == "" { - viper.AddConfigPath("/etc/headscale/") - viper.AddConfigPath("$HOME/.headscale") - viper.AddConfigPath(".") +func LoadConfig(path string, isFile bool) error { + if isFile { + viper.SetConfigFile(path) } else { - // For testing - viper.AddConfigPath(path) + viper.SetConfigName("config") + if path == "" { + viper.AddConfigPath("/etc/headscale/") + viper.AddConfigPath("$HOME/.headscale") + viper.AddConfigPath(".") + } else { + // For testing + viper.AddConfigPath(path) + } } viper.SetEnvPrefix("headscale") diff --git a/cmd/headscale/headscale.go b/cmd/headscale/headscale.go index 600b186e..28b5f2ed 100644 --- a/cmd/headscale/headscale.go +++ b/cmd/headscale/headscale.go @@ -43,7 +43,7 @@ func main() { NoColor: !colors, }) - if err := cli.LoadConfig(""); err != nil { + if err := cli.LoadConfig("", false); err != nil { log.Fatal().Caller().Err(err) } diff --git a/cmd/headscale/headscale_test.go b/cmd/headscale/headscale_test.go index faf55f4c..92bba4b0 100644 --- a/cmd/headscale/headscale_test.go +++ b/cmd/headscale/headscale_test.go @@ -27,6 +27,51 @@ func (s *Suite) SetUpSuite(c *check.C) { func (s *Suite) TearDownSuite(c *check.C) { } +func (*Suite) TestConfigFileLoading(c *check.C) { + tmpDir, err := ioutil.TempDir("", "headscale") + if err != nil { + c.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + path, err := os.Getwd() + if err != nil { + c.Fatal(err) + } + + cfgFile := filepath.Join(tmpDir, "config.yaml") + + // Symlink the example config file + err = os.Symlink( + filepath.Clean(path+"/../../config-example.yaml"), + cfgFile, + ) + if err != nil { + c.Fatal(err) + } + + // Load example config, it should load without validation errors + err = cli.LoadConfig(cfgFile, true) + c.Assert(err, check.IsNil) + + // Test that config file was interpreted correctly + c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8080") + c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8080") + c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:9090") + c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3") + c.Assert(viper.GetString("db_path"), check.Equals, "/var/lib/headscale/db.sqlite") + c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "") + c.Assert(viper.GetString("tls_letsencrypt_listen"), check.Equals, ":http") + c.Assert(viper.GetString("tls_letsencrypt_challenge_type"), check.Equals, "HTTP-01") + c.Assert(viper.GetStringSlice("dns_config.nameservers")[0], check.Equals, "1.1.1.1") + c.Assert( + cli.GetFileMode("unix_socket_permission"), + check.Equals, + fs.FileMode(0o770), + ) + c.Assert(viper.GetBool("logtail.enabled"), check.Equals, false) +} + func (*Suite) TestConfigLoading(c *check.C) { tmpDir, err := ioutil.TempDir("", "headscale") if err != nil { @@ -49,7 +94,7 @@ func (*Suite) TestConfigLoading(c *check.C) { } // Load example config, it should load without validation errors - err = cli.LoadConfig(tmpDir) + err = cli.LoadConfig(tmpDir, false) c.Assert(err, check.IsNil) // Test that config file was interpreted correctly @@ -92,7 +137,7 @@ func (*Suite) TestDNSConfigLoading(c *check.C) { } // Load example config, it should load without validation errors - err = cli.LoadConfig(tmpDir) + err = cli.LoadConfig(tmpDir, false) c.Assert(err, check.IsNil) dnsConfig, baseDomain := cli.GetDNSConfig() @@ -125,7 +170,7 @@ func (*Suite) TestTLSConfigValidation(c *check.C) { writeConfig(c, tmpDir, configYaml) // Check configuration validation errors (1) - err = cli.LoadConfig(tmpDir) + err = cli.LoadConfig(tmpDir, false) c.Assert(err, check.NotNil) // check.Matches can not handle multiline strings tmp := strings.ReplaceAll(err.Error(), "\n", "***") @@ -150,6 +195,6 @@ func (*Suite) TestTLSConfigValidation(c *check.C) { "---\nserver_url: \"http://127.0.0.1:8080\"\ntls_letsencrypt_hostname: \"example.com\"\ntls_letsencrypt_challenge_type: \"TLS-ALPN-01\"", ) writeConfig(c, tmpDir, configYaml) - err = cli.LoadConfig(tmpDir) + err = cli.LoadConfig(tmpDir, false) c.Assert(err, check.IsNil) } From 402a29e50cfe7203e51b5365fea2031528f13ba7 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 18:25:09 +0800 Subject: [PATCH 05/12] impl heascale -c to specify config file --- cmd/headscale/cli/root.go | 57 ++++++++++++++++++++++++++++++++++++++ cmd/headscale/headscale.go | 43 ---------------------------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/cmd/headscale/cli/root.go b/cmd/headscale/cli/root.go index 99b15140..ab312c81 100644 --- a/cmd/headscale/cli/root.go +++ b/cmd/headscale/cli/root.go @@ -3,17 +3,74 @@ package cli import ( "fmt" "os" + "runtime" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/tcnksm/go-latest" ) +var cfgFile string = "" + func init() { + cobra.OnInitialize(initConfig) + rootCmd.PersistentFlags(). + StringVarP(&cfgFile, "config", "c", "", "config file (default is /etc/headscale/config.yaml)") rootCmd.PersistentFlags(). StringP("output", "o", "", "Output format. Empty for human-readable, 'json', 'json-line' or 'yaml'") rootCmd.PersistentFlags(). Bool("force", false, "Disable prompts and forces the execution") } +func initConfig() { + if cfgFile != "" { + if err := LoadConfig(cfgFile, true); err != nil { + log.Fatal().Caller().Err(err) + } + } else { + if err := LoadConfig("", false); err != nil { + log.Fatal().Caller().Err(err) + } + } + + machineOutput := HasMachineOutputFlag() + + logLevel := viper.GetString("log_level") + level, err := zerolog.ParseLevel(logLevel) + if err != nil { + zerolog.SetGlobalLevel(zerolog.DebugLevel) + } else { + zerolog.SetGlobalLevel(level) + } + + // If the user has requested a "machine" readable format, + // then disable login so the output remains valid. + if machineOutput { + zerolog.SetGlobalLevel(zerolog.Disabled) + } + + if !viper.GetBool("disable_check_updates") && !machineOutput { + if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") && + Version != "dev" { + githubTag := &latest.GithubTag{ + Owner: "juanfont", + Repository: "headscale", + } + res, err := latest.Check(githubTag, Version) + if err == nil && res.Outdated { + //nolint + fmt.Printf( + "An updated version of Headscale has been found (%s vs. your current %s). Check it out https://github.com/juanfont/headscale/releases\n", + res.Current, + Version, + ) + } + } + } +} + var rootCmd = &cobra.Command{ Use: "headscale", Short: "headscale - a Tailscale control server", diff --git a/cmd/headscale/headscale.go b/cmd/headscale/headscale.go index 28b5f2ed..40772a93 100644 --- a/cmd/headscale/headscale.go +++ b/cmd/headscale/headscale.go @@ -1,17 +1,13 @@ package main import ( - "fmt" "os" - "runtime" "time" "github.com/efekarakus/termcolor" "github.com/juanfont/headscale/cmd/headscale/cli" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/spf13/viper" - "github.com/tcnksm/go-latest" ) func main() { @@ -43,44 +39,5 @@ func main() { NoColor: !colors, }) - if err := cli.LoadConfig("", false); err != nil { - log.Fatal().Caller().Err(err) - } - - machineOutput := cli.HasMachineOutputFlag() - - logLevel := viper.GetString("log_level") - level, err := zerolog.ParseLevel(logLevel) - if err != nil { - zerolog.SetGlobalLevel(zerolog.DebugLevel) - } else { - zerolog.SetGlobalLevel(level) - } - - // If the user has requested a "machine" readable format, - // then disable login so the output remains valid. - if machineOutput { - zerolog.SetGlobalLevel(zerolog.Disabled) - } - - if !viper.GetBool("disable_check_updates") && !machineOutput { - if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") && - cli.Version != "dev" { - githubTag := &latest.GithubTag{ - Owner: "juanfont", - Repository: "headscale", - } - res, err := latest.Check(githubTag, cli.Version) - if err == nil && res.Outdated { - //nolint - fmt.Printf( - "An updated version of Headscale has been found (%s vs. your current %s). Check it out https://github.com/juanfont/headscale/releases\n", - res.Current, - cli.Version, - ) - } - } - } - cli.Execute() } From ce13596077ff19233655efc79c4097d710382803 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 19:29:42 +0800 Subject: [PATCH 06/12] add integration test for headscale -c --- cmd/headscale/cli/dump_config.go | 28 +++++++++++ integration_cli_test.go | 40 ++++++++++++++++ .../etc/alt-config.dump.gold.yaml | 46 +++++++++++++++++++ integration_test/etc/alt-config.yaml | 24 ++++++++++ integration_test/etc/config.dump.gold.yaml | 46 +++++++++++++++++++ 5 files changed, 184 insertions(+) create mode 100644 cmd/headscale/cli/dump_config.go create mode 100644 integration_test/etc/alt-config.dump.gold.yaml create mode 100644 integration_test/etc/alt-config.yaml create mode 100644 integration_test/etc/config.dump.gold.yaml diff --git a/cmd/headscale/cli/dump_config.go b/cmd/headscale/cli/dump_config.go new file mode 100644 index 00000000..374690ed --- /dev/null +++ b/cmd/headscale/cli/dump_config.go @@ -0,0 +1,28 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func init() { + rootCmd.AddCommand(dumpConfigCmd) +} + +var dumpConfigCmd = &cobra.Command{ + Use: "dumpConfig", + Short: "dump current config to /etc/headscale/config.dump.yaml, integration test only", + Hidden: true, + Args: func(cmd *cobra.Command, args []string) error { + return nil + }, + Run: func(cmd *cobra.Command, args []string) { + err := viper.WriteConfigAs("/etc/headscale/config.dump.yaml") + if err != nil { + //nolint + fmt.Println("Failed to dump config") + } + }, +} diff --git a/integration_cli_test.go b/integration_cli_test.go index 075c38ac..8ac6ee4d 100644 --- a/integration_cli_test.go +++ b/integration_cli_test.go @@ -1721,3 +1721,43 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() { assert.Equal(s.T(), machine.Namespace, oldNamespace) } + +func (s *IntegrationCLITestSuite) TestLoadConfigFromCommand() { + // TODO: make sure defaultConfig is not same as altConfig + defaultConfig, err := os.ReadFile("integration_test/etc/config.dump.gold.yaml") + assert.Nil(s.T(), err) + altConfig, err := os.ReadFile("integration_test/etc/alt-config.dump.gold.yaml") + assert.Nil(s.T(), err) + + _, err = ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "dumpConfig", + }, + []string{}, + ) + assert.Nil(s.T(), err) + + defaultDumpConfig, err := os.ReadFile("integration_test/etc/config.dump.yaml") + assert.Nil(s.T(), err) + + assert.YAMLEq(s.T(), string(defaultConfig), string(defaultDumpConfig)) + + _, err = ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "-c", + "/etc/headscale/alt-config.yaml", + "dumpConfig", + }, + []string{}, + ) + assert.Nil(s.T(), err) + + altDumpConfig, err := os.ReadFile("integration_test/etc/config.dump.yaml") + assert.Nil(s.T(), err) + + assert.YAMLEq(s.T(), string(altConfig), string(altDumpConfig)) +} diff --git a/integration_test/etc/alt-config.dump.gold.yaml b/integration_test/etc/alt-config.dump.gold.yaml new file mode 100644 index 00000000..7b2fe6ab --- /dev/null +++ b/integration_test/etc/alt-config.dump.gold.yaml @@ -0,0 +1,46 @@ +acl_policy_path: "" +cli: + insecure: false + timeout: 5s +db_path: /tmp/integration_test_db.sqlite3 +db_type: sqlite3 +derp: + auto_update_enabled: false + server: + enabled: false + stun: + enabled: true + update_frequency: 1m + urls: + - https://controlplane.tailscale.com/derpmap/default +dns_config: + base_domain: headscale.net + domains: [] + magic_dns: true + nameservers: + - 1.1.1.1 +ephemeral_node_inactivity_timeout: 30m +grpc_allow_insecure: false +grpc_listen_addr: :50443 +ip_prefixes: + - fd7a:115c:a1e0::/48 + - 100.64.0.0/10 +listen_addr: 0.0.0.0:18080 +log_level: trace +logtail: + enabled: false +metrics_listen_addr: 127.0.0.1:19090 +oidc: + scope: + - openid + - profile + - email + strip_email_domain: true +private_key_path: private.key +server_url: http://headscale:18080 +tls_client_auth_mode: relaxed +tls_letsencrypt_cache_dir: /var/www/.cache +tls_letsencrypt_challenge_type: HTTP-01 +unix_socket: /var/run/headscale.sock +unix_socket_permission: "0o770" + diff --git a/integration_test/etc/alt-config.yaml b/integration_test/etc/alt-config.yaml new file mode 100644 index 00000000..8de9a828 --- /dev/null +++ b/integration_test/etc/alt-config.yaml @@ -0,0 +1,24 @@ +log_level: trace +acl_policy_path: "" +db_type: sqlite3 +ephemeral_node_inactivity_timeout: 30m +ip_prefixes: + - fd7a:115c:a1e0::/48 + - 100.64.0.0/10 +dns_config: + base_domain: headscale.net + magic_dns: true + domains: [] + nameservers: + - 1.1.1.1 +db_path: /tmp/integration_test_db.sqlite3 +private_key_path: private.key +listen_addr: 0.0.0.0:18080 +metrics_listen_addr: 127.0.0.1:19090 +server_url: http://headscale:18080 + +derp: + urls: + - https://controlplane.tailscale.com/derpmap/default + auto_update_enabled: false + update_frequency: 1m diff --git a/integration_test/etc/config.dump.gold.yaml b/integration_test/etc/config.dump.gold.yaml new file mode 100644 index 00000000..d33610d9 --- /dev/null +++ b/integration_test/etc/config.dump.gold.yaml @@ -0,0 +1,46 @@ +acl_policy_path: "" +cli: + insecure: false + timeout: 5s +db_path: /tmp/integration_test_db.sqlite3 +db_type: sqlite3 +derp: + auto_update_enabled: false + server: + enabled: false + stun: + enabled: true + update_frequency: 1m + urls: + - https://controlplane.tailscale.com/derpmap/default +dns_config: + base_domain: headscale.net + domains: [] + magic_dns: true + nameservers: + - 1.1.1.1 +ephemeral_node_inactivity_timeout: 30m +grpc_allow_insecure: false +grpc_listen_addr: :50443 +ip_prefixes: + - fd7a:115c:a1e0::/48 + - 100.64.0.0/10 +listen_addr: 0.0.0.0:8080 +log_level: trace +logtail: + enabled: false +metrics_listen_addr: 127.0.0.1:9090 +oidc: + scope: + - openid + - profile + - email + strip_email_domain: true +private_key_path: private.key +server_url: http://headscale:8080 +tls_client_auth_mode: relaxed +tls_letsencrypt_cache_dir: /var/www/.cache +tls_letsencrypt_challenge_type: HTTP-01 +unix_socket: /var/run/headscale.sock +unix_socket_permission: "0o770" + From 8744eeeb190ce1d91bd192f3224c997a47a386bb Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 23:14:49 +0800 Subject: [PATCH 07/12] ExecuteCommand set HEADSCALE_LOG_LEVEL to disabled --- integration_test/etc/alt-config.dump.gold.yaml | 2 +- integration_test/etc/config.dump.gold.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration_test/etc/alt-config.dump.gold.yaml b/integration_test/etc/alt-config.dump.gold.yaml index 7b2fe6ab..5cc025cc 100644 --- a/integration_test/etc/alt-config.dump.gold.yaml +++ b/integration_test/etc/alt-config.dump.gold.yaml @@ -26,7 +26,7 @@ ip_prefixes: - fd7a:115c:a1e0::/48 - 100.64.0.0/10 listen_addr: 0.0.0.0:18080 -log_level: trace +log_level: disabled logtail: enabled: false metrics_listen_addr: 127.0.0.1:19090 diff --git a/integration_test/etc/config.dump.gold.yaml b/integration_test/etc/config.dump.gold.yaml index d33610d9..0df651ed 100644 --- a/integration_test/etc/config.dump.gold.yaml +++ b/integration_test/etc/config.dump.gold.yaml @@ -26,7 +26,7 @@ ip_prefixes: - fd7a:115c:a1e0::/48 - 100.64.0.0/10 listen_addr: 0.0.0.0:8080 -log_level: trace +log_level: disabled logtail: enabled: false metrics_listen_addr: 127.0.0.1:9090 From 0c5a402206657797389afe7b67b9ae5bff535803 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sun, 5 Jun 2022 23:15:21 +0800 Subject: [PATCH 08/12] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e991f139..dd25e317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - This change disables the logs by default - Use [Prometheus]'s duration parser, supporting days (`d`), weeks (`w`) and years (`y`) [#598](https://github.com/juanfont/headscale/pull/598) - Add support for reloading ACLs with SIGHUP [#601](https://github.com/juanfont/headscale/pull/601) +- 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) ## 0.15.0 (2022-03-20) From 0b4b5308099e2140074a0fb1ae13889a645ee581 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sat, 11 Jun 2022 16:41:52 +0800 Subject: [PATCH 09/12] remove the hardcoded version(suggested by @kradalby) --- docs/running-headscale-openbsd.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/running-headscale-openbsd.md b/docs/running-headscale-openbsd.md index 9d4d3117..6a307f91 100644 --- a/docs/running-headscale-openbsd.md +++ b/docs/running-headscale-openbsd.md @@ -27,7 +27,11 @@ git clone https://github.com/juanfont/headscale.git cd headscale # optionally checkout a release -git checkout v0.16.0-beta1 +# option a. you can find offical relase at https://github.com/juanfont/headscale/releases/latest +# option b. get latest tag, this may be a beta relase +latestTag=$(git describe --tags `git rev-list --tags --max-count=1`) + +git checkout $latestTag gmake build From 2be16b581c3857bcae2ca34f13e2b257be058423 Mon Sep 17 00:00:00 2001 From: Jiang Zhu Date: Sat, 11 Jun 2022 17:23:01 +0800 Subject: [PATCH 10/12] 1) fix typo 2) another hard coded version --- docs/running-headscale-openbsd.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/running-headscale-openbsd.md b/docs/running-headscale-openbsd.md index 6a307f91..dcd1c9bb 100644 --- a/docs/running-headscale-openbsd.md +++ b/docs/running-headscale-openbsd.md @@ -28,7 +28,7 @@ cd headscale # optionally checkout a release # option a. you can find offical relase at https://github.com/juanfont/headscale/releases/latest -# option b. get latest tag, this may be a beta relase +# option b. get latest tag, this may be a beta release latestTag=$(git describe --tags `git rev-list --tags --max-count=1`) git checkout $latestTag @@ -54,7 +54,11 @@ git clone https://github.com/juanfont/headscale.git cd headscale # optionally checkout a release -git checkout v0.16.0-beta1 +# option a. you can find offical relase at https://github.com/juanfont/headscale/releases/latest +# option b. get latest tag, this may be a beta release +latestTag=$(git describe --tags `git rev-list --tags --max-count=1`) + +git checkout $latestTag make build GOOS=openbsd From 7e6291c21c480f797bce6ee1611ad45702032ce8 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sat, 11 Jun 2022 12:53:02 +0100 Subject: [PATCH 11/12] Change Set state change function to filter instead of single namespace This commit makes the setLastStateChangeToNow function take a list of namespaces instead of a single namespace. If no namespaces is passed, all namespaces will be updated. This means that the argument acts like a filter. --- app.go | 22 +++++++++++++++++----- namespaces.go | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 01528fb9..062860db 100644 --- a/app.go +++ b/app.go @@ -756,13 +756,25 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { } } -func (h *Headscale) setLastStateChangeToNow(namespace string) { +func (h *Headscale) setLastStateChangeToNow(namespaces ...string) { + var err error + now := time.Now().UTC() - lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix())) - if h.lastStateChange == nil { - h.lastStateChange = xsync.NewMapOf[time.Time]() + + if len(namespaces) == 0 { + namespaces, err = h.ListNamespacesStr() + if err != nil { + log.Error().Caller().Err(err).Msg("failed to fetch all namespaces, failing to update last changed state.") + } + } + + for _, namespace := range namespaces { + lastStateUpdate.WithLabelValues(namespace, "headscale").Set(float64(now.Unix())) + if h.lastStateChange == nil { + h.lastStateChange = xsync.NewMapOf[time.Time]() + } + h.lastStateChange.Store(namespace, now) } - h.lastStateChange.Store(namespace, now) } func (h *Headscale) getLastStateChange(namespaces ...string) time.Time { diff --git a/namespaces.go b/namespaces.go index 19407b82..0add03ff 100644 --- a/namespaces.go +++ b/namespaces.go @@ -148,6 +148,21 @@ func (h *Headscale) ListNamespaces() ([]Namespace, error) { return namespaces, nil } +func (h *Headscale) ListNamespacesStr() ([]string, error) { + namespaces, err := h.ListNamespaces() + if err != nil { + return []string{}, err + } + + namespaceStrs := make([]string, len(namespaces)) + + for index, namespace := range namespaces { + namespaceStrs[index] = namespace.Name + } + + return namespaceStrs, nil +} + // ListMachinesInNamespace gets all the nodes in a given namespace. func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { err := CheckForFQDNRules(name) From 0c2648c1889c332bca61e82006793ea40695faa1 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sat, 11 Jun 2022 12:54:44 +0100 Subject: [PATCH 12/12] Update the nodes after we have reloaded the ACL policy with sighup --- app.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app.go b/app.go index 062860db..ee4732fe 100644 --- a/app.go +++ b/app.go @@ -657,7 +657,9 @@ func (h *Headscale) Serve() error { } log.Info(). Str("path", aclPath). - Msg("ACL policy successfully reloaded") + Msg("ACL policy successfully reloaded, notifying nodes of change") + + h.setLastStateChangeToNow() } default: