From e2a46589ae6361f8963f59ada9b57d299a36412d Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Sun, 24 Aug 2025 17:10:23 +0100 Subject: [PATCH 01/13] Flip default DNS state to match upstream https://github.com/juanfont/headscale/commit/51c6367bb13c63112cb5836c98906add127638e1 --- templates/headscale.template.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/headscale.template.yaml b/templates/headscale.template.yaml index 29e957c..ad6d477 100644 --- a/templates/headscale.template.yaml +++ b/templates/headscale.template.yaml @@ -272,9 +272,9 @@ dns: # `hostname.base_domain` (e.g., _myhost.example.com_). base_domain: $HEADSCALE_DNS_BASE_DOMAIN - # Whether to use the local DNS settings of a node (default) or override the - # local DNS settings and force the use of Headscale's DNS configuration. - override_local_dns: false + # Whether to use the local DNS settings of a node or override the local DNS + # settings (default) and force the use of Headscale's DNS configuration. + override_local_dns: true # List of DNS servers to expose to clients. nameservers: From ec2d782011153f6606fbdc4a0ae27db6036e6393 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Sun, 24 Aug 2025 17:14:20 +0100 Subject: [PATCH 02/13] Export the default value so it can be overridden --- scripts/container-entrypoint.sh | 23 +++++++++++++++++++---- templates/headscale.template.yaml | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/scripts/container-entrypoint.sh b/scripts/container-entrypoint.sh index 196f8a0..70d6ee5 100755 --- a/scripts/container-entrypoint.sh +++ b/scripts/container-entrypoint.sh @@ -170,10 +170,11 @@ check_headscale_environment_vars() { check_litestream_replica_url validate_oidc_settings validate_extra_records - check_env_var_or_set_default "MAGIC_DNS" "${headscale_magic_dns_default}" "^(true|false)$" "Invalid 'MAGIC_DNS'. Must be 'true' or 'false'." - check_env_var_or_set_default "IPV6_PREFIX" "${headscale_ipv6_prefix_default}" - check_env_var_or_set_default "IPV4_PREFIX" "${headscale_ipv4_prefix_default}" + check_env_var_or_set_default "HEADSCALE_OVERRIDE_LOCAL_DNS" "true" "^(true|false)$" "Invalid 'HEADSCALE_OVERRIDE_LOCAL_DNS'. Must be 'true' (default) or 'false'." check_env_var_or_set_default "IP_ALLOCATION" "${headscale_ip_allocation_default}" "^(sequential|random)$" "Invalid 'IP_ALLOCATION'. Must be either 'sequential' (default) or 'random'." + check_env_var_or_set_default "IPV4_PREFIX" "${headscale_ipv4_prefix_default}" + check_env_var_or_set_default "IPV6_PREFIX" "${headscale_ipv6_prefix_default}" + check_env_var_or_set_default "MAGIC_DNS" "${headscale_magic_dns_default}" "^(true|false)$" "Invalid 'MAGIC_DNS'. Must be 'true' or 'false'." require_env_var "PUBLIC_SERVER_URL" require_env_var "HEADSCALE_DNS_BASE_DOMAIN" #This is for the v0.26.0 bump. @@ -393,7 +394,21 @@ check_config_files() { check_caddy_environment_variables - create_headscale_config + # Ensure all template variables are exported for envsubst + local template_vars=( + "ACME_EAB_BLOCK" + "CLOUDFLARE_ACME_BLOCK" + "SECURITY_HEADERS_BLOCK" + "PUBLIC_LISTEN_PORT" + "MAGIC_DNS" + "IPV6_PREFIX" + "IPV4_PREFIX" + "IP_ALLOCATION" + "HEADSCALE_EXTRA_RECORDS_PATH" + ) + for var in "${template_vars[@]}"; do + export "${var}=${!var}" + done create_caddyfile diff --git a/templates/headscale.template.yaml b/templates/headscale.template.yaml index ad6d477..96aaa1a 100644 --- a/templates/headscale.template.yaml +++ b/templates/headscale.template.yaml @@ -274,7 +274,7 @@ dns: # Whether to use the local DNS settings of a node or override the local DNS # settings (default) and force the use of Headscale's DNS configuration. - override_local_dns: true + override_local_dns: $HEADSCALE_OVERRIDE_LOCAL_DNS # List of DNS servers to expose to clients. nameservers: From 1fcdf61fbc0aad70b21b9cae85c33c9c655ec9f9 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Mon, 25 Aug 2025 18:58:06 +0100 Subject: [PATCH 03/13] Remove upstream dead code --- scripts/container-entrypoint.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/container-entrypoint.sh b/scripts/container-entrypoint.sh index 70d6ee5..54294f3 100755 --- a/scripts/container-entrypoint.sh +++ b/scripts/container-entrypoint.sh @@ -177,11 +177,6 @@ check_headscale_environment_vars() { check_env_var_or_set_default "MAGIC_DNS" "${headscale_magic_dns_default}" "^(true|false)$" "Invalid 'MAGIC_DNS'. Must be 'true' or 'false'." require_env_var "PUBLIC_SERVER_URL" require_env_var "HEADSCALE_DNS_BASE_DOMAIN" - #This is for the v0.26.0 bump. - if env_var_is_defined "HEADSCALE_POLICY_V1" ; then - export HEADSCALE_POLICY_V1=1 - log_warn "Using Headscale policy version 1. Please migrate and remove this variable." - fi } ####################################### From e47827124221af06b0978076d26163ca60546872 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Tue, 26 Aug 2025 17:10:37 +0100 Subject: [PATCH 04/13] Upstream DERP updates are now 3h https://github.com/juanfont/headscale/commit/b87567628a88703884d2c95c0aba7b0c2f118538 --- templates/headscale.template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/headscale.template.yaml b/templates/headscale.template.yaml index 96aaa1a..08a0dd6 100644 --- a/templates/headscale.template.yaml +++ b/templates/headscale.template.yaml @@ -127,7 +127,7 @@ derp: auto_update_enabled: true # How often should we check for DERP updates? - update_frequency: 24h + update_frequency: 3h # Disables the automatic check for headscale updates on startup disable_check_updates: true From 48658d8cd7ace0f292ff2d54548bf7872f90ed36 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 17 Oct 2025 10:21:53 +0100 Subject: [PATCH 05/13] Bump `headscale` to `v0.27.0-beta.1` --- Dockerfile | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index a3117c6..0db3493 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,8 @@ # Tool version arguments # Bump these every time there is a new release. # We're pulling these from github source, don't forget to bump the checksum! -ARG HEADSCALE_VERSION="0.26.1" -ARG HEADSCALE_SHA256="5012577e6fc5d4234aab7b4be0d6e271ea1a4ec38521a8aa472f80ea1fe81cba" +ARG HEADSCALE_VERSION="0.27.0-beta.1" +ARG HEADSCALE_SHA256="975d580dd9aebde4259a6f55813a9f1150e359ec39973067d927734418adeeb4" ARG LITESTREAM_VERSION="0.5.2" ARG LITESTREAM_SHA256="235da234edd2c7140b702f1a53ecdad996040b7afaf03b4dcf9620d7998cd830" diff --git a/README.md b/README.md index 64b713b..848d7c0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Deploy [Headscale][headscale-wob] using a "serverless" immutable docker image wi | Tool | Upstream Repository | Version | |---|---|---| | [`Alpine Linux`][alpine-linux-wob] | [Alpine Linux Repo][alpine-linux-repo] | [`v3.22.1`](https://git.alpinelinux.org/aports/log/?h=v3.22.1) | -| [`Headscale`][headscale-wob] | [Headscale Repo][headscale-repo] | [`v0.26.1`](https://github.com/juanfont/headscale/releases/tag/v0.26.1) | +| [`Headscale`][headscale-wob] | [Headscale Repo][headscale-repo] | [`v0.27.0-beta.1`](https://github.com/juanfont/headscale/releases/tag/v0.27.0-beta.1) | | [`Headscale-Admin`][headscale-admin-wob] | [Headscale-Admin Repo][headscale-admin-repo] | [`0.26.0`](https://github.com/GoodiesHQ/headscale-admin/commit/6cf2bc7d59165757a70f4c918a032225eb5e6e7d) | | [`Litestream`][litestream-wob] | [Litestream Repo][litestream-repo] | [`v0.5.2`](https://github.com/benbjohnson/litestream/releases/tag/v0.5.2) | | [`Caddy`][caddy-wob] | [Caddy Repo][caddy-repo] | [`v2.10.2`](https://github.com/caddyserver/caddy/releases/tag/v2.10.2) | From 00361bc23d94ce2d343b85ed1497aecb613cfda1 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 17 Oct 2025 10:29:34 +0100 Subject: [PATCH 06/13] Fix logging declaration to match upstream config --- templates/headscale.template.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/headscale.template.yaml b/templates/headscale.template.yaml index 08a0dd6..5df836a 100644 --- a/templates/headscale.template.yaml +++ b/templates/headscale.template.yaml @@ -224,9 +224,11 @@ tls_cert_path: "" tls_key_path: "" log: + # Valid log levels: panic, fatal, error, warn, info, debug, trace + level: info + # Output formatting for logs: text or json format: text - level: info ## Policy # headscale supports Tailscale's ACL policies. From 52c612b3c1c58dbb0d02e503fb5ad6464952ffc5 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 17 Oct 2025 10:31:30 +0100 Subject: [PATCH 07/13] Add new `verify_clients` option to DERP confid --- templates/headscale.template.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/headscale.template.yaml b/templates/headscale.template.yaml index 5df836a..12b0264 100644 --- a/templates/headscale.template.yaml +++ b/templates/headscale.template.yaml @@ -85,6 +85,9 @@ derp: region_code: "headscale" region_name: "Headscale Embedded DERP" + # Only allow clients associated with this server access + verify_clients: true + # Listens over UDP at the configured address for STUN connections - to help with NAT traversal. # When the embedded DERP server is enabled stun_listen_addr MUST be defined. # From 5ef94a2d58aeb57ec9c0f2a4283e9ad7c67870bf Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 17 Oct 2025 10:56:17 +0100 Subject: [PATCH 08/13] Ensure we're exporting everything for the envsubstr --- scripts/container-entrypoint.sh | 28 +++++++++++++++++----------- scripts/defaults.sh | 1 + 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/scripts/container-entrypoint.sh b/scripts/container-entrypoint.sh index 54294f3..3337cd7 100755 --- a/scripts/container-entrypoint.sh +++ b/scripts/container-entrypoint.sh @@ -184,17 +184,20 @@ check_headscale_environment_vars() { ####################################### create_headscale_config() { # Ensure all template variables are exported for envsubst - local template_vars=( - "ACME_EAB_BLOCK" - "CLOUDFLARE_ACME_BLOCK" - "SECURITY_HEADERS_BLOCK" - "PUBLIC_LISTEN_PORT" - "MAGIC_DNS" - "IPV6_PREFIX" - "IPV4_PREFIX" - "IP_ALLOCATION" - "HEADSCALE_EXTRA_RECORDS_PATH" - ) + local template_vars=( + "ACME_EAB_BLOCK" + "CLOUDFLARE_ACME_BLOCK" + "SECURITY_HEADERS_BLOCK" + "PUBLIC_SERVER_URL" + "PUBLIC_LISTEN_PORT" + "HEADSCALE_DNS_BASE_DOMAIN" + "HEADSCALE_OVERRIDE_LOCAL_DNS" + "MAGIC_DNS" + "IPV6_PREFIX" + "IPV4_PREFIX" + "IP_ALLOCATION" + "HEADSCALE_EXTRA_RECORDS_PATH" + ) for var in "${template_vars[@]}"; do export "${var}=${!var}" done @@ -394,7 +397,10 @@ check_config_files() { "ACME_EAB_BLOCK" "CLOUDFLARE_ACME_BLOCK" "SECURITY_HEADERS_BLOCK" + "PUBLIC_SERVER_URL" "PUBLIC_LISTEN_PORT" + "HEADSCALE_DNS_BASE_DOMAIN" + "HEADSCALE_OVERRIDE_LOCAL_DNS" "MAGIC_DNS" "IPV6_PREFIX" "IPV4_PREFIX" diff --git a/scripts/defaults.sh b/scripts/defaults.sh index e64efd0..64c0f79 100644 --- a/scripts/defaults.sh +++ b/scripts/defaults.sh @@ -8,6 +8,7 @@ headscale_ipv6_prefix_default="fd7a:115c:a1e0::/48" headscale_ipv4_prefix_default="100.64.0.0/10" headscale_ip_allocation_default="sequential" headscale_gomaxprocs_default=1 +headscale_override_local_dns_default="true" caddyfile_cleartext=/etc/caddy/Caddyfile-http caddyfile_https=/etc/caddy/Caddyfile-https From 5f1c7c0b7b7328fc67c89d5d6b4c4211b60e6a76 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 17 Oct 2025 11:08:49 +0100 Subject: [PATCH 09/13] _Actually create_ the headscale config --- scripts/container-entrypoint.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/container-entrypoint.sh b/scripts/container-entrypoint.sh index 3337cd7..3d351b3 100755 --- a/scripts/container-entrypoint.sh +++ b/scripts/container-entrypoint.sh @@ -411,6 +411,8 @@ check_config_files() { export "${var}=${!var}" done + create_headscale_config + create_caddyfile reuse_or_create_noise_private_key From b2b5592847a84f78592e58704e61673edfbb272b Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 24 Oct 2025 10:18:36 +0100 Subject: [PATCH 10/13] Centralise exporting of all vars to the check --- scripts/container-entrypoint.sh | 38 --------------------------------- scripts/variables-check.sh | 5 ++++- 2 files changed, 4 insertions(+), 39 deletions(-) diff --git a/scripts/container-entrypoint.sh b/scripts/container-entrypoint.sh index 3d351b3..2adfdc6 100755 --- a/scripts/container-entrypoint.sh +++ b/scripts/container-entrypoint.sh @@ -183,25 +183,6 @@ check_headscale_environment_vars() { # Create our Headscale configuration file ####################################### create_headscale_config() { - # Ensure all template variables are exported for envsubst - local template_vars=( - "ACME_EAB_BLOCK" - "CLOUDFLARE_ACME_BLOCK" - "SECURITY_HEADERS_BLOCK" - "PUBLIC_SERVER_URL" - "PUBLIC_LISTEN_PORT" - "HEADSCALE_DNS_BASE_DOMAIN" - "HEADSCALE_OVERRIDE_LOCAL_DNS" - "MAGIC_DNS" - "IPV6_PREFIX" - "IPV4_PREFIX" - "IP_ALLOCATION" - "HEADSCALE_EXTRA_RECORDS_PATH" - ) - for var in "${template_vars[@]}"; do - export "${var}=${!var}" - done - create_config_from_template "${headscale_config}" "Headscale configuration file" } @@ -392,25 +373,6 @@ check_config_files() { check_caddy_environment_variables - # Ensure all template variables are exported for envsubst - local template_vars=( - "ACME_EAB_BLOCK" - "CLOUDFLARE_ACME_BLOCK" - "SECURITY_HEADERS_BLOCK" - "PUBLIC_SERVER_URL" - "PUBLIC_LISTEN_PORT" - "HEADSCALE_DNS_BASE_DOMAIN" - "HEADSCALE_OVERRIDE_LOCAL_DNS" - "MAGIC_DNS" - "IPV6_PREFIX" - "IPV4_PREFIX" - "IP_ALLOCATION" - "HEADSCALE_EXTRA_RECORDS_PATH" - ) - for var in "${template_vars[@]}"; do - export "${var}=${!var}" - done - create_headscale_config create_caddyfile diff --git a/scripts/variables-check.sh b/scripts/variables-check.sh index b5f3fb9..764b8d5 100644 --- a/scripts/variables-check.sh +++ b/scripts/variables-check.sh @@ -31,7 +31,7 @@ require_env_var() { } ######################################## -# Check environment variable is set, or default (and optionally validate with regex - now you have two problems) +# Check environment variable is set, or default, and export it (and optionally validate with regex - now you have two problems) # Arguments: # $1 - Variable name # $2 - Default value @@ -49,6 +49,9 @@ check_env_var_or_set_default() { export "${var_name}"="${default_value}" fi + # Ensure it's exported + declare -x "$var_name" + # Validate with regex if pattern provided if [[ -n "${pattern}" && ! "${!var_name}" =~ ${pattern} ]]; then log_error "${error_msg:-"Invalid '${var_name}' value: '${!var_name}'"}" From bf6a79b4eee3ccf1928d8093c74dd4710c8d8c74 Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 24 Oct 2025 10:18:48 +0100 Subject: [PATCH 11/13] Bump headscale to `0.27.0-beta.2` --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0db3493..5ab625b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,8 @@ # Tool version arguments # Bump these every time there is a new release. # We're pulling these from github source, don't forget to bump the checksum! -ARG HEADSCALE_VERSION="0.27.0-beta.1" -ARG HEADSCALE_SHA256="975d580dd9aebde4259a6f55813a9f1150e359ec39973067d927734418adeeb4" +ARG HEADSCALE_VERSION="0.27.0-beta.2" +ARG HEADSCALE_SHA256="d07a39f896a8d84643cb1a2a65e262a9213f2e51de65f3db8bc00824de119745" ARG LITESTREAM_VERSION="0.5.2" ARG LITESTREAM_SHA256="235da234edd2c7140b702f1a53ecdad996040b7afaf03b4dcf9620d7998cd830" From 898bbb19c0c0f324354a2079e2a9f1b27165e14d Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Fri, 24 Oct 2025 10:31:23 +0100 Subject: [PATCH 12/13] Revert "Centralise exporting of all vars to the check" This reverts commit b2b5592847a84f78592e58704e61673edfbb272b. --- scripts/container-entrypoint.sh | 38 +++++++++++++++++++++++++++++++++ scripts/variables-check.sh | 5 +---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/scripts/container-entrypoint.sh b/scripts/container-entrypoint.sh index 2adfdc6..3d351b3 100755 --- a/scripts/container-entrypoint.sh +++ b/scripts/container-entrypoint.sh @@ -183,6 +183,25 @@ check_headscale_environment_vars() { # Create our Headscale configuration file ####################################### create_headscale_config() { + # Ensure all template variables are exported for envsubst + local template_vars=( + "ACME_EAB_BLOCK" + "CLOUDFLARE_ACME_BLOCK" + "SECURITY_HEADERS_BLOCK" + "PUBLIC_SERVER_URL" + "PUBLIC_LISTEN_PORT" + "HEADSCALE_DNS_BASE_DOMAIN" + "HEADSCALE_OVERRIDE_LOCAL_DNS" + "MAGIC_DNS" + "IPV6_PREFIX" + "IPV4_PREFIX" + "IP_ALLOCATION" + "HEADSCALE_EXTRA_RECORDS_PATH" + ) + for var in "${template_vars[@]}"; do + export "${var}=${!var}" + done + create_config_from_template "${headscale_config}" "Headscale configuration file" } @@ -373,6 +392,25 @@ check_config_files() { check_caddy_environment_variables + # Ensure all template variables are exported for envsubst + local template_vars=( + "ACME_EAB_BLOCK" + "CLOUDFLARE_ACME_BLOCK" + "SECURITY_HEADERS_BLOCK" + "PUBLIC_SERVER_URL" + "PUBLIC_LISTEN_PORT" + "HEADSCALE_DNS_BASE_DOMAIN" + "HEADSCALE_OVERRIDE_LOCAL_DNS" + "MAGIC_DNS" + "IPV6_PREFIX" + "IPV4_PREFIX" + "IP_ALLOCATION" + "HEADSCALE_EXTRA_RECORDS_PATH" + ) + for var in "${template_vars[@]}"; do + export "${var}=${!var}" + done + create_headscale_config create_caddyfile diff --git a/scripts/variables-check.sh b/scripts/variables-check.sh index 764b8d5..b5f3fb9 100644 --- a/scripts/variables-check.sh +++ b/scripts/variables-check.sh @@ -31,7 +31,7 @@ require_env_var() { } ######################################## -# Check environment variable is set, or default, and export it (and optionally validate with regex - now you have two problems) +# Check environment variable is set, or default (and optionally validate with regex - now you have two problems) # Arguments: # $1 - Variable name # $2 - Default value @@ -49,9 +49,6 @@ check_env_var_or_set_default() { export "${var_name}"="${default_value}" fi - # Ensure it's exported - declare -x "$var_name" - # Validate with regex if pattern provided if [[ -n "${pattern}" && ! "${!var_name}" =~ ${pattern} ]]; then log_error "${error_msg:-"Invalid '${var_name}' value: '${!var_name}'"}" From 97f793b3b788f8261e6e39b32a5c0d5452a0effb Mon Sep 17 00:00:00 2001 From: Ed Geraghty Date: Wed, 5 Nov 2025 10:54:46 +0000 Subject: [PATCH 13/13] Bump headscale to `v0.27.0` --- Dockerfile | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5ab625b..67b14af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,8 @@ # Tool version arguments # Bump these every time there is a new release. # We're pulling these from github source, don't forget to bump the checksum! -ARG HEADSCALE_VERSION="0.27.0-beta.2" -ARG HEADSCALE_SHA256="d07a39f896a8d84643cb1a2a65e262a9213f2e51de65f3db8bc00824de119745" +ARG HEADSCALE_VERSION="0.27.0" +ARG HEADSCALE_SHA256="d7f61f8078c6c1767b30bf8166b714fe15f4bf72162d4c2619b2f69280a597a5" ARG LITESTREAM_VERSION="0.5.2" ARG LITESTREAM_SHA256="235da234edd2c7140b702f1a53ecdad996040b7afaf03b4dcf9620d7998cd830" diff --git a/README.md b/README.md index 848d7c0..71f430b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Deploy [Headscale][headscale-wob] using a "serverless" immutable docker image wi | Tool | Upstream Repository | Version | |---|---|---| | [`Alpine Linux`][alpine-linux-wob] | [Alpine Linux Repo][alpine-linux-repo] | [`v3.22.1`](https://git.alpinelinux.org/aports/log/?h=v3.22.1) | -| [`Headscale`][headscale-wob] | [Headscale Repo][headscale-repo] | [`v0.27.0-beta.1`](https://github.com/juanfont/headscale/releases/tag/v0.27.0-beta.1) | +| [`Headscale`][headscale-wob] | [Headscale Repo][headscale-repo] | [`v0.27.0`](https://github.com/juanfont/headscale/releases/tag/v0.27.0) | | [`Headscale-Admin`][headscale-admin-wob] | [Headscale-Admin Repo][headscale-admin-repo] | [`0.26.0`](https://github.com/GoodiesHQ/headscale-admin/commit/6cf2bc7d59165757a70f4c918a032225eb5e6e7d) | | [`Litestream`][litestream-wob] | [Litestream Repo][litestream-repo] | [`v0.5.2`](https://github.com/benbjohnson/litestream/releases/tag/v0.5.2) | | [`Caddy`][caddy-wob] | [Caddy Repo][caddy-repo] | [`v2.10.2`](https://github.com/caddyserver/caddy/releases/tag/v2.10.2) |