Merge branch 'main' into acl-syntax-fixes
This commit is contained in:
commit
7cd0f5e8a4
|
@ -27,6 +27,7 @@
|
|||
- 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)
|
||||
- Use new ACL syntax [#618](https://github.com/juanfont/headscale/pull/618)
|
||||
- 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)
|
||||
|
||||
|
|
26
app.go
26
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:
|
||||
|
@ -756,13 +758,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 {
|
||||
|
|
|
@ -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 (
|
||||
"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",
|
||||
|
|
|
@ -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() {
|
||||
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -92,7 +137,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()
|
||||
|
@ -125,7 +170,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", "***")
|
||||
|
@ -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 = headscale.LoadConfig(tmpDir)
|
||||
err = headscale.LoadConfig(tmpDir, false)
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
|
25
config.go
25
config.go
|
@ -114,15 +114,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")
|
||||
|
@ -377,11 +381,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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
# 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-rcd)
|
||||
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
|
||||
# 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
|
||||
|
||||
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
|
||||
# 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
|
||||
|
||||
# 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-rcd) 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 <YOU_+MACHINE_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 <YOUR_HEADSCALE_URL> --authkey <YOUR_AUTH_KEY>
|
||||
```
|
||||
|
||||
## 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.
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
@ -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
|
|
@ -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"
|
||||
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue