Compare commits

..

3 commits

Author SHA1 Message Date
Kristoffer Dalby
b25c2c7f09
update nix hash
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-11-04 10:14:30 -06:00
Kristoffer Dalby
1d0768c135
conf
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-10-24 09:46:46 -05:00
Kristoffer Dalby
67b5528f74
linter fixes
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-10-24 09:38:33 -05:00
27 changed files with 117 additions and 337 deletions

16
.github/CODEOWNERS vendored
View file

@ -1,10 +1,10 @@
* @juanfont @kradalby * @juanfont @kradalby
*.md @ohdearaugustin @nblock *.md @ohdearaugustin
*.yml @ohdearaugustin @nblock *.yml @ohdearaugustin
*.yaml @ohdearaugustin @nblock *.yaml @ohdearaugustin
Dockerfile* @ohdearaugustin @nblock Dockerfile* @ohdearaugustin
.goreleaser.yaml @ohdearaugustin @nblock .goreleaser.yaml @ohdearaugustin
/docs/ @ohdearaugustin @nblock /docs/ @ohdearaugustin
/.github/workflows/ @ohdearaugustin @nblock /.github/workflows/ @ohdearaugustin
/.github/renovate.json @ohdearaugustin @nblock /.github/renovate.json @ohdearaugustin

View file

@ -154,7 +154,7 @@ kos:
- "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}.{{ .Patch }}-debug{{ end }}" - "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}.{{ .Patch }}-debug{{ end }}"
- "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}-debug{{ end }}" - "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}-debug{{ end }}"
- "{{ if not .Prerelease }}v{{ .Major }}-debug{{ end }}" - "{{ if not .Prerelease }}v{{ .Major }}-debug{{ end }}"
- "{{ if not .Prerelease }}stable-debug{{ else }}unstable-debug{{ end }}" - "{{ if not .Prerelease }}stable{{ else }}unstable-debug{{ end }}"
- "{{ .Tag }}-debug" - "{{ .Tag }}-debug"
- '{{ trimprefix .Tag "v" }}-debug' - '{{ trimprefix .Tag "v" }}-debug'
- "sha-{{ .ShortCommit }}-debug" - "sha-{{ .ShortCommit }}-debug"
@ -177,7 +177,7 @@ kos:
- "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}.{{ .Patch }}-debug{{ end }}" - "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}.{{ .Patch }}-debug{{ end }}"
- "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}-debug{{ end }}" - "{{ if not .Prerelease }}v{{ .Major }}.{{ .Minor }}-debug{{ end }}"
- "{{ if not .Prerelease }}v{{ .Major }}-debug{{ end }}" - "{{ if not .Prerelease }}v{{ .Major }}-debug{{ end }}"
- "{{ if not .Prerelease }}stable-debug{{ else }}unstable-debug{{ end }}" - "{{ if not .Prerelease }}stable{{ else }}unstable-debug{{ end }}"
- "{{ .Tag }}-debug" - "{{ .Tag }}-debug"
- '{{ trimprefix .Tag "v" }}-debug' - '{{ trimprefix .Tag "v" }}-debug'
- "sha-{{ .ShortCommit }}-debug" - "sha-{{ .ShortCommit }}-debug"

View file

@ -1,3 +1,2 @@
.github/workflows/test-integration-v2* .github/workflows/test-integration-v2*
docs/about/features.md docs/about/features.md
docs/ref/remote-cli.md

View file

@ -22,7 +22,6 @@
- Fixed processing of fields in post request in MoveNode rpc [#2179](https://github.com/juanfont/headscale/pull/2179) - Fixed processing of fields in post request in MoveNode rpc [#2179](https://github.com/juanfont/headscale/pull/2179)
- Added conversion of 'Hostname' to 'givenName' in a node with FQDN rules applied [#2198](https://github.com/juanfont/headscale/pull/2198) - Added conversion of 'Hostname' to 'givenName' in a node with FQDN rules applied [#2198](https://github.com/juanfont/headscale/pull/2198)
- Fixed updating of hostname and givenName when it is updated in HostInfo [#2199](https://github.com/juanfont/headscale/pull/2199) - Fixed updating of hostname and givenName when it is updated in HostInfo [#2199](https://github.com/juanfont/headscale/pull/2199)
- Fixed missing `stable-debug` container tag [#2232](https://github.com/juanfont/headscale/pr/2232)
## 0.23.0 (2024-09-18) ## 0.23.0 (2024-09-18)

View file

@ -62,7 +62,7 @@ event.
Instances of abusive, harassing, or otherwise unacceptable behavior Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported to the community leaders responsible for enforcement may be reported to the community leaders responsible for enforcement
on our [Discord server](https://discord.gg/c84AZQhmpx). All complaints at our Discord channel. All complaints
will be reviewed and investigated promptly and fairly. will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and All community leaders are obligated to respect the privacy and

View file

@ -28,9 +28,7 @@ ARG VERSION_GIT_HASH=""
ENV VERSION_GIT_HASH=$VERSION_GIT_HASH ENV VERSION_GIT_HASH=$VERSION_GIT_HASH
ARG TARGETARCH ARG TARGETARCH
ARG BUILD_TAGS="" RUN GOARCH=$TARGETARCH go install -ldflags="\
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" \

View file

@ -4,7 +4,7 @@
An open source, self-hosted implementation of the Tailscale control server. An open source, self-hosted implementation of the Tailscale control server.
Join our [Discord server](https://discord.gg/c84AZQhmpx) for a chat. Join our [Discord](https://discord.gg/c84AZQhmpx) server for a chat.
**Note:** Always select the same GitHub tag as the released version you use **Note:** Always select the same GitHub tag as the released version you use
to ensure you have the correct example configuration and documentation. to ensure you have the correct example configuration and documentation.

View file

@ -13,4 +13,3 @@ headscale.
| Android | Yes (see [docs](../usage/connect/android.md)) | | Android | Yes (see [docs](../usage/connect/android.md)) |
| macOS | Yes (see [docs](../usage/connect/apple.md#macos) and `/apple` on your headscale for more information) | | macOS | Yes (see [docs](../usage/connect/apple.md#macos) and `/apple` on your headscale for more information) |
| iOS | Yes (see [docs](../usage/connect/apple.md#ios) and `/apple` on your headscale for more information) | | iOS | Yes (see [docs](../usage/connect/apple.md#ios) and `/apple` on your headscale for more information) |
| tvOS | Yes (see [docs](../usage/connect/apple.md#tvos) and `/apple` on your headscale for more information) |

View file

@ -41,15 +41,13 @@ In addition to that, you may use packages provided by the community or from dist
[installation guide using community packages](../setup/install/community.md). [installation guide using community packages](../setup/install/community.md).
For convenience, we also [build Docker images with headscale](../setup/install/container.md). But **please be aware that For convenience, we also [build Docker images with headscale](../setup/install/container.md). But **please be aware that
we don't officially support deploying headscale using Docker**. On our [Discord server](https://discord.gg/c84AZQhmpx) we don't officially support deploying headscale using Docker**. We have a [Discord
we have a "docker-issues" channel where you can ask for Docker-specific help to the community. channel](https://discord.com/channels/896711691637780480/1070619770942148618) where you can ask for Docker-specific help
to the community.
## Why is my reverse proxy not working with headscale? ## Why is my reverse proxy not working with headscale?
We don't know. We don't use reverse proxies with headscale ourselves, so we don't have any experience with them. We have We don't know. We don't use reverse proxies with headscale ourselves, so we don't have any experience with them. We have [community documentation](../ref/integration/reverse-proxy.md) on how to configure various reverse proxies, and a dedicated [Discord channel](https://discord.com/channels/896711691637780480/1070619818346164324) where you can ask for help to the community.
[community documentation](../ref/integration/reverse-proxy.md) on how to configure various reverse proxies, and a
dedicated "reverse-proxy-issues" channel on our [Discord server](https://discord.gg/c84AZQhmpx) where you can ask for
help to the community.
## Can I use headscale and tailscale on the same machine? ## Can I use headscale and tailscale on the same machine?

View file

@ -1,5 +1,11 @@
# Getting help # Getting help
Join our [Discord server](https://discord.gg/c84AZQhmpx) for announcements and community support. Join our Discord server for announcements and community support:
- [announcements](https://discord.com/channels/896711691637780480/896711692120129538)
- [general](https://discord.com/channels/896711691637780480/896711692120129540)
- [docker-issues](https://discord.com/channels/896711691637780480/1070619770942148618)
- [reverse-proxy-issues](https://discord.com/channels/896711691637780480/1070619818346164324)
- [web-interfaces](https://discord.com/channels/896711691637780480/1105842846386356294)
Please report bugs via [GitHub issues](https://github.com/juanfont/headscale/issues) Please report bugs via [GitHub issues](https://github.com/juanfont/headscale/issues)

View file

@ -6,4 +6,5 @@ code archives. Container images are available on [Docker Hub](https://hub.docker
An Atom/RSS feed of headscale releases is available [here](https://github.com/juanfont/headscale/releases.atom). An Atom/RSS feed of headscale releases is available [here](https://github.com/juanfont/headscale/releases.atom).
See the "announcements" channel on our [Discord server](https://discord.gg/c84AZQhmpx) for news about headscale. Join the ["announcements" channel on Discord](https://discord.com/channels/896711691637780480/896711692120129538) for
news about headscale.

View file

@ -10,7 +10,7 @@ Headscale is an open source, self-hosted implementation of the Tailscale control
This page contains the documentation for the latest version of headscale. Please also check our [FAQ](./about/faq.md). This page contains the documentation for the latest version of headscale. Please also check our [FAQ](./about/faq.md).
Join our [Discord server](https://discord.gg/c84AZQhmpx) for a chat and community support. Join our [Discord](https://discord.gg/c84AZQhmpx) server for a chat and community support.
## Design goal ## Design goal

View file

@ -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](../usage/getting-started.md#register-a-node) we When registering the servers we will need to add the flag
will need to add the flag `--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user `--advertise-tags=tag:<tag1>,tag:<tag2>`, and the user that is
that is registering the server should be allowed to do it. Since anyone can add registering the server should be allowed to do it. Since anyone can add tags to
tags to a server they can register, the check of the tags is done on headscale a server they can register, the check of the tags is done on headscale server
server and only valid tags are applied. A tag is valid if the user that is 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/).

View file

@ -1,12 +0,0 @@
# Tools related to headscale
!!! warning "Community contributions"
This page contains community contributions. The projects listed here are not
maintained by the headscale authors and are written by community members.
This page collects third-party tools and scripts related to headscale.
| Name | Repository Link | Description |
| ----------------- | --------------------------------------------------------------- | ------------------------------------------------- |
| tailscale-manager | [Github](https://github.com/singlestore-labs/tailscale-manager) | Dynamically manage Tailscale route advertisements |

View file

@ -1,19 +1,17 @@
# Web interfaces for headscale # Headscale web interface
!!! warning "Community contributions" !!! warning "Community contributions"
This page contains community contributions. The projects listed here are not This page contains community contributions. The projects listed here are not
maintained by the headscale authors and are written by community members. maintained by the headscale authors and are written by community members.
Headscale doesn't provide a built-in web interface but users may pick one from the available options. | Name | Repository Link | Description | Status |
| --------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------ |
| headscale-webui | [Github](https://github.com/ifargle/headscale-webui) | A simple headscale web UI for small-scale deployments. | Alpha |
| headscale-ui | [Github](https://github.com/gurucomputing/headscale-ui) | A web frontend for the headscale Tailscale-compatible coordination server | Alpha |
| HeadscaleUi | [GitHub](https://github.com/simcu/headscale-ui) | A static headscale admin ui, no backend enviroment required | Alpha |
| Headplane | [GitHub](https://github.com/tale/headplane) | An advanced Tailscale inspired frontend for headscale | Alpha |
| headscale-admin | [Github](https://github.com/GoodiesHQ/headscale-admin) | Headscale-Admin is meant to be a simple, modern web interface for headscale | Beta |
| ouroboros | [Github](https://github.com/yellowsink/ouroboros) | Ouroboros is designed for users to manage their own devices, rather than for admins | Stable |
| Name | Repository Link | Description | You can ask for support on our dedicated [Discord channel](https://discord.com/channels/896711691637780480/1105842846386356294).
| --------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| headscale-webui | [Github](https://github.com/ifargle/headscale-webui) | A simple headscale web UI for small-scale deployments. |
| headscale-ui | [Github](https://github.com/gurucomputing/headscale-ui) | A web frontend for the headscale Tailscale-compatible coordination server |
| HeadscaleUi | [GitHub](https://github.com/simcu/headscale-ui) | A static headscale admin ui, no backend enviroment required |
| Headplane | [GitHub](https://github.com/tale/headplane) | An advanced Tailscale inspired frontend for headscale |
| headscale-admin | [Github](https://github.com/GoodiesHQ/headscale-admin) | Headscale-Admin is meant to be a simple, modern web interface for headscale |
| ouroboros | [Github](https://github.com/yellowsink/ouroboros) | Ouroboros is designed for users to manage their own devices, rather than for admins |
You can ask for support on our [Discord server](https://discord.gg/c84AZQhmpx) in the "web-interfaces" channel.

View file

@ -1,21 +1,22 @@
# Controlling headscale with remote CLI # Controlling headscale with remote CLI
This documentation has the goal of showing a user how-to control a headscale instance This documentation has the goal of showing a user how-to set control a headscale instance
from a remote machine with the `headscale` command line binary. from a remote machine with the `headscale` command line binary.
## Prerequisite ## Prerequisite
- A workstation to run `headscale` (any supported platform, e.g. Linux). - A workstation to run headscale (could be Linux, macOS, other supported platforms)
- A headscale server with gRPC enabled. - A headscale server (version `0.13.0` or newer)
- Connections to the gRPC port (default: `50443`) are allowed. - Access to create API keys (local access to the headscale server)
- Remote access requires an encrypted connection via TLS. - headscale _must_ be served over TLS/HTTPS
- An API key to authenticate with the headscale server. - Remote access does _not_ support unencrypted traffic.
- Port `50443` must be open in the firewall (or port overridden by `grpc_listen_addr` option)
## Create an API key ## Create an API key
We need to create an API key to authenticate with the remote headscale server when using it from our workstation. We need to create an API key to authenticate our remote headscale when using it from our workstation.
To create an API key, log into your headscale server and generate a key: To create a API key, log into your headscale server and generate a key:
```shell ```shell
headscale apikeys create --expiration 90d headscale apikeys create --expiration 90d
@ -24,7 +25,7 @@ headscale apikeys create --expiration 90d
Copy the output of the command and save it for later. Please note that you can not retrieve a key again, Copy the output of the command and save it for later. Please note that you can not retrieve a key again,
if the key is lost, expire the old one, and create a new key. if the key is lost, expire the old one, and create a new key.
To list the keys currently associated with the server: To list the keys currently assosicated with the server:
```shell ```shell
headscale apikeys list headscale apikeys list
@ -38,8 +39,7 @@ headscale apikeys expire --prefix "<PREFIX>"
## Download and configure headscale ## Download and configure headscale
1. Download the [`headscale` binary from GitHub's release page](https://github.com/juanfont/headscale/releases). Make 1. Download the latest [`headscale` binary from GitHub's release page](https://github.com/juanfont/headscale/releases):
sure to use the same version as on the server.
1. Put the binary somewhere in your `PATH`, e.g. `/usr/local/bin/headscale` 1. Put the binary somewhere in your `PATH`, e.g. `/usr/local/bin/headscale`
@ -49,32 +49,25 @@ headscale apikeys expire --prefix "<PREFIX>"
chmod +x /usr/local/bin/headscale chmod +x /usr/local/bin/headscale
``` ```
1. Provide the connection parameters for the remote headscale server either via a minimal YAML configuration file or via 1. Configure the CLI through environment variables
environment variables:
=== "Minimal YAML configuration file" ```shell
export HEADSCALE_CLI_ADDRESS="<HEADSCALE ADDRESS>:<PORT>"
export HEADSCALE_CLI_API_KEY="<API KEY FROM PREVIOUS STAGE>"
```
```yaml for example:
cli:
address: <HEADSCALE_ADDRESS>:<PORT>
api_key: <API_KEY_FROM_PREVIOUS_STEP>
```
=== "Environment variables" ```shell
export HEADSCALE_CLI_ADDRESS="headscale.example.com:50443"
export HEADSCALE_CLI_API_KEY="abcde12345"
```
```shell This will tell the `headscale` binary to connect to a remote instance, instead of looking
export HEADSCALE_CLI_ADDRESS="<HEADSCALE_ADDRESS>:<PORT>" for a local instance (which is what it does on the server).
export HEADSCALE_CLI_API_KEY="<API_KEY_FROM_PREVIOUS_STEP>"
```
!!! bug The API key is needed to make sure that you are allowed to access the server. The key is _not_
needed when running directly on the server, as the connection is local.
Headscale 0.23.0 requires at least an empty configuration file when environment variables are used to
specify connection details. See [issue 2193](https://github.com/juanfont/headscale/issues/2193) for more
information.
This instructs the `headscale` binary to connect to a remote instance at `<HEADSCALE_ADDRESS>:<PORT>`, instead of
connecting to the local instance.
1. Test the connection 1. Test the connection
@ -96,10 +89,10 @@ While this is _not a supported_ feature, an example on how this can be set up on
## Troubleshooting ## Troubleshooting
- Make sure you have the _same_ headscale version on your server and workstation. Checklist:
- Ensure that connections to the gRPC port are allowed.
- Verify that your TLS certificate is valid and trusted. - Make sure you have the _same_ headscale version on your server and workstation
- If you don't have access to a trusted certificate (e.g. from Let's Encrypt), either: - Make sure you use version `0.13.0` or newer.
- Add your self-signed certificate to the trust store of your OS _or_ - Verify that your TLS certificate is valid and trusted
- Disable certificate verification by either setting `cli.insecure: true` in the configuration file or by setting - If you do not have access to a trusted certificate (e.g. from Let's Encrypt), add your self signed certificate to the trust store of your OS or
`HEADSCALE_CLI_INSECURE=1` via an environment variable. We do **not** recommend to disable certificate validation. - Set `HEADSCALE_CLI_INSECURE` to 0 in your environment

View file

@ -9,8 +9,6 @@ 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.

View file

@ -28,7 +28,7 @@ development version.
## Fedora, RHEL, CentOS ## Fedora, RHEL, CentOS
A third-party repository for various RPM based distributions is available at: A 3rd-party repository for various RPM based distributions is available at:
<https://copr.fedorainfracloud.org/coprs/jonathanspw/headscale/>. The site provides detailed setup and installation <https://copr.fedorainfracloud.org/coprs/jonathanspw/headscale/>. The site provides detailed setup and installation
instructions. instructions.

View file

@ -47,23 +47,3 @@ tailscale login --login-server <YOUR_HEADSCALE_URL>
- Under `Custom Login Server`, select `Add Account...` - Under `Custom Login Server`, select `Add Account...`
- Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `Add Account` - Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `Add Account`
- Follow the login procedure in the browser - Follow the login procedure in the browser
## tvOS
### Installation
Install the official Tailscale tvOS client from the [App Store](https://apps.apple.com/app/tailscale/id1470499037).
!!! danger
**Don't** open the Tailscale App after installation!
### Configuring the headscale URL
- Open Settings (the Apple tvOS settings) > Apps > Tailscale
- Under `ALTERNATE COORDINATION SERVER URL`, select `URL`
- Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `OK`
- Return to the tvOS Home screen
- Open Tailscale
- Click the button `Install VPN configuration` and confirm the appearing popup by clicking the `Allow` button
- Scan the QR code and follow the login procedure

View file

@ -9,8 +9,6 @@ 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.

View file

@ -5,11 +5,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1731533236, "lastModified": 1726560853,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1731763621, "lastModified": 1728093190,
"narHash": "sha256-ddcX4lQL0X05AYkrkV2LMFgGdRvgap7Ho8kgon3iWZk=", "narHash": "sha256-CAZF2NRuHmqTtRTNAruWpHA43Gg2UvuCNEIzabP0l6M=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c69a9bffbecde46b4b939465422ddc59493d3e4d", "rev": "e2f08f4d8b3ecb5cf5c9fd9cb2d53bb3c71807da",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -460,7 +460,6 @@ func (h *Headscale) createRouter(grpcMux *grpcRuntime.ServeMux) *mux.Router {
if h.cfg.DERP.ServerEnabled { if h.cfg.DERP.ServerEnabled {
router.HandleFunc("/derp", h.DERPServer.DERPHandler) router.HandleFunc("/derp", h.DERPServer.DERPHandler)
router.HandleFunc("/derp/probe", derpServer.DERPProbeHandler) router.HandleFunc("/derp/probe", derpServer.DERPProbeHandler)
router.HandleFunc("/derp/latency-check", derpServer.DERPProbeHandler)
router.HandleFunc("/bootstrap-dns", derpServer.DERPBootstrapDNSHandler(h.DERPMap)) router.HandleFunc("/bootstrap-dns", derpServer.DERPBootstrapDNSHandler(h.DERPMap))
} }

View file

@ -78,7 +78,7 @@ func prometheusMiddleware(next http.Handler) http.Handler {
// Ignore streaming and noise sessions // Ignore streaming and noise sessions
// it has its own router further down. // it has its own router further down.
if path == "/ts2021" || path == "/machine/map" || path == "/derp" || path == "/derp/probe" || path == "/derp/latency-check" || path == "/bootstrap-dns" { if path == "/ts2021" || path == "/machine/map" || path == "/derp" || path == "/derp/probe" || path == "/bootstrap-dns" {
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
return return
} }

View file

@ -17,13 +17,9 @@ func Apple(url string) *elem.Element {
headerOne("headscale: iOS configuration"), headerOne("headscale: iOS configuration"),
headerTwo("GUI"), headerTwo("GUI"),
elem.Ol(nil, elem.Ol(nil,
elem.Li( elem.Li(nil,
nil,
elem.Text("Install the official Tailscale iOS client from the "), elem.Text("Install the official Tailscale iOS client from the "),
elem.A( elem.A(attrs.Props{attrs.Href: "https://apps.apple.com/app/tailscale/id1470499037"},
attrs.Props{
attrs.Href: "https://apps.apple.com/app/tailscale/id1470499037",
},
elem.Text("App store"), elem.Text("App store"),
), ),
), ),
@ -35,47 +31,27 @@ func Apple(url string) *elem.Element {
elem.Li(nil, elem.Li(nil,
elem.Text("Open Settings on the iOS device"), elem.Text("Open Settings on the iOS device"),
), ),
elem.Li( elem.Li(nil,
nil, elem.Text(`Scroll down to the "third party apps" section, under "Game Center" or "TV Provider"`),
elem.Text(
`Scroll down to the "third party apps" section, under "Game Center" or "TV Provider"`,
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text("Find Tailscale and select it"), elem.Text("Find Tailscale and select it"),
elem.Ul(nil, elem.Ul(nil,
elem.Li( elem.Li(nil,
nil, elem.Text(`If the iOS device was previously logged into Tailscale, switch the "Reset Keychain" toggle to "on"`),
elem.Text(
`If the iOS device was previously logged into Tailscale, switch the "Reset Keychain" toggle to "on"`,
),
), ),
), ),
), ),
elem.Li( elem.Li(nil,
nil, elem.Text(fmt.Sprintf(`Enter "%s" under "Alternate Coordination Server URL"`, url)),
elem.Text(
fmt.Sprintf(
`Enter "%s" under "Alternate Coordination Server URL"`,
url,
),
),
), ),
elem.Li( elem.Li(nil,
nil, elem.Text("Restart the app by closing it from the iOS app switcher, open the app and select the regular sign in option "),
elem.Text(
"Restart the app by closing it from the iOS app switcher, open the app and select the regular sign in option ",
),
elem.I(nil, elem.Text("(non-SSO)")), elem.I(nil, elem.Text("(non-SSO)")),
elem.Text( elem.Text(". It should open up to the headscale authentication page."),
". It should open up to the headscale authentication page.",
),
), ),
elem.Li( elem.Li(nil,
nil, elem.Text("Enter your credentials and log in. Headscale should now be working on your iOS device"),
elem.Text(
"Enter your credentials and log in. Headscale should now be working on your iOS device",
),
), ),
), ),
headerOne("headscale: macOS configuration"), headerOne("headscale: macOS configuration"),
@ -90,58 +66,34 @@ func Apple(url string) *elem.Element {
), ),
headerTwo("GUI"), headerTwo("GUI"),
elem.Ol(nil, elem.Ol(nil,
elem.Li( elem.Li(nil,
nil, elem.Text("ALT + Click the Tailscale icon in the menu and hover over the Debug menu"),
elem.Text(
"ALT + Click the Tailscale icon in the menu and hover over the Debug menu",
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`Under "Custom Login Server", select "Add Account..."`), elem.Text(`Under "Custom Login Server", select "Add Account..."`),
), ),
elem.Li( elem.Li(nil,
nil, elem.Text(fmt.Sprintf(`Enter "%s" of the headscale instance and press "Add Account"`, url)),
elem.Text(
fmt.Sprintf(
`Enter "%s" of the headscale instance and press "Add Account"`,
url,
),
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`Follow the login procedure in the browser`), elem.Text(`Follow the login procedure in the browser`),
), ),
), ),
headerTwo("Profiles"), headerTwo("Profiles"),
elem.P( elem.P(nil,
nil, elem.Text("Headscale can be set to the default server by installing a Headscale configuration profile:"),
elem.Text(
"Headscale can be set to the default server by installing a Headscale configuration profile:",
),
), ),
elem.P( elem.P(nil,
nil, elem.A(attrs.Props{attrs.Href: "/apple/macos-app-store", attrs.Download: "headscale_macos.mobileconfig"},
elem.A(
attrs.Props{
attrs.Href: "/apple/macos-app-store",
attrs.Download: "headscale_macos.mobileconfig",
},
elem.Text("macOS AppStore profile "), elem.Text("macOS AppStore profile "),
), ),
elem.A( elem.A(attrs.Props{attrs.Href: "/apple/macos-standalone", attrs.Download: "headscale_macos.mobileconfig"},
attrs.Props{
attrs.Href: "/apple/macos-standalone",
attrs.Download: "headscale_macos.mobileconfig",
},
elem.Text("macOS Standalone profile"), elem.Text("macOS Standalone profile"),
), ),
), ),
elem.Ol(nil, elem.Ol(nil,
elem.Li( elem.Li(nil,
nil, elem.Text("Download the profile, then open it. When it has been opened, there should be a notification that a profile can be installed"),
elem.Text(
"Download the profile, then open it. When it has been opened, there should be a notification that a profile can be installed",
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`Open System Preferences and go to "Profiles"`), elem.Text(`Open System Preferences and go to "Profiles"`),
@ -154,35 +106,20 @@ func Apple(url string) *elem.Element {
), ),
), ),
elem.P(nil, elem.Text("Or")), elem.P(nil, elem.Text("Or")),
elem.P( elem.P(nil,
nil, elem.Text("Use your terminal to configure the default setting for Tailscale by issuing:"),
elem.Text(
"Use your terminal to configure the default setting for Tailscale by issuing:",
),
), ),
elem.Ul(nil, elem.Ul(nil,
elem.Li(nil, elem.Li(nil,
elem.Text(`for app store client:`), elem.Text(`for app store client:`),
elem.Code( elem.Code(nil,
nil, elem.Text(fmt.Sprintf(`defaults write io.tailscale.ipn.macos ControlURL %s`, url)),
elem.Text(
fmt.Sprintf(
`defaults write io.tailscale.ipn.macos ControlURL %s`,
url,
),
),
), ),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`for standalone client:`), elem.Text(`for standalone client:`),
elem.Code( elem.Code(nil,
nil, elem.Text(fmt.Sprintf(`defaults write io.tailscale.ipn.macsys ControlURL %s`, url)),
elem.Text(
fmt.Sprintf(
`defaults write io.tailscale.ipn.macsys ControlURL %s`,
url,
),
),
), ),
), ),
), ),
@ -190,11 +127,8 @@ func Apple(url string) *elem.Element {
elem.Text("Restart Tailscale.app and log in."), elem.Text("Restart Tailscale.app and log in."),
), ),
headerThree("Caution"), headerThree("Caution"),
elem.P( elem.P(nil,
nil, elem.Text("You should always download and inspect the profile before installing it:"),
elem.Text(
"You should always download and inspect the profile before installing it:",
),
), ),
elem.Ul(nil, elem.Ul(nil,
elem.Li(nil, elem.Li(nil,
@ -210,53 +144,6 @@ func Apple(url string) *elem.Element {
), ),
), ),
), ),
headerOne("headscale: tvOS configuration"),
headerTwo("GUI"),
elem.Ol(nil,
elem.Li(
nil,
elem.Text("Install the official Tailscale tvOS client from the "),
elem.A(
attrs.Props{
attrs.Href: "https://apps.apple.com/app/tailscale/id1470499037",
},
elem.Text("App store"),
),
),
elem.Li(
nil,
elem.Text(
"Open Settings (the Apple tvOS settings) > Apps > Tailscale",
),
),
elem.Li(
nil,
elem.Text(
fmt.Sprintf(
`Enter "%s" under "ALTERNATE COORDINATION SERVER URL"`,
url,
),
),
),
elem.Li(nil,
elem.Text("Return to the tvOS Home screen"),
),
elem.Li(nil,
elem.Text("Open Tailscale"),
),
elem.Li(nil,
elem.Text(`Select "Install VPN configuration"`),
),
elem.Li(nil,
elem.Text(`Select "Allow"`),
),
elem.Li(nil,
elem.Text("Scan the QR code and follow the login procedure"),
),
elem.Li(nil,
elem.Text("Headscale should now be working on your tvOS device"),
),
),
), ),
) )
} }

View file

@ -55,7 +55,7 @@ func TestDERPServerWebsocketScenario(t *testing.T) {
spec := map[string]ClientsSpec{ spec := map[string]ClientsSpec{
"user1": { "user1": {
Plain: 0, Plain: 0,
WebsocketDERP: 2, WebsocketDERP: len(MustTestVersions),
}, },
} }
@ -239,13 +239,10 @@ 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,
tsic.VersionHead, "all",
clientCount.WebsocketDERP, clientCount.WebsocketDERP,
tsic.WithWebsocketDERP(true), tsic.WithWebsocketDERP(true),
) )

View file

@ -12,7 +12,6 @@ import (
"net/netip" "net/netip"
"net/url" "net/url"
"os" "os"
"reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -45,11 +44,6 @@ 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 {
@ -80,13 +74,6 @@ 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
@ -188,22 +175,6 @@ 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,
@ -248,12 +219,6 @@ 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),
@ -280,36 +245,14 @@ 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 VersionHead: case "head":
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,

View file

@ -183,4 +183,3 @@ nav:
- Integration: - Integration:
- Reverse proxy: ref/integration/reverse-proxy.md - Reverse proxy: ref/integration/reverse-proxy.md
- Web UI: ref/integration/web-ui.md - Web UI: ref/integration/web-ui.md
- Tools: ref/integration/tools.md