From 90e840c3c93cae2c0ac133eb1cf67d637946fa02 Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Sun, 4 Sep 2022 09:42:23 -0700 Subject: [PATCH 1/8] Add reverse proxy documentation --- docs/README.md | 1 + docs/reverse-proxy.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 docs/reverse-proxy.md diff --git a/docs/README.md b/docs/README.md index 9f8e681a..dfad6116 100644 --- a/docs/README.md +++ b/docs/README.md @@ -28,6 +28,7 @@ written by community members. It is _not_ verified by `headscale` developers. - [Running headscale in a container](running-headscale-container.md) - [Running headscale on OpenBSD](running-headscale-openbsd.md) +- [Running headscale behind a reverse proxy](reverse-proxy.md) ## Misc diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md new file mode 100644 index 00000000..c9a1d1b7 --- /dev/null +++ b/docs/reverse-proxy.md @@ -0,0 +1,43 @@ +# Running behind a reverse proxy + +Running Headscale behind a reverse proxy is suitable for container-based deployments. This is especially useful on a server were port 443 is already being used for other web services. + +Headscale can be configured not to use TLS, leaving it to the reverse proxy to handle. Add the following configuration values to your headscale config file. + +```yaml +server_url: https:// # This should be the FQDN at which headscale will be served +listen_addr: 0.0.0.0:8080 +metrics_listen_addr: 0.0.0.0:9090 +tls_cert_path: "" +tls_key_path: "" +``` + +## nginx +The following example configuration can be used in your nginx setup, substituting values as necessary. `` should be the IP address and port where headscale is running. In most cases, this will be `http://localhost:8080`. + +```Nginx +server { + listen 80; + listen [::]:80; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name ; + + ssl_certificate ; + ssl_certificate_key ; + ssl_protocols TLSv1.2 TLSv1.3; + + location / { + proxy_pass http://; + proxy_set_header Host $server_name; + proxy_redirect http:// https://; + proxy_buffering off; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; + } +} +``` From 02ab3a2cb66c6f8b711fc0fe5f29390474a491c6 Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Sun, 4 Sep 2022 09:46:11 -0700 Subject: [PATCH 2/8] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0afb7f..e194a7ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Target Go 1.19 for Headscale [#778](https://github.com/juanfont/headscale/pull/778) - Target Tailscale v1.30.0 to build Headscale [#780](https://github.com/juanfont/headscale/pull/780) - Give a warning when running Headscale with reverse proxy improperly configured for WebSockets [#788](https://github.com/juanfont/headscale/pull/788) +- Add documentation for running behind a reverse proxy. ## 0.16.4 (2022-08-21) From f6e83413e5871cf501047c165cd318ccb655d380 Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Sun, 4 Sep 2022 09:49:34 -0700 Subject: [PATCH 3/8] Add PR link to changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e194a7ac..35047977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - Target Go 1.19 for Headscale [#778](https://github.com/juanfont/headscale/pull/778) - Target Tailscale v1.30.0 to build Headscale [#780](https://github.com/juanfont/headscale/pull/780) - Give a warning when running Headscale with reverse proxy improperly configured for WebSockets [#788](https://github.com/juanfont/headscale/pull/788) -- Add documentation for running behind a reverse proxy. +- Add documentation for running behind a reverse proxy. [#790](https://github.com/juanfont/headscale/pull/790) ## 0.16.4 (2022-08-21) From dc18d64286534f8f9bfb013a3e4e6773b46d2afe Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Sun, 4 Sep 2022 17:26:33 -0700 Subject: [PATCH 4/8] Add websockets config --- docs/reverse-proxy.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md index c9a1d1b7..0dbd75fe 100644 --- a/docs/reverse-proxy.md +++ b/docs/reverse-proxy.md @@ -29,8 +29,17 @@ server { ssl_certificate_key ; ssl_protocols TLSv1.2 TLSv1.3; + map $http_upgrade $connection_upgrade { + default keep-alive; + 'websocket' upgrade; + '' close; + } + location / { proxy_pass http://; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; proxy_set_header Host $server_name; proxy_redirect http:// https://; proxy_buffering off; From 3a042471b798af6facf6e5f36dd3366168fbbd5b Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Sun, 4 Sep 2022 17:39:51 -0700 Subject: [PATCH 5/8] Add web sockets section --- docs/reverse-proxy.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md index 0dbd75fe..db698d86 100644 --- a/docs/reverse-proxy.md +++ b/docs/reverse-proxy.md @@ -2,6 +2,10 @@ Running Headscale behind a reverse proxy is suitable for container-based deployments. This is especially useful on a server were port 443 is already being used for other web services. +### Web Sockets +The reverse proxy _must_ be configured to support websockets if you are running headscale 0.17.x+ and tailscale v1.30+. + +### TLS Headscale can be configured not to use TLS, leaving it to the reverse proxy to handle. Add the following configuration values to your headscale config file. ```yaml From 45df6e77ff39d9d68104d3b06a55508aaf5086e9 Mon Sep 17 00:00:00 2001 From: Mike Lloyd <49411532+mike-lloyd03@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:37:39 -0700 Subject: [PATCH 6/8] Apply suggestions from code review Thanks for the pointers! Co-authored-by: Juan Font --- docs/reverse-proxy.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md index db698d86..1f66d3c2 100644 --- a/docs/reverse-proxy.md +++ b/docs/reverse-proxy.md @@ -1,9 +1,13 @@ -# Running behind a reverse proxy +# Running headscale behind a reverse proxy + +Running headscale behind a reverse proxy is useful when running multiple applications on the same server, and you want to reuse the same external IP and port - usually tcp/443 for HTTPS. + +### WebSockets +The reverse proxy MUST be configured to support WebSockets, as it is needed for clients running Tailscale v1.30+. + +WebSockets support is required when using the headscale embedded DERP server. In this case, you will also need to expose the UDP port used for STUN (by default, udp/3478). Please check our [config-example.yaml](https://github.com/juanfont/headscale/blob/main/config-example.yaml). -Running Headscale behind a reverse proxy is suitable for container-based deployments. This is especially useful on a server were port 443 is already being used for other web services. -### Web Sockets -The reverse proxy _must_ be configured to support websockets if you are running headscale 0.17.x+ and tailscale v1.30+. ### TLS Headscale can be configured not to use TLS, leaving it to the reverse proxy to handle. Add the following configuration values to your headscale config file. From 0fe3c21223d22ac46e433507f405cbd6f77b8f26 Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Tue, 6 Sep 2022 16:12:20 -0700 Subject: [PATCH 7/8] Move map block out of server block --- docs/reverse-proxy.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md index 1f66d3c2..0809d044 100644 --- a/docs/reverse-proxy.md +++ b/docs/reverse-proxy.md @@ -24,6 +24,12 @@ tls_key_path: "" The following example configuration can be used in your nginx setup, substituting values as necessary. `` should be the IP address and port where headscale is running. In most cases, this will be `http://localhost:8080`. ```Nginx +map $http_upgrade $connection_upgrade { + default keep-alive; + 'websocket' upgrade; + '' close; +} + server { listen 80; listen [::]:80; @@ -37,12 +43,6 @@ server { ssl_certificate_key ; ssl_protocols TLSv1.2 TLSv1.3; - map $http_upgrade $connection_upgrade { - default keep-alive; - 'websocket' upgrade; - '' close; - } - location / { proxy_pass http://; proxy_http_version 1.1; From e286ba817b52fbeb2fd9cc904ecfc12b1ea83a08 Mon Sep 17 00:00:00 2001 From: Mike Lloyd Date: Tue, 20 Sep 2022 20:12:45 -0700 Subject: [PATCH 8/8] Format reverse-proxy.md --- docs/reverse-proxy.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/reverse-proxy.md b/docs/reverse-proxy.md index 0809d044..74bbff71 100644 --- a/docs/reverse-proxy.md +++ b/docs/reverse-proxy.md @@ -3,13 +3,13 @@ Running headscale behind a reverse proxy is useful when running multiple applications on the same server, and you want to reuse the same external IP and port - usually tcp/443 for HTTPS. ### WebSockets -The reverse proxy MUST be configured to support WebSockets, as it is needed for clients running Tailscale v1.30+. + +The reverse proxy MUST be configured to support WebSockets, as it is needed for clients running Tailscale v1.30+. WebSockets support is required when using the headscale embedded DERP server. In this case, you will also need to expose the UDP port used for STUN (by default, udp/3478). Please check our [config-example.yaml](https://github.com/juanfont/headscale/blob/main/config-example.yaml). - - ### TLS + Headscale can be configured not to use TLS, leaving it to the reverse proxy to handle. Add the following configuration values to your headscale config file. ```yaml @@ -21,12 +21,13 @@ tls_key_path: "" ``` ## nginx + The following example configuration can be used in your nginx setup, substituting values as necessary. `` should be the IP address and port where headscale is running. In most cases, this will be `http://localhost:8080`. ```Nginx -map $http_upgrade $connection_upgrade { +map $http_upgrade $connection_upgrade { default keep-alive; - 'websocket' upgrade; + 'websocket' upgrade; '' close; }