Skip to content

Commit

Permalink
Merge branch 'main' into feature/configure-randomize-port
Browse files Browse the repository at this point in the history
  • Loading branch information
kradalby authored Jun 11, 2022
2 parents 34be108 + 586c541 commit 3f7749c
Show file tree
Hide file tree
Showing 12 changed files with 511 additions and 55 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
28 changes: 28 additions & 0 deletions cmd/headscale/cli/dump_config.go
Original file line number Diff line number Diff line change
@@ -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")
}
},
}
58 changes: 58 additions & 0 deletions cmd/headscale/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,75 @@ package cli
import (
"fmt"
"os"
"runtime"

"github.com/juanfont/headscale"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"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 != "" {
err := headscale.LoadConfig(cfgFile, true)
if err != nil {
log.Fatal().Caller().Err(err)
}
} else {
err := headscale.LoadConfig("", false)
if err != nil {
log.Fatal().Caller().Err(err)
}
}

cfg, err := headscale.GetHeadscaleConfig()
if err != nil {
log.Fatal().Caller().Err(err)
}

machineOutput := HasMachineOutputFlag()

zerolog.SetGlobalLevel(cfg.LogLevel)

// If the user has requested a "machine" readable format,
// then disable login so the output remains valid.
if machineOutput {
zerolog.SetGlobalLevel(zerolog.Disabled)
}

if !cfg.DisableUpdateCheck && !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",
Expand Down
38 changes: 0 additions & 38 deletions cmd/headscale/headscale.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package main

import (
"fmt"
"os"
"runtime"
"time"

"github.com/efekarakus/termcolor"
"github.com/juanfont/headscale"
"github.com/juanfont/headscale/cmd/headscale/cli"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/tcnksm/go-latest"
)

func main() {
Expand Down Expand Up @@ -43,39 +39,5 @@ func main() {
NoColor: !colors,
})

cfg, err := headscale.GetHeadscaleConfig()
if err != nil {
log.Fatal().Caller().Err(err)
}

machineOutput := cli.HasMachineOutputFlag()

zerolog.SetGlobalLevel(cfg.LogLevel)

// If the user has requested a "machine" readable format,
// then disable login so the output remains valid.
if machineOutput {
zerolog.SetGlobalLevel(zerolog.Disabled)
}

if !cfg.DisableUpdateCheck && !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()
}
53 changes: 49 additions & 4 deletions cmd/headscale/headscale_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = headscale.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(
headscale.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 {
Expand All @@ -49,7 +94,7 @@ func (*Suite) TestConfigLoading(c *check.C) {
}

// Load example config, it should load without validation errors
err = headscale.LoadConfig(tmpDir)
err = headscale.LoadConfig(tmpDir, false)
c.Assert(err, check.IsNil)

// Test that config file was interpreted correctly
Expand Down Expand Up @@ -93,7 +138,7 @@ func (*Suite) TestDNSConfigLoading(c *check.C) {
}

// Load example config, it should load without validation errors
err = headscale.LoadConfig(tmpDir)
err = headscale.LoadConfig(tmpDir, false)
c.Assert(err, check.IsNil)

dnsConfig, baseDomain := headscale.GetDNSConfig()
Expand Down Expand Up @@ -126,7 +171,7 @@ func (*Suite) TestTLSConfigValidation(c *check.C) {
writeConfig(c, tmpDir, configYaml)

// Check configuration validation errors (1)
err = headscale.LoadConfig(tmpDir)
err = headscale.LoadConfig(tmpDir, false)
c.Assert(err, check.NotNil)
// check.Matches can not handle multiline strings
tmp := strings.ReplaceAll(err.Error(), "\n", "***")
Expand All @@ -151,6 +196,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 = headscale.LoadConfig(tmpDir)
err = headscale.LoadConfig(tmpDir, false)
c.Assert(err, check.IsNil)
}
25 changes: 12 additions & 13 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,19 @@ type ACLConfig struct {
PolicyPath string
}

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")
Expand Down Expand Up @@ -379,11 +383,6 @@ func GetDNSConfig() (*tailcfg.DNSConfig, string) {
}

func GetHeadscaleConfig() (*Config, error) {
err := LoadConfig("")
if err != nil {
return nil, err
}

dnsConfig, baseDomain := GetDNSConfig()
derpConfig := GetDERPConfig()
logConfig := GetLogTailConfig()
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading

0 comments on commit 3f7749c

Please sign in to comment.