Merge pull request #262 from kradalby/improve-docs
Rewrite main documentation
This commit is contained in:
commit
42bed58329
|
@ -54,9 +54,8 @@ func (*Suite) TestConfigLoading(c *check.C) {
|
||||||
// Test that config file was interpreted correctly
|
// 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("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("listen_addr"), check.Equals, "0.0.0.0:8080")
|
||||||
c.Assert(viper.GetStringSlice("derp.paths")[0], check.Equals, "derp-example.yaml")
|
|
||||||
c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3")
|
c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3")
|
||||||
c.Assert(viper.GetString("db_path"), check.Equals, "db.sqlite")
|
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_hostname"), check.Equals, "")
|
||||||
c.Assert(viper.GetString("tls_letsencrypt_listen"), check.Equals, ":http")
|
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.GetString("tls_letsencrypt_challenge_type"), check.Equals, "HTTP-01")
|
||||||
|
|
|
@ -1,39 +1,65 @@
|
||||||
---
|
---
|
||||||
|
# headscale will look for a configuration file named `config.yaml` (or `config.json`) in the following order:
|
||||||
|
#
|
||||||
|
# - `/etc/headscale`
|
||||||
|
# - `~/.headscale`
|
||||||
|
# - current working directory
|
||||||
|
|
||||||
# The url clients will connect to.
|
# The url clients will connect to.
|
||||||
# Typically this will be a domain.
|
# Typically this will be a domain like:
|
||||||
|
#
|
||||||
|
# https://myheadscale.example.com:443
|
||||||
|
#
|
||||||
server_url: http://127.0.0.1:8080
|
server_url: http://127.0.0.1:8080
|
||||||
|
|
||||||
# Address to listen to / bind to on the server
|
# Address to listen to / bind to on the server
|
||||||
|
#
|
||||||
listen_addr: 0.0.0.0:8080
|
listen_addr: 0.0.0.0:8080
|
||||||
|
|
||||||
# Private key file which will be
|
# Private key used encrypt the traffic between headscale
|
||||||
|
# and Tailscale clients.
|
||||||
|
# The private key file which will be
|
||||||
# autogenerated if it's missing
|
# autogenerated if it's missing
|
||||||
private_key_path: private.key
|
private_key_path: /var/lib/headscale/private.key
|
||||||
|
|
||||||
|
# DERP is a relay system that Tailscale uses when a direct
|
||||||
|
# connection cannot be established.
|
||||||
|
# https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp
|
||||||
|
#
|
||||||
|
# headscale needs a list of DERP servers that can be presented
|
||||||
|
# to the clients.
|
||||||
derp:
|
derp:
|
||||||
# List of externally available DERP maps encoded in JSON
|
# List of externally available DERP maps encoded in JSON
|
||||||
urls:
|
urls:
|
||||||
- https://controlplane.tailscale.com/derpmap/default
|
- https://controlplane.tailscale.com/derpmap/default
|
||||||
|
|
||||||
# Locally available DERP map files encoded in YAML
|
# Locally available DERP map files encoded in YAML
|
||||||
paths:
|
#
|
||||||
- derp-example.yaml
|
# This option is mostly interesting for people hosting
|
||||||
|
# their own DERP servers:
|
||||||
|
# https://tailscale.com/kb/1118/custom-derp-servers/
|
||||||
|
#
|
||||||
|
# paths:
|
||||||
|
# - /etc/headscale/derp-example.yaml
|
||||||
|
paths: []
|
||||||
|
|
||||||
# If enabled, a worker will be set up to periodically
|
# If enabled, a worker will be set up to periodically
|
||||||
# refresh the given sources and update the derpmap
|
# refresh the given sources and update the derpmap
|
||||||
# will be set up.
|
# will be set up.
|
||||||
auto_update_enabled: true
|
auto_update_enabled: true
|
||||||
|
|
||||||
# How often should we check for updates?
|
# How often should we check for DERP updates?
|
||||||
update_frequency: 24h
|
update_frequency: 24h
|
||||||
|
|
||||||
# Disables the automatic check for updates on startup
|
# Disables the automatic check for headscale updates on startup
|
||||||
disable_check_updates: false
|
disable_check_updates: false
|
||||||
|
|
||||||
|
# Time before an inactive ephemeral node is deleted?
|
||||||
ephemeral_node_inactivity_timeout: 30m
|
ephemeral_node_inactivity_timeout: 30m
|
||||||
|
|
||||||
# SQLite config
|
# SQLite config
|
||||||
db_type: sqlite3
|
db_type: sqlite3
|
||||||
db_path: db.sqlite
|
db_path: /var/lib/headscale/db.sqlite
|
||||||
|
|
||||||
# # Postgres config
|
# # Postgres config
|
||||||
# db_type: postgres
|
# db_type: postgres
|
||||||
|
@ -43,35 +69,87 @@ db_path: db.sqlite
|
||||||
# db_user: foo
|
# db_user: foo
|
||||||
# db_pass: bar
|
# db_pass: bar
|
||||||
|
|
||||||
|
### TLS configuration
|
||||||
|
#
|
||||||
|
## Let's encrypt / ACME
|
||||||
|
#
|
||||||
|
# headscale supports automatically requesting and setting up
|
||||||
|
# TLS for a domain with Let's Encrypt.
|
||||||
|
#
|
||||||
|
# URL to ACME directory
|
||||||
acme_url: https://acme-v02.api.letsencrypt.org/directory
|
acme_url: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
|
||||||
|
# Email to register with ACME provider
|
||||||
acme_email: ""
|
acme_email: ""
|
||||||
|
|
||||||
|
# Domain name to request a TLS certificate for:
|
||||||
tls_letsencrypt_hostname: ""
|
tls_letsencrypt_hostname: ""
|
||||||
tls_letsencrypt_listen: ":http"
|
|
||||||
tls_letsencrypt_cache_dir: ".cache"
|
|
||||||
tls_letsencrypt_challenge_type: HTTP-01
|
|
||||||
|
|
||||||
|
# Path to store certificates and metadata needed by
|
||||||
|
# letsencrypt
|
||||||
|
tls_letsencrypt_cache_dir: /var/lib/headscale/cache
|
||||||
|
|
||||||
|
# Type of ACME challenge to use, currently supported types:
|
||||||
|
# HTTP-01 or TLS_ALPN-01
|
||||||
|
# See [docs/tls.md](docs/tls.md) for more information
|
||||||
|
tls_letsencrypt_challenge_type: HTTP-01
|
||||||
|
# When HTTP-01 challenge is chosen, letsencrypt must set up a
|
||||||
|
# verification endpoint, and it will be listning on:
|
||||||
|
# :http = port 80
|
||||||
|
tls_letsencrypt_listen: ":http"
|
||||||
|
|
||||||
|
## Use already defined certificates:
|
||||||
tls_cert_path: ""
|
tls_cert_path: ""
|
||||||
tls_key_path: ""
|
tls_key_path: ""
|
||||||
|
|
||||||
log_level: info
|
log_level: info
|
||||||
|
|
||||||
# Path to a file containg ACL policies.
|
# Path to a file containg ACL policies.
|
||||||
|
# Recommended path: /etc/headscale/acl.hujson
|
||||||
acl_policy_path: ""
|
acl_policy_path: ""
|
||||||
|
|
||||||
|
## DNS
|
||||||
|
#
|
||||||
|
# headscale supports Tailscale's DNS configuration and MagicDNS.
|
||||||
|
# Please have a look to their KB to better understand the concepts:
|
||||||
|
#
|
||||||
|
# - https://tailscale.com/kb/1054/dns/
|
||||||
|
# - https://tailscale.com/kb/1081/magicdns/
|
||||||
|
# - https://tailscale.com/blog/2021-09-private-dns-with-magicdns/
|
||||||
|
#
|
||||||
dns_config:
|
dns_config:
|
||||||
# Upstream DNS servers
|
# List of DNS servers to expose to clients.
|
||||||
nameservers:
|
nameservers:
|
||||||
- 1.1.1.1
|
- 1.1.1.1
|
||||||
|
|
||||||
|
# Split DNS (see https://tailscale.com/kb/1054/dns/),
|
||||||
|
# list of search domains and the DNS to query for each one.
|
||||||
|
#
|
||||||
|
# restricted_nameservers:
|
||||||
|
# foo.bar.com:
|
||||||
|
# - 1.1.1.1
|
||||||
|
# darp.headscale.net:
|
||||||
|
# - 1.1.1.1
|
||||||
|
# - 8.8.8.8
|
||||||
|
|
||||||
|
# Search domains to inject.
|
||||||
domains: []
|
domains: []
|
||||||
|
|
||||||
|
# Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/).
|
||||||
|
# Only works if there is at least a nameserver defined.
|
||||||
magic_dns: true
|
magic_dns: true
|
||||||
|
|
||||||
|
# Defines the base domain to create the hostnames for MagicDNS.
|
||||||
|
# `base_domain` must be a FQDNs, without the trailing dot.
|
||||||
|
# The FQDN of the hosts will be
|
||||||
|
# `hostname.namespace.base_domain` (e.g., _myhost.mynamespace.example.com_).
|
||||||
base_domain: example.com
|
base_domain: example.com
|
||||||
|
|
||||||
# Unix socket used for the CLI to connect without authentication
|
# Unix socket used for the CLI to connect without authentication
|
||||||
# Note: for local development, you probably want to change this to:
|
# Note: for local development, you probably want to change this to:
|
||||||
# unix_socket: ./headscale.sock
|
# unix_socket: ./headscale.sock
|
||||||
unix_socket: /var/run/headscale.sock
|
unix_socket: /var/run/headscale.sock
|
||||||
|
#
|
||||||
# headscale supports experimental OpenID connect support,
|
# headscale supports experimental OpenID connect support,
|
||||||
# it is still being tested and might have some bugs, please
|
# it is still being tested and might have some bugs, please
|
||||||
# help us test it.
|
# help us test it.
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
# Configuration reference
|
|
||||||
|
|
||||||
Headscale will look for a configuration file named `config.yaml` (or `config.json`) in the following order:
|
|
||||||
|
|
||||||
- `/etc/headscale`
|
|
||||||
- `~/.headscale`
|
|
||||||
- current working directory
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
server_url: http://headscale.mydomain.net
|
|
||||||
listen_addr: 0.0.0.0:8080
|
|
||||||
ip_prefix: 100.64.0.0/10
|
|
||||||
disable_check_updates: false
|
|
||||||
```
|
|
||||||
|
|
||||||
`server_url` is the external URL via which Headscale is reachable. `listen_addr` is the IP address and port the Headscale program should listen on. `ip_prefix` is the IP prefix (range) in which IP addresses for nodes will be allocated (default 100.64.0.0/10, e.g., 192.168.4.0/24, 10.0.0.0/8). `disable_check_updates` disables the automatic check for updates.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
log_level: debug
|
|
||||||
```
|
|
||||||
|
|
||||||
`log_level` can be used to set the Log level for Headscale, it defaults to `debug`, and the available levels are: `trace`, `debug`, `info`, `warn` and `error`.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
derp_map_path: derp.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
`derp_map_path` is the path to the [DERP](https://pkg.go.dev/tailscale.com/derp) map file. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
ephemeral_node_inactivity_timeout: "30m"
|
|
||||||
```
|
|
||||||
|
|
||||||
`ephemeral_node_inactivity_timeout` is the timeout after which inactive ephemeral node records will be deleted from the database. The default is 30 minutes. This value must be higher than 65 seconds (the keepalive timeout for the HTTP long poll is 60 seconds, plus a few seconds to avoid race conditions).
|
|
||||||
|
|
||||||
PostgresSQL
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
db_host: localhost
|
|
||||||
db_port: 5432
|
|
||||||
db_name: headscale
|
|
||||||
db_user: foo
|
|
||||||
db_pass: bar
|
|
||||||
```
|
|
||||||
|
|
||||||
SQLite
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
db_type: sqlite3
|
|
||||||
db_path: db.sqlite
|
|
||||||
```
|
|
||||||
|
|
||||||
The fields starting with `db_` are used for the DB connection information.
|
|
||||||
|
|
||||||
### TLS configuration
|
|
||||||
|
|
||||||
Please check [`TLS.md`](TLS.md).
|
|
||||||
|
|
||||||
### DNS configuration
|
|
||||||
|
|
||||||
Please refer to [`DNS.md`](DNS.md).
|
|
||||||
|
|
||||||
### Policy ACLs
|
|
||||||
|
|
||||||
Headscale implements the same policy ACLs as Tailscale.com, adapted to the self-hosted environment.
|
|
||||||
|
|
||||||
For instance, instead of referring to users when defining groups you must
|
|
||||||
use namespaces (which are the equivalent to user/logins in Tailscale.com).
|
|
||||||
|
|
||||||
Please check https://tailscale.com/kb/1018/acls/, and `./tests/acls/` in this repo for working examples.
|
|
||||||
|
|
||||||
### Apple devices
|
|
||||||
|
|
||||||
An endpoint with information on how to connect your Apple devices (currently macOS only) is available at `/apple` on your running instance.
|
|
37
docs/DNS.md
37
docs/DNS.md
|
@ -1,37 +0,0 @@
|
||||||
# DNS in headscale
|
|
||||||
|
|
||||||
headscale supports Tailscale's DNS configuration and MagicDNS. Please have a look to their KB to better understand what this means:
|
|
||||||
|
|
||||||
- https://tailscale.com/kb/1054/dns/
|
|
||||||
- https://tailscale.com/kb/1081/magicdns/
|
|
||||||
- https://tailscale.com/blog/2021-09-private-dns-with-magicdns/
|
|
||||||
|
|
||||||
Long story short, you can define the DNS servers you want to use in your tailnets, activate MagicDNS (so you don't have to remember the IP addresses of your nodes), define search domains, as well as predefined hosts. headscale will inject that settings into your nodes.
|
|
||||||
|
|
||||||
## Configuration reference
|
|
||||||
|
|
||||||
The setup is done via the `config.yaml` file, under the `dns_config` key.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
server_url: http://127.0.0.1:8001
|
|
||||||
listen_addr: 0.0.0.0:8001
|
|
||||||
dns_config:
|
|
||||||
nameservers:
|
|
||||||
- 1.1.1.1
|
|
||||||
- 8.8.8.8
|
|
||||||
restricted_nameservers:
|
|
||||||
foo.bar.com:
|
|
||||||
- 1.1.1.1
|
|
||||||
darp.headscale.net:
|
|
||||||
- 1.1.1.1
|
|
||||||
- 8.8.8.8
|
|
||||||
domains: []
|
|
||||||
magic_dns: true
|
|
||||||
base_domain: example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
- `nameservers`: The list of DNS servers to use.
|
|
||||||
- `domains`: Search domains to inject.
|
|
||||||
- `magic_dns`: Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/). Only works if there is at least a nameserver defined.
|
|
||||||
- `base_domain`: Defines the base domain to create the hostnames for MagicDNS. `base_domain` must be a FQDNs, without the trailing dot. The FQDN of the hosts will be `hostname.namespace.base_domain` (e.g., _myhost.mynamespace.example.com_).
|
|
||||||
- `restricted_nameservers`: Split DNS (see https://tailscale.com/kb/1054/dns/), list of search domains and the DNS to query for each one.
|
|
|
@ -1,7 +1,42 @@
|
||||||
# Official headscale documentation
|
# headscale documentation
|
||||||
|
|
||||||
- [Configuration](Configuration.md)
|
This page contains the official and community contributed documentation for `headscale`.
|
||||||
- [Running](Running.md)
|
|
||||||
- [DNS](DNS.md)
|
If you are having trouble with following the documentation or get unexpected results,
|
||||||
- [TLS](TLS.md)
|
please ask on [Discord](https://discord.gg/XcQxk2VHjx) instead of opening an Issue.
|
||||||
- [Glossary](Glossary.md)
|
|
||||||
|
## Official documentation
|
||||||
|
|
||||||
|
### How-to
|
||||||
|
|
||||||
|
- [Running headscale on Linux](running-headscale-linux.md)
|
||||||
|
|
||||||
|
### References
|
||||||
|
|
||||||
|
- [Configuration](../config-example.yaml)
|
||||||
|
- [Glossary](glossary.md)
|
||||||
|
- [TLS](tls.md)
|
||||||
|
|
||||||
|
## Community documentation
|
||||||
|
|
||||||
|
Community documentation is not actively maintained by the headscale authors and is
|
||||||
|
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)
|
||||||
|
|
||||||
|
## Misc
|
||||||
|
|
||||||
|
### Policy ACLs
|
||||||
|
|
||||||
|
Headscale implements the same policy ACLs as Tailscale.com, adapted to the self-hosted environment.
|
||||||
|
|
||||||
|
For instance, instead of referring to users when defining groups you must
|
||||||
|
use namespaces (which are the equivalent to user/logins in Tailscale.com).
|
||||||
|
|
||||||
|
Please check https://tailscale.com/kb/1018/acls/, and `./tests/acls/` in this repo for working examples.
|
||||||
|
|
||||||
|
### Apple devices
|
||||||
|
|
||||||
|
An endpoint with information on how to connect your Apple devices (currently macOS only) is available at `/apple` on your running instance.
|
||||||
|
|
193
docs/Running.md
193
docs/Running.md
|
@ -1,193 +0,0 @@
|
||||||
# Running headscale
|
|
||||||
|
|
||||||
**Note:** The docs are currently out of date with the new 0.12.x releases, we are working on this. The _main_ change is that `headscale` must be running before using the CLI.
|
|
||||||
|
|
||||||
## Server configuration
|
|
||||||
|
|
||||||
1. Download the headscale binary https://github.com/juanfont/headscale/releases, and place it somewhere in your $PATH or use the docker container
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker pull headscale/headscale:x.x.x
|
|
||||||
```
|
|
||||||
|
|
||||||
<!--
|
|
||||||
or
|
|
||||||
```shell
|
|
||||||
docker pull ghrc.io/juanfont/headscale:x.x.x
|
|
||||||
``` -->
|
|
||||||
|
|
||||||
2. When running headscale in a docker container, prepare a directory to hold all configuration
|
|
||||||
|
|
||||||
```shell
|
|
||||||
mkdir config
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Get yourself a DB
|
|
||||||
|
|
||||||
a) Get a Postgres DB running in Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run --name headscale \
|
|
||||||
-e POSTGRES_DB=headscale \
|
|
||||||
-e POSTGRES_USER=foo \
|
|
||||||
-e POSTGRES_PASSWORD=bar \
|
|
||||||
-p 5432:5432 \
|
|
||||||
-d postgres
|
|
||||||
```
|
|
||||||
|
|
||||||
or b) Prepare a SQLite DB file:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
touch config/db.sqlite
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Create a headscale configuration, and a DERP map file. Refer to [tailscale sample](https://raw.githubusercontent.com/tailscale/tailscale/main/net/dnsfallback/dns-fallback-servers.json) for more guidance.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
cp config.yaml.[sqlite|postgres].example config/config.yaml
|
|
||||||
|
|
||||||
cp derp-example.yaml config/derp.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Create a namespace
|
|
||||||
|
|
||||||
```shell
|
|
||||||
headscale namespaces create myfirstnamespace
|
|
||||||
```
|
|
||||||
|
|
||||||
or Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run \
|
|
||||||
-v $(pwd)/config:/etc/headscale/ \
|
|
||||||
-p 127.0.0.1:8080:8080 \
|
|
||||||
headscale/headscale:x.x.x \
|
|
||||||
headscale namespaces create myfirstnamespace
|
|
||||||
```
|
|
||||||
|
|
||||||
or if your server is already running in Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker exec <container_name> \
|
|
||||||
headscale namespaces create myfirstnamespace
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Run the server
|
|
||||||
|
|
||||||
```shell
|
|
||||||
headscale serve
|
|
||||||
```
|
|
||||||
|
|
||||||
or Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run \
|
|
||||||
-v $(pwd)/config:/etc/headscale/ \
|
|
||||||
-p 127.0.0.1:8080:8080 \
|
|
||||||
headscale/headscale:x.x.x \
|
|
||||||
headscale serve
|
|
||||||
```
|
|
||||||
|
|
||||||
## Nodes configuration
|
|
||||||
|
|
||||||
If you used tailscale.com before in your nodes, make sure you clear the tailscaled data folder
|
|
||||||
|
|
||||||
```shell
|
|
||||||
systemctl stop tailscaled
|
|
||||||
rm -fr /var/lib/tailscale
|
|
||||||
systemctl start tailscaled
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding node based on MACHINEKEY
|
|
||||||
|
|
||||||
1. Add your first machine
|
|
||||||
|
|
||||||
```shell
|
|
||||||
tailscale up --login-server YOUR_HEADSCALE_URL
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Navigate to the URL returned by `tailscale up`, where you'll find your machine key.
|
|
||||||
|
|
||||||
3. In the server, register your machine to a namespace with the CLI
|
|
||||||
|
|
||||||
```shell
|
|
||||||
headscale -n myfirstnamespace nodes register -k YOURMACHINEKEY
|
|
||||||
```
|
|
||||||
|
|
||||||
or Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run \
|
|
||||||
-v $(pwd)/config:/etc/headscale/ \
|
|
||||||
headscale/headscale:x.x.x \
|
|
||||||
headscale -n myfirstnamespace nodes register -k YOURMACHINEKEY
|
|
||||||
```
|
|
||||||
|
|
||||||
or if your server is already running in Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker exec <container_name> \
|
|
||||||
headscale -n myfirstnamespace nodes register -k YOURMACHINEKEY
|
|
||||||
```
|
|
||||||
|
|
||||||
### Alternative: adding node with AUTHKEY
|
|
||||||
|
|
||||||
1. Create an authkey
|
|
||||||
|
|
||||||
```shell
|
|
||||||
headscale -n myfirstnamespace preauthkeys create --reusable --expiration 24h
|
|
||||||
```
|
|
||||||
|
|
||||||
or Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker run \
|
|
||||||
-v $(pwd)/config:/etc/headscale/ \
|
|
||||||
headscale/headscale:x.x.x \
|
|
||||||
headscale -n myfirstnamespace preauthkeys create --reusable --expiration 24h
|
|
||||||
```
|
|
||||||
|
|
||||||
or if your server is already running in Docker:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker exec <container_name> \
|
|
||||||
headscale -n myfirstnamespace preauthkeys create --reusable --expiration 24h
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Use the authkey on your node to register it:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
tailscale up --login-server YOUR_HEADSCALE_URL --authkey YOURAUTHKEY
|
|
||||||
```
|
|
||||||
|
|
||||||
If you create an authkey with the `--ephemeral` flag, that key will create ephemeral nodes. This implies that `--reusable` is true.
|
|
||||||
|
|
||||||
Please bear in mind that all headscale commands support adding `-o json` or `-o json-line` to get nicely JSON-formatted output.
|
|
||||||
|
|
||||||
## Debugging headscale running in Docker
|
|
||||||
|
|
||||||
The `headscale/headscale` Docker container is based on a "distroless" image that does not contain a shell or any other debug tools. If you need to debug your application running in the Docker container, you can use the `-debug` variant, for example `headscale/headscale:x.x.x-debug`.
|
|
||||||
|
|
||||||
### Running the debug Docker container
|
|
||||||
|
|
||||||
To run the debug Docker container, use the exact same commands as above, but replace `headscale/headscale:x.x.x` with `headscale/headscale:x.x.x-debug` (`x.x.x` is the version of headscale). The two containers are compatible with each other, so you can alternate between them.
|
|
||||||
|
|
||||||
### Executing commands in the debug container
|
|
||||||
|
|
||||||
The default command in the debug container is to run `headscale`, which is located at `/bin/headscale` inside the container.
|
|
||||||
|
|
||||||
Additionally, the debug container includes a minimalist Busybox shell.
|
|
||||||
|
|
||||||
To launch a shell in the container, use:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -it headscale/headscale:x.x.x-debug sh
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also execute commands directly, such as `ls /bin` in this example:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run headscale/headscale:x.x.x-debug ls /bin
|
|
||||||
```
|
|
||||||
|
|
||||||
Using `docker exec` allows you to run commands in an existing container.
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
This directory contains examples on how to run `headscale` on different platforms.
|
||||||
|
|
||||||
|
All examples are provided by the community and they are not verified by the `headscale` authors.
|
|
@ -1,5 +1,7 @@
|
||||||
# Deploying headscale on Kubernetes
|
# Deploying headscale on Kubernetes
|
||||||
|
|
||||||
|
**Note:** This is contributed by the community and not verified by the headscale authors.
|
||||||
|
|
||||||
This directory contains [Kustomize](https://kustomize.io) templates that deploy
|
This directory contains [Kustomize](https://kustomize.io) templates that deploy
|
||||||
headscale in various configurations.
|
headscale in various configurations.
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ tasks like creating namespaces, authkeys, etc.
|
||||||
|
|
||||||
headscale is an open source implementation of the Tailscale control server
|
headscale is an open source implementation of the Tailscale control server
|
||||||
|
|
||||||
https://gitlab.com/juanfont/headscale
|
https://github.com/juanfont/headscale
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
headscale [command]
|
headscale [command]
|
|
@ -0,0 +1,133 @@
|
||||||
|
# Running headscale in a container
|
||||||
|
|
||||||
|
**Note:** the container documentation is maintained by the _community_ and there is no guarentee
|
||||||
|
it is up to date, or working.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
This documentation has the goal of showing a user how-to set up and run `headscale` in a container.
|
||||||
|
[Docker](https://www.docker.com) is used as the reference container implementation, but there is no reason that it should
|
||||||
|
not work with alternatives like [Podman](https://podman.io).
|
||||||
|
|
||||||
|
## Configure and run `headscale`
|
||||||
|
|
||||||
|
1. Prepare a direction to hold `headscale` configuration and the [SQLite](https://www.sqlite.org/) database:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
mkdir config
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create an empty SQlite datebase:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
touch config/db.sqlite
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Create a `headscale` configuration:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
touch config/config.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
It is **strongly recommended** to copy the [example configuration](../config.yaml) from the [headscale repository](../)
|
||||||
|
|
||||||
|
4. Start the headscale server:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run \
|
||||||
|
--name headscale \
|
||||||
|
--detach \
|
||||||
|
--rm \
|
||||||
|
--volume $(pwd)/config:/etc/headscale/ \
|
||||||
|
--publish 127.0.0.1:8080:8080 \
|
||||||
|
headscale/headscale:<VERSION> \
|
||||||
|
headscale serve
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
This command will mount `config/` under `/etc/headscale`, forward port 8080 out of the container so the
|
||||||
|
`headscale` instance becomes available and then detach so headscale runs in the background.
|
||||||
|
|
||||||
|
5. Verify `headscale` is running:
|
||||||
|
|
||||||
|
Follow the container logs:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker logs --follow headscale
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify running containers:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify `headscale` is available:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl http://127.0.0.1:8080/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Create a namespace ([tailnet](https://tailscale.com/kb/1136/tailnet/)):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker exec headscale -- 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
|
||||||
|
```
|
||||||
|
|
||||||
|
To register a machine when running `headscale` in a container, take the headscale command and pass it to the container:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker exec headscale -- \
|
||||||
|
headscale --namespace myfirstnamespace nodes register --key <YOU_+MACHINE_KEY>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Register machine using a pre authenticated key
|
||||||
|
|
||||||
|
Generate a key using the command line:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker exec headscale -- \
|
||||||
|
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>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging headscale running in Docker
|
||||||
|
|
||||||
|
The `headscale/headscale` Docker container is based on a "distroless" image that does not contain a shell or any other debug tools. If you need to debug your application running in the Docker container, you can use the `-debug` variant, for example `headscale/headscale:x.x.x-debug`.
|
||||||
|
|
||||||
|
### Running the debug Docker container
|
||||||
|
|
||||||
|
To run the debug Docker container, use the exact same commands as above, but replace `headscale/headscale:x.x.x` with `headscale/headscale:x.x.x-debug` (`x.x.x` is the version of headscale). The two containers are compatible with each other, so you can alternate between them.
|
||||||
|
|
||||||
|
### Executing commands in the debug container
|
||||||
|
|
||||||
|
The default command in the debug container is to run `headscale`, which is located at `/bin/headscale` inside the container.
|
||||||
|
|
||||||
|
Additionally, the debug container includes a minimalist Busybox shell.
|
||||||
|
|
||||||
|
To launch a shell in the container, use:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -it headscale/headscale:x.x.x-debug sh
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also execute commands directly, such as `ls /bin` in this example:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run headscale/headscale:x.x.x-debug ls /bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `docker exec` allows you to run commands in an existing container.
|
|
@ -0,0 +1,172 @@
|
||||||
|
# Running headscale on Linux
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
This documentation has the goal of showing a user how-to set up and run `headscale` on Linux.
|
||||||
|
In additional to the "get up and running section", there is an optional [SystemD section](#running-headscale-in-the-background-with-systemd)
|
||||||
|
describing how to make `headscale` run properly in a server environment.
|
||||||
|
|
||||||
|
## Configure and run `headscale`
|
||||||
|
|
||||||
|
1. Download the latest [`headscale` binary from GitHub's release page](https://github.com/juanfont/headscale/releases):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
wget --output-document=/usr/local/bin/headscale \
|
||||||
|
https://github.com/juanfont/headscale/releases/download/v<HEADSCALE VERSION>/headscale_<HEADSCALE VERSION>_linux_<ARCH>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Make `headscale` executable:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
chmod +x /usr/local/bin/headscale
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Prepare a direction 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
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Create an empty SQlite datebase:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
touch /var/lib/headscale/db.sqlite
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Create a `headscale` configuration:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
touch /etc/headscale/config.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
It is **strongly recommended** to copy and modifiy the [example configuration](../config.yaml)
|
||||||
|
from the [headscale repository](../)
|
||||||
|
|
||||||
|
6. 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) or [screen](https://www.gnu.org/software/screen/).
|
||||||
|
|
||||||
|
To run `headscale` in the background, please follow the steps in the [SystemD section](#running-headscale-in-the-background-with-systemd) before continuing.
|
||||||
|
|
||||||
|
7. Verify `headscale` is running:
|
||||||
|
|
||||||
|
Verify `headscale` is available:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl http://127.0.0.1:8080/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
8. 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 SystemD
|
||||||
|
|
||||||
|
In this section it will be demonstrated how to run `headscale` as a service in the background with [SystemD](https://www.freedesktop.org/wiki/Software/systemd/).
|
||||||
|
This should work on most modern Linux distributions.
|
||||||
|
|
||||||
|
1. Create a SystemD service configuration at `/etc/systemd/system/headscale.service` containing:
|
||||||
|
|
||||||
|
```systemd
|
||||||
|
[Unit]
|
||||||
|
Description=headscale controller
|
||||||
|
After=syslog.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=headscale
|
||||||
|
Group=headscale
|
||||||
|
ExecStart=/usr/local/bin/headscale serve
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Optional security enhancements
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
ReadWritePaths=/var/lib/headscale /var/run/headscale
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||||
|
RuntimeDirectory=headscale
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
2. In `/etc/headscale/config.yaml`, override the default `headscale` unix socket with a SystemD friendly path:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
unix_socket: /var/run/headscale/headscale.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Reload SystemD to load the new configuration file:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Enable and start the new `headscale` service:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
systemctl enable headscale
|
||||||
|
systemctl start headscale
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Verify the headscale service:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
systemctl status headscale
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify `headscale` is available:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl http://127.0.0.1:8080/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
`headscale` will now run in the background and start at boot.
|
|
@ -1,5 +1,9 @@
|
||||||
# Running the service via TLS (optional)
|
# Running the service via TLS (optional)
|
||||||
|
|
||||||
|
## 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. The certificate will automatically be renewed as needed.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
tls_letsencrypt_hostname: ""
|
tls_letsencrypt_hostname: ""
|
||||||
tls_letsencrypt_listen: ":http"
|
tls_letsencrypt_listen: ":http"
|
||||||
|
@ -7,21 +11,21 @@ tls_letsencrypt_cache_dir: ".cache"
|
||||||
tls_letsencrypt_challenge_type: HTTP-01
|
tls_letsencrypt_challenge_type: HTTP-01
|
||||||
```
|
```
|
||||||
|
|
||||||
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. The certificate will automatically be renewed as needed.
|
### Challenge type HTTP-01
|
||||||
|
|
||||||
```yaml
|
|
||||||
tls_cert_path: ""
|
|
||||||
tls_key_path: ""
|
|
||||||
```
|
|
||||||
|
|
||||||
headscale can also be configured to expose its web service via TLS. To configure the certificate and key file manually, set the `tls_cert_path` and `tls_cert_path` configuration parameters. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
|
||||||
|
|
||||||
## Challenge type HTTP-01
|
|
||||||
|
|
||||||
The default challenge type `HTTP-01` requires that headscale is reachable on port 80 for the Let's Encrypt automated validation, in addition to whatever port is configured in `listen_addr`. By default, headscale listens on port 80 on all local IPs for Let's Encrypt automated validation.
|
The default challenge type `HTTP-01` requires that headscale is reachable on port 80 for the Let's Encrypt automated validation, in addition to whatever port is configured in `listen_addr`. By default, headscale listens on port 80 on all local IPs for Let's Encrypt automated validation.
|
||||||
|
|
||||||
If you need to change the ip and/or port used by headscale for the Let's Encrypt validation process, set `tls_letsencrypt_listen` to the appropriate value. This can be handy if you are running headscale as a non-root user (or can't run `setcap`). Keep in mind, however, that Let's Encrypt will _only_ connect to port 80 for the validation callback, so if you change `tls_letsencrypt_listen` you will also need to configure something else (e.g. a firewall rule) to forward the traffic from port 80 to the ip:port combination specified in `tls_letsencrypt_listen`.
|
If you need to change the ip and/or port used by headscale for the Let's Encrypt validation process, set `tls_letsencrypt_listen` to the appropriate value. This can be handy if you are running headscale as a non-root user (or can't run `setcap`). Keep in mind, however, that Let's Encrypt will _only_ connect to port 80 for the validation callback, so if you change `tls_letsencrypt_listen` you will also need to configure something else (e.g. a firewall rule) to forward the traffic from port 80 to the ip:port combination specified in `tls_letsencrypt_listen`.
|
||||||
|
|
||||||
## Challenge type TLS-ALPN-01
|
### Challenge type TLS-ALPN-01
|
||||||
|
|
||||||
Alternatively, `tls_letsencrypt_challenge_type` can be set to `TLS-ALPN-01`. In this configuration, headscale listens on the ip:port combination defined in `listen_addr`. Let's Encrypt will _only_ connect to port 443 for the validation callback, so if `listen_addr` is not set to port 443, something else (e.g. a firewall rule) will be required to forward the traffic from port 443 to the ip:port combination specified in `listen_addr`.
|
Alternatively, `tls_letsencrypt_challenge_type` can be set to `TLS-ALPN-01`. In this configuration, headscale listens on the ip:port combination defined in `listen_addr`. Let's Encrypt will _only_ connect to port 443 for the validation callback, so if `listen_addr` is not set to port 443, something else (e.g. a firewall rule) will be required to forward the traffic from port 443 to the ip:port combination specified in `listen_addr`.
|
||||||
|
|
||||||
|
## Bring your own certificate
|
||||||
|
|
||||||
|
headscale can also be configured to expose its web service via TLS. To configure the certificate and key file manually, set the `tls_cert_path` and `tls_cert_path` configuration parameters. If the path is relative, it will be interpreted as relative to the directory the configuration file was read from.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
tls_cert_path: ""
|
||||||
|
tls_key_path: ""
|
||||||
|
```
|
Loading…
Reference in New Issue