mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-26 08:53:05 +00:00
Compare commits
4 commits
716d86f71e
...
84c1243bc6
Author | SHA1 | Date | |
---|---|---|---|
|
84c1243bc6 | ||
|
5fbf3f8327 | ||
|
6275399327 | ||
|
29119bb7f4 |
10 changed files with 90 additions and 16 deletions
|
@ -28,7 +28,9 @@ ARG VERSION_GIT_HASH=""
|
||||||
ENV VERSION_GIT_HASH=$VERSION_GIT_HASH
|
ENV VERSION_GIT_HASH=$VERSION_GIT_HASH
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
||||||
RUN GOARCH=$TARGETARCH go install -ldflags="\
|
ARG BUILD_TAGS=""
|
||||||
|
|
||||||
|
RUN GOARCH=$TARGETARCH go install -tags="${BUILD_TAGS}" -ldflags="\
|
||||||
-X tailscale.com/version.longStamp=$VERSION_LONG \
|
-X tailscale.com/version.longStamp=$VERSION_LONG \
|
||||||
-X tailscale.com/version.shortStamp=$VERSION_SHORT \
|
-X tailscale.com/version.shortStamp=$VERSION_SHORT \
|
||||||
-X tailscale.com/version.gitCommitStamp=$VERSION_GIT_HASH" \
|
-X tailscale.com/version.gitCommitStamp=$VERSION_GIT_HASH" \
|
||||||
|
|
|
@ -168,6 +168,11 @@ database:
|
||||||
# https://www.sqlite.org/wal.html
|
# https://www.sqlite.org/wal.html
|
||||||
write_ahead_log: true
|
write_ahead_log: true
|
||||||
|
|
||||||
|
# Maximum number of WAL file frames before the WAL file is automatically checkpointed.
|
||||||
|
# https://www.sqlite.org/c3ref/wal_autocheckpoint.html
|
||||||
|
# Set to 0 to disable automatic checkpointing.
|
||||||
|
wal_autocheckpoint: 1000
|
||||||
|
|
||||||
# # Postgres config
|
# # Postgres config
|
||||||
# Please note that using Postgres is highly discouraged as it is only supported for legacy reasons.
|
# Please note that using Postgres is highly discouraged as it is only supported for legacy reasons.
|
||||||
# See database.type for more information.
|
# See database.type for more information.
|
||||||
|
|
|
@ -45,11 +45,11 @@ headscale server.
|
||||||
|
|
||||||
ACLs have to be written in [huJSON](https://github.com/tailscale/hujson).
|
ACLs have to be written in [huJSON](https://github.com/tailscale/hujson).
|
||||||
|
|
||||||
When registering the servers we will need to add the flag
|
When [registering the servers](../usage/getting-started.md#register-a-node) we
|
||||||
`--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user that is
|
will need to add the flag `--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user
|
||||||
registering the server should be allowed to do it. Since anyone can add tags to
|
that is registering the server should be allowed to do it. Since anyone can add
|
||||||
a server they can register, the check of the tags is done on headscale server
|
tags to a server they can register, the check of the tags is done on headscale
|
||||||
and only valid tags are applied. A tag is valid if the user that is
|
server and only valid tags are applied. A tag is valid if the user that is
|
||||||
registering it is allowed to do it.
|
registering it is allowed to do it.
|
||||||
|
|
||||||
To use ACLs in headscale, you must edit your `config.yaml` file. In there you will find a `policy.path` parameter. This will need to point to your ACL file. More info on how these policies are written can be found [here](https://tailscale.com/kb/1018/acls/).
|
To use ACLs in headscale, you must edit your `config.yaml` file. In there you will find a `policy.path` parameter. This will need to point to your ACL file. More info on how these policies are written can be found [here](https://tailscale.com/kb/1018/acls/).
|
||||||
|
|
|
@ -9,6 +9,8 @@ tls_cert_path: ""
|
||||||
tls_key_path: ""
|
tls_key_path: ""
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The certificate should contain the full chain, else some clients, like the Tailscale Android client, will reject it.
|
||||||
|
|
||||||
## Let's Encrypt / ACME
|
## Let's Encrypt / ACME
|
||||||
|
|
||||||
To get a certificate automatically via [Let's Encrypt](https://letsencrypt.org/), set `tls_letsencrypt_hostname` to the desired certificate hostname. This name must resolve to the IP address(es) headscale is reachable on (i.e., it must correspond to the `server_url` configuration parameter). The certificate and Let's Encrypt account credentials will be stored in the directory configured in `tls_letsencrypt_cache_dir`. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
To get a certificate automatically via [Let's Encrypt](https://letsencrypt.org/), set `tls_letsencrypt_hostname` to the desired certificate hostname. This name must resolve to the IP address(es) headscale is reachable on (i.e., it must correspond to the `server_url` configuration parameter). The certificate and Let's Encrypt account credentials will be stored in the directory configured in `tls_letsencrypt_cache_dir`. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
||||||
|
|
|
@ -60,7 +60,7 @@ Install the official Tailscale tvOS client from the [App Store](https://apps.app
|
||||||
|
|
||||||
### Configuring the headscale URL
|
### Configuring the headscale URL
|
||||||
|
|
||||||
- Go Settings (the apple tvOS settings) > Apps > Tailscale
|
- Open Settings (the Apple tvOS settings) > Apps > Tailscale
|
||||||
- Under `ALTERNATE COORDINATION SERVER URL`, select `URL`
|
- Under `ALTERNATE COORDINATION SERVER URL`, select `URL`
|
||||||
- Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `OK`
|
- Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `OK`
|
||||||
- Return to the tvOS Home screen
|
- Return to the tvOS Home screen
|
||||||
|
|
|
@ -9,6 +9,8 @@ This page helps you get started with headscale and provides a few usage examples
|
||||||
installation instructions.
|
installation instructions.
|
||||||
* The configuration file exists and is adjusted to suit your environment, see
|
* The configuration file exists and is adjusted to suit your environment, see
|
||||||
[Configuration](../ref/configuration.md) for details.
|
[Configuration](../ref/configuration.md) for details.
|
||||||
|
* Headscale is reachable from the Internet. Verify this by opening client specific setup instructions in your
|
||||||
|
browser, e.g. https://headscale.example.com/windows
|
||||||
* The Tailscale client is installed, see [Client and operating system support](../about/clients.md) for more
|
* The Tailscale client is installed, see [Client and operating system support](../about/clients.md) for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
|
|
@ -543,10 +543,10 @@ func openDB(cfg types.DatabaseConfig) (*gorm.DB, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Sqlite.WriteAheadLog {
|
if cfg.Sqlite.WriteAheadLog {
|
||||||
if err := db.Exec(`
|
if err := db.Exec(fmt.Sprintf(`
|
||||||
PRAGMA journal_mode=WAL;
|
PRAGMA journal_mode=WAL;
|
||||||
PRAGMA wal_autocheckpoint=0;
|
PRAGMA wal_autocheckpoint=%d;
|
||||||
`).Error; err != nil {
|
`, cfg.Sqlite.WALAutoCheckPoint)).Error; err != nil {
|
||||||
return nil, fmt.Errorf("setting WAL mode: %w", err)
|
return nil, fmt.Errorf("setting WAL mode: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ type Nameservers struct {
|
||||||
type SqliteConfig struct {
|
type SqliteConfig struct {
|
||||||
Path string
|
Path string
|
||||||
WriteAheadLog bool
|
WriteAheadLog bool
|
||||||
|
WALAutoCheckPoint int
|
||||||
}
|
}
|
||||||
|
|
||||||
type PostgresConfig struct {
|
type PostgresConfig struct {
|
||||||
|
@ -270,6 +271,7 @@ func LoadConfig(path string, isFile bool) error {
|
||||||
viper.SetDefault("database.postgres.conn_max_idle_time_secs", 3600)
|
viper.SetDefault("database.postgres.conn_max_idle_time_secs", 3600)
|
||||||
|
|
||||||
viper.SetDefault("database.sqlite.write_ahead_log", true)
|
viper.SetDefault("database.sqlite.write_ahead_log", true)
|
||||||
|
viper.SetDefault("database.sqlite.wal_autocheckpoint", 1000) // SQLite default
|
||||||
|
|
||||||
viper.SetDefault("oidc.scope", []string{oidc.ScopeOpenID, "profile", "email"})
|
viper.SetDefault("oidc.scope", []string{oidc.ScopeOpenID, "profile", "email"})
|
||||||
viper.SetDefault("oidc.only_start_if_oidc_is_available", true)
|
viper.SetDefault("oidc.only_start_if_oidc_is_available", true)
|
||||||
|
@ -543,6 +545,7 @@ func databaseConfig() DatabaseConfig {
|
||||||
viper.GetString("database.sqlite.path"),
|
viper.GetString("database.sqlite.path"),
|
||||||
),
|
),
|
||||||
WriteAheadLog: viper.GetBool("database.sqlite.write_ahead_log"),
|
WriteAheadLog: viper.GetBool("database.sqlite.write_ahead_log"),
|
||||||
|
WALAutoCheckPoint: viper.GetInt("database.sqlite.wal_autocheckpoint"),
|
||||||
},
|
},
|
||||||
Postgres: PostgresConfig{
|
Postgres: PostgresConfig{
|
||||||
Host: viper.GetString("database.postgres.host"),
|
Host: viper.GetString("database.postgres.host"),
|
||||||
|
|
|
@ -55,7 +55,7 @@ func TestDERPServerWebsocketScenario(t *testing.T) {
|
||||||
spec := map[string]ClientsSpec{
|
spec := map[string]ClientsSpec{
|
||||||
"user1": {
|
"user1": {
|
||||||
Plain: 0,
|
Plain: 0,
|
||||||
WebsocketDERP: len(MustTestVersions),
|
WebsocketDERP: 2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,10 +239,13 @@ func (s *EmbeddedDERPServerScenario) CreateHeadscaleEnv(
|
||||||
|
|
||||||
if clientCount.WebsocketDERP > 0 {
|
if clientCount.WebsocketDERP > 0 {
|
||||||
// Containers that use DERP-over-WebSocket
|
// Containers that use DERP-over-WebSocket
|
||||||
|
// Note that these clients *must* be built
|
||||||
|
// from source, which is currently
|
||||||
|
// only done for HEAD.
|
||||||
err = s.CreateTailscaleIsolatedNodesInUser(
|
err = s.CreateTailscaleIsolatedNodesInUser(
|
||||||
hash,
|
hash,
|
||||||
userName,
|
userName,
|
||||||
"all",
|
tsic.VersionHead,
|
||||||
clientCount.WebsocketDERP,
|
clientCount.WebsocketDERP,
|
||||||
tsic.WithWebsocketDERP(true),
|
tsic.WithWebsocketDERP(true),
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -44,6 +45,11 @@ var (
|
||||||
errTailscaleCannotUpWithoutAuthkey = errors.New("cannot up without authkey")
|
errTailscaleCannotUpWithoutAuthkey = errors.New("cannot up without authkey")
|
||||||
errTailscaleNotConnected = errors.New("tailscale not connected")
|
errTailscaleNotConnected = errors.New("tailscale not connected")
|
||||||
errTailscaledNotReadyForLogin = errors.New("tailscaled not ready for login")
|
errTailscaledNotReadyForLogin = errors.New("tailscaled not ready for login")
|
||||||
|
errInvalidClientConfig = errors.New("verifiably invalid client config requested")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
VersionHead = "head"
|
||||||
)
|
)
|
||||||
|
|
||||||
func errTailscaleStatus(hostname string, err error) error {
|
func errTailscaleStatus(hostname string, err error) error {
|
||||||
|
@ -74,6 +80,13 @@ type TailscaleInContainer struct {
|
||||||
withExtraHosts []string
|
withExtraHosts []string
|
||||||
workdir string
|
workdir string
|
||||||
netfilter string
|
netfilter string
|
||||||
|
|
||||||
|
// build options, solely for HEAD
|
||||||
|
buildConfig TailscaleInContainerBuildConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type TailscaleInContainerBuildConfig struct {
|
||||||
|
tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option represent optional settings that can be given to a
|
// Option represent optional settings that can be given to a
|
||||||
|
@ -175,6 +188,22 @@ func WithNetfilter(state string) Option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithBuildTag adds an additional value to the `-tags=` parameter
|
||||||
|
// of the Go compiler, allowing callers to customize the Tailscale client build.
|
||||||
|
// This option is only meaningful when invoked on **HEAD** versions of the client.
|
||||||
|
// Attempts to use it with any other version is a bug in the calling code.
|
||||||
|
func WithBuildTag(tag string) Option {
|
||||||
|
return func(tsic *TailscaleInContainer) {
|
||||||
|
if tsic.version != VersionHead {
|
||||||
|
panic(errInvalidClientConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
tsic.buildConfig.tags = append(
|
||||||
|
tsic.buildConfig.tags, tag,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// New returns a new TailscaleInContainer instance.
|
// New returns a new TailscaleInContainer instance.
|
||||||
func New(
|
func New(
|
||||||
pool *dockertest.Pool,
|
pool *dockertest.Pool,
|
||||||
|
@ -219,6 +248,12 @@ func New(
|
||||||
}
|
}
|
||||||
|
|
||||||
if tsic.withWebsocketDERP {
|
if tsic.withWebsocketDERP {
|
||||||
|
if version != VersionHead {
|
||||||
|
return tsic, errInvalidClientConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
WithBuildTag("ts_debug_websockets")(tsic)
|
||||||
|
|
||||||
tailscaleOptions.Env = append(
|
tailscaleOptions.Env = append(
|
||||||
tailscaleOptions.Env,
|
tailscaleOptions.Env,
|
||||||
fmt.Sprintf("TS_DEBUG_DERP_WS_CLIENT=%t", tsic.withWebsocketDERP),
|
fmt.Sprintf("TS_DEBUG_DERP_WS_CLIENT=%t", tsic.withWebsocketDERP),
|
||||||
|
@ -245,14 +280,36 @@ func New(
|
||||||
}
|
}
|
||||||
|
|
||||||
var container *dockertest.Resource
|
var container *dockertest.Resource
|
||||||
|
|
||||||
|
if version != VersionHead {
|
||||||
|
// build options are not meaningful with pre-existing images,
|
||||||
|
// let's not lead anyone astray by pretending otherwise.
|
||||||
|
defaultBuildConfig := TailscaleInContainerBuildConfig{}
|
||||||
|
hasBuildConfig := !reflect.DeepEqual(defaultBuildConfig, tsic.buildConfig)
|
||||||
|
if hasBuildConfig {
|
||||||
|
return tsic, errInvalidClientConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch version {
|
switch version {
|
||||||
case "head":
|
case VersionHead:
|
||||||
buildOptions := &dockertest.BuildOptions{
|
buildOptions := &dockertest.BuildOptions{
|
||||||
Dockerfile: "Dockerfile.tailscale-HEAD",
|
Dockerfile: "Dockerfile.tailscale-HEAD",
|
||||||
ContextDir: dockerContextPath,
|
ContextDir: dockerContextPath,
|
||||||
BuildArgs: []docker.BuildArg{},
|
BuildArgs: []docker.BuildArg{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildTags := strings.Join(tsic.buildConfig.tags, ",")
|
||||||
|
if len(buildTags) > 0 {
|
||||||
|
buildOptions.BuildArgs = append(
|
||||||
|
buildOptions.BuildArgs,
|
||||||
|
docker.BuildArg{
|
||||||
|
Name: "BUILD_TAGS",
|
||||||
|
Value: buildTags,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
container, err = pool.BuildAndRunWithBuildOptions(
|
container, err = pool.BuildAndRunWithBuildOptions(
|
||||||
buildOptions,
|
buildOptions,
|
||||||
tailscaleOptions,
|
tailscaleOptions,
|
||||||
|
|
Loading…
Reference in a new issue