Merge pull request #612 from huskyii/enhance_cli_config
This commit is contained in:
commit
efca3daa5c
10 changed files with 304 additions and 55 deletions
|
@ -22,6 +22,7 @@
|
||||||
- This change disables the logs by default
|
- 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)
|
- 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 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)
|
## 0.15.0 (2022-03-20)
|
||||||
|
|
||||||
|
|
28
cmd/headscale/cli/dump_config.go
Normal file
28
cmd/headscale/cli/dump_config.go
Normal file
|
@ -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")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
|
@ -3,17 +3,75 @@ package cli
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/juanfont/headscale"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/tcnksm/go-latest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var cfgFile string = ""
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
cobra.OnInitialize(initConfig)
|
||||||
|
rootCmd.PersistentFlags().
|
||||||
|
StringVarP(&cfgFile, "config", "c", "", "config file (default is /etc/headscale/config.yaml)")
|
||||||
rootCmd.PersistentFlags().
|
rootCmd.PersistentFlags().
|
||||||
StringP("output", "o", "", "Output format. Empty for human-readable, 'json', 'json-line' or 'yaml'")
|
StringP("output", "o", "", "Output format. Empty for human-readable, 'json', 'json-line' or 'yaml'")
|
||||||
rootCmd.PersistentFlags().
|
rootCmd.PersistentFlags().
|
||||||
Bool("force", false, "Disable prompts and forces the execution")
|
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{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "headscale",
|
Use: "headscale",
|
||||||
Short: "headscale - a Tailscale control server",
|
Short: "headscale - a Tailscale control server",
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/efekarakus/termcolor"
|
"github.com/efekarakus/termcolor"
|
||||||
"github.com/juanfont/headscale"
|
|
||||||
"github.com/juanfont/headscale/cmd/headscale/cli"
|
"github.com/juanfont/headscale/cmd/headscale/cli"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/tcnksm/go-latest"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -43,39 +39,5 @@ func main() {
|
||||||
NoColor: !colors,
|
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()
|
cli.Execute()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,51 @@ func (s *Suite) SetUpSuite(c *check.C) {
|
||||||
func (s *Suite) TearDownSuite(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) {
|
func (*Suite) TestConfigLoading(c *check.C) {
|
||||||
tmpDir, err := ioutil.TempDir("", "headscale")
|
tmpDir, err := ioutil.TempDir("", "headscale")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -49,7 +94,7 @@ func (*Suite) TestConfigLoading(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load example config, it should load without validation errors
|
// Load example config, it should load without validation errors
|
||||||
err = headscale.LoadConfig(tmpDir)
|
err = headscale.LoadConfig(tmpDir, false)
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
// Test that config file was interpreted correctly
|
// 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
|
// Load example config, it should load without validation errors
|
||||||
err = headscale.LoadConfig(tmpDir)
|
err = headscale.LoadConfig(tmpDir, false)
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
dnsConfig, baseDomain := headscale.GetDNSConfig()
|
dnsConfig, baseDomain := headscale.GetDNSConfig()
|
||||||
|
@ -125,7 +170,7 @@ func (*Suite) TestTLSConfigValidation(c *check.C) {
|
||||||
writeConfig(c, tmpDir, configYaml)
|
writeConfig(c, tmpDir, configYaml)
|
||||||
|
|
||||||
// Check configuration validation errors (1)
|
// Check configuration validation errors (1)
|
||||||
err = headscale.LoadConfig(tmpDir)
|
err = headscale.LoadConfig(tmpDir, false)
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
// check.Matches can not handle multiline strings
|
// check.Matches can not handle multiline strings
|
||||||
tmp := strings.ReplaceAll(err.Error(), "\n", "***")
|
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\"",
|
"---\nserver_url: \"http://127.0.0.1:8080\"\ntls_letsencrypt_hostname: \"example.com\"\ntls_letsencrypt_challenge_type: \"TLS-ALPN-01\"",
|
||||||
)
|
)
|
||||||
writeConfig(c, tmpDir, configYaml)
|
writeConfig(c, tmpDir, configYaml)
|
||||||
err = headscale.LoadConfig(tmpDir)
|
err = headscale.LoadConfig(tmpDir, false)
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
}
|
}
|
||||||
|
|
25
config.go
25
config.go
|
@ -114,15 +114,19 @@ type ACLConfig struct {
|
||||||
PolicyPath string
|
PolicyPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(path string) error {
|
func LoadConfig(path string, isFile bool) error {
|
||||||
viper.SetConfigName("config")
|
if isFile {
|
||||||
if path == "" {
|
viper.SetConfigFile(path)
|
||||||
viper.AddConfigPath("/etc/headscale/")
|
|
||||||
viper.AddConfigPath("$HOME/.headscale")
|
|
||||||
viper.AddConfigPath(".")
|
|
||||||
} else {
|
} else {
|
||||||
// For testing
|
viper.SetConfigName("config")
|
||||||
viper.AddConfigPath(path)
|
if path == "" {
|
||||||
|
viper.AddConfigPath("/etc/headscale/")
|
||||||
|
viper.AddConfigPath("$HOME/.headscale")
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
} else {
|
||||||
|
// For testing
|
||||||
|
viper.AddConfigPath(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viper.SetEnvPrefix("headscale")
|
viper.SetEnvPrefix("headscale")
|
||||||
|
@ -377,11 +381,6 @@ func GetDNSConfig() (*tailcfg.DNSConfig, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHeadscaleConfig() (*Config, error) {
|
func GetHeadscaleConfig() (*Config, error) {
|
||||||
err := LoadConfig("")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsConfig, baseDomain := GetDNSConfig()
|
dnsConfig, baseDomain := GetDNSConfig()
|
||||||
derpConfig := GetDERPConfig()
|
derpConfig := GetDERPConfig()
|
||||||
logConfig := GetLogTailConfig()
|
logConfig := GetLogTailConfig()
|
||||||
|
|
|
@ -1721,3 +1721,43 @@ func (s *IntegrationCLITestSuite) TestNodeMoveCommand() {
|
||||||
|
|
||||||
assert.Equal(s.T(), machine.Namespace, oldNamespace)
|
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))
|
||||||
|
}
|
||||||
|
|
46
integration_test/etc/alt-config.dump.gold.yaml
Normal file
46
integration_test/etc/alt-config.dump.gold.yaml
Normal file
|
@ -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: disabled
|
||||||
|
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"
|
||||||
|
|
24
integration_test/etc/alt-config.yaml
Normal file
24
integration_test/etc/alt-config.yaml
Normal file
|
@ -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
|
46
integration_test/etc/config.dump.gold.yaml
Normal file
46
integration_test/etc/config.dump.gold.yaml
Normal file
|
@ -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: disabled
|
||||||
|
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"
|
||||||
|
|
Loading…
Reference in a new issue