diff --git a/tailscale/DOCS.md b/tailscale/DOCS.md index ffd62c465..1d99322ad 100644 --- a/tailscale/DOCS.md +++ b/tailscale/DOCS.md @@ -40,21 +40,28 @@ however, it is nice to know where you need to go later on. ## Configuration -This add-on has almost no additional configuration options for the -add-on itself. +The add-on by default exposes "Exit Node" capabilities that you can enable from +your Tailscale account. Additionally, if the Supervisor managed your network +(which is the default), the add-on will also advertise routes to your subnets on +all supported interfaces to Tailscale. -However, when logging in to Tailscale, you can configure your Tailscale -network right from their interface. +Consider disabling key expiry to avoid losing connection to your Home Assistant +device. See [Key expiry][tailscale_info_key_expiry] for more information. + +Logging in to Tailscale, you can configure your Tailscale network right from +their interface. -The add-on exposes "Exit Node" capabilities that you can enable from your -Tailscale account. Additionally, if the Supervisor managed your network (which -is the default), the add-on will also advertise routes to your subnets on all -supported interfaces to Tailscale. +1. Navigate to the [Machines page][tailscale_machines] of the admin console, and + find your Home Assistant instance. -Consider disabling key expiry to avoid losing connection to your Home Assistant -device. See [Key expiry][tailscale_info_key_expiry] for more information. +1. Click on the **…** icon at the right side and select the "Edit route + settings..." option. The "Exit node" and "Subnet routes" functions can be + enabled here. + +1. Click on the **…** icon at the right side and select the "Disable key + expiry" option. ```yaml accept_dns: true @@ -62,6 +69,7 @@ accept_routes: true advertise_exit_node: true advertise_connector: true advertise_routes: + - local_subnets - 192.168.1.0/24 - fd12:3456:abcd::/64 exit_node: 100.101.102.103 @@ -89,7 +97,7 @@ userspace_networking: true If you are experiencing trouble with MagicDNS on this device and wish to disable, you can do so using this option. -When not set, this option is enabled by default. +This option is enabled by default. MagicDNS may cause issues if you run things like Pi-hole or AdGuard Home on the same machine as this add-on. In such cases disabling `accept_dns` @@ -103,7 +111,7 @@ your tailnet. More information: [Subnet routers][tailscale_info_subnets] -When not set, this option is enabled by default. +This option is enabled by default. ### Option: `advertise_exit_node` @@ -114,7 +122,7 @@ route all your public internet traffic as needed, like a consumer VPN. More information: [Exit nodes][tailscale_info_exit_nodes] -When not set, this option is enabled by default. +This option is enabled by default. **Note:** You can't advertise this device as an exit node and at the same time specify an exit node to use. See also the "Option: `exit_node`" section of this @@ -134,7 +142,7 @@ all nodes on the tailnet will use that IP address for their traffic egress. More information: [App connectors][tailscale_info_app_connectors] -When not set, this option is enabled by default. +This option is enabled by default. ### Option: `advertise_routes` @@ -149,8 +157,8 @@ If you want to disable this option, specify an empty list in the configuration More information: [Subnet routers][tailscale_info_subnets] -When not set, the add-on by default will advertise routes to your subnets on all -supported interfaces. +The add-on by default will advertise routes to your subnets on all supported +interfaces by adding `local_subnets` to the list. ### Option: `exit_node` @@ -209,7 +217,7 @@ This option allows you to enable Tailscale Serve or Funnel features to present your Home Assistant instance with a valid certificate on your tailnet or on the internet. -When not set, this option is disabled by default. +This option is disabled by default. Tailscale can provide a TLS certificate for your Home Assistant instance within your tailnet domain. @@ -284,14 +292,14 @@ internet. Only ports 443, 8443, and 10000 are allowed by Tailscale. -When not set, port 443 is used by default. +Port 443 is used by default. ### Option: `snat_subnet_routes` This option allows subnet devices to see the traffic originating from the subnet router, and this simplifies routing configuration. -When not set, this option is enabled by default. +This option is enabled by default. To support advanced [Site-to-site networking][tailscale_info_site_to_site] (e.g. to traverse multiple networks), you can disable this functionality, and follow @@ -310,7 +318,7 @@ nodes, subnet routers, and app connectors), to only allow return packets for existing outbound connections. Inbound packets that don't belong to an existing connection are dropped. -When not set, this option is disabled by default. +This option is disabled by default. ### Option: `tags` @@ -325,7 +333,7 @@ This add-on supports [Tailscale's Taildrop][tailscale_info_taildrop] feature, which allows you to send files to your Home Assistant instance from other Tailscale devices. -When not set, this option is enabled by default. +This option is enabled by default. Received files are stored in the `/share/taildrop` directory. @@ -335,7 +343,7 @@ The add-on uses [userspace networking mode][tailscale_info_userspace_networking] to make your Home Assistant instance (and optionally the local subnets) accessible within your tailnet. -When not set, this option is enabled by default. +This option is enabled by default. If you need to access other clients on your tailnet from your Home Assistant instance, disable userspace networking mode, which will create a `tailscale0` @@ -463,3 +471,4 @@ SOFTWARE. [tailscale_info_tags]: https://tailscale.com/kb/1068/tags [tailscale_info_taildrop]: https://tailscale.com/kb/1106/taildrop [tailscale_info_userspace_networking]: https://tailscale.com/kb/1112/userspace-networking +[tailscale_machines]: https://login.tailscale.com/admin/machines diff --git a/tailscale/config.yaml b/tailscale/config.yaml index 64b21f82e..ebac53094 100644 --- a/tailscale/config.yaml +++ b/tailscale/config.yaml @@ -27,21 +27,37 @@ map: - share:rw ports: 41641/udp: null +options: + accept_dns: true + accept_routes: true + advertise_exit_node: true + advertise_connector: true + advertise_routes: + - local_subnets + log_level: info + login_server: "https://controlplane.tailscale.com" + share_homeassistant: disabled + share_on_port: 443 + snat_subnet_routes: true + stateful_filtering: false + tags: [] + taildrop: true + userspace_networking: true schema: - accept_dns: bool? - accept_routes: bool? - advertise_exit_node: bool? - advertise_connector: bool? + accept_dns: bool + accept_routes: bool + advertise_exit_node: bool + advertise_connector: bool advertise_routes: - - "match(^(((25[0-5]|(2[0-4]|1\\d|[1-9]?)\\d)\\.){3}(25[0-5]|(2[0-4]|1\\d|[1-9]?)\\d)\\/(3[0-2]|[12]?\\d)|[a-fA-F\\d.:]+:[a-fA-F\\d.:]+\\/(12[0-8]|(1[01]|[1-9]?)\\d))$)?" + - "match(^(?:local.subnets|(?:(?:25[0-5]|(?:2[0-4]|1\\d|[1-9]?)\\d)\\.){3}(?:25[0-5]|(?:2[0-4]|1\\d|[1-9]?)\\d)\\/(?:3[0-2]|[12]?\\d)|[a-fA-F\\d.:]+:[a-fA-F\\d.:]+\\/(?:12[0-8]|(?:1[01]|[1-9]?)\\d))$)" exit_node: "match(^(?:(?:(?:25[0-5]|(?:2[0-4]|1\\d|[1-9]?)\\d)\\.){3}(?:25[0-5]|(?:2[0-4]|1\\d|[1-9]?)\\d)|[a-fA-F\\d.:]+:[a-fA-F\\d.:]+|[a-fA-F\\d]{8}(?:-[a-fA-F\\d]{4}){3}-[a-fA-F\\d]{12}|auto:any)$)?" - log_level: list(trace|debug|info|notice|warning|error|fatal)? - login_server: url? - share_homeassistant: list(disabled|serve|funnel)? - share_on_port: match(^(443|8443|10000)$)? - snat_subnet_routes: bool? - stateful_filtering: bool? + log_level: list(trace|debug|info|notice|warning|error|fatal) + login_server: url + share_homeassistant: list(disabled|serve|funnel) + share_on_port: match(^(?:443|8443|10000)$) + snat_subnet_routes: bool + stateful_filtering: bool tags: - - "match(^tag:[a-zA-Z][a-zA-Z0-9-]*$)?" - taildrop: bool? - userspace_networking: bool? + - "match(^tag:[a-zA-Z][a-zA-Z0-9-]*$)" + taildrop: bool + userspace_networking: bool diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run index a6c134220..212cc98b1 100755 --- a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run @@ -16,36 +16,29 @@ declare keyexpiry # Default options options+=(--hostname "$(bashio::info.hostname)") -# Accept magicDNS by default when not set, or when explicitly enabled -if ! bashio::config.has_value "accept_dns" || \ - bashio::config.true "accept_dns"; -then +# Accept magicDNS when explicitly enabled +if bashio::config.true "accept_dns"; then options+=(--accept-dns) else options+=(--accept-dns=false) fi -# Accept routes by default when not set, or when explicitly enabled -if ! bashio::config.has_value "accept_routes" || \ - bashio::config.true "accept_routes"; -then +# Accept routes when explicitly enabled +if bashio::config.true "accept_routes"; then options+=(--accept-routes) else options+=(--accept-routes=false) fi # Check exit node configuration -if (! bashio::config.has_value "advertise_exit_node" || \ - bashio::config.true "advertise_exit_node") && \ +if bashio::config.true "advertise_exit_node" && \ bashio::config.has_value "exit_node" then bashio::exit.nok "You can't advertise this device as an exit node and at the same time specify an exit node to use" fi -# Advertise as exit node by default when not set, or when explicitly enabled -if ! bashio::config.has_value "advertise_exit_node" || \ - bashio::config.true "advertise_exit_node"; -then +# Advertise as exit node when explicitly enabled +if bashio::config.true "advertise_exit_node"; then options+=(--advertise-exit-node) else options+=(--advertise-exit-node=false) @@ -61,42 +54,33 @@ else options+=(--exit-node-allow-lan-access=false) fi -# Advertise app connector by default when not set, or when explicitly enabled -if ! bashio::config.has_value "advertise_connector" || \ - bashio::config.true "advertise_connector"; -then +# Advertise app connector when explicitly enabled +if bashio::config.true "advertise_connector"; then options+=(--advertise-connector) else options+=(--advertise-connector=false) fi # Get configured control server -if bashio::config.has_value "login_server"; -then - login_server=$(bashio::config "login_server") - options+=(--login-server="${login_server}") -fi +login_server=$(bashio::config "login_server") +options+=(--login-server="${login_server}") -# Enable stateful filtering (it's disabled by default from v1.66.4) -if ! bashio::config.has_value "stateful_filtering" || \ - bashio::config.false "stateful_filtering"; -then - options+=(--stateful-filtering=false) -else +# Enable stateful filtering when explicitly enabled +if bashio::config.true "stateful_filtering"; then options+=(--stateful-filtering) +else + options+=(--stateful-filtering=false) fi -# Support advanced site-to-site networking, disable source addresses NAT -if ! bashio::config.has_value "snat_subnet_routes" || \ - bashio::config.true "snat_subnet_routes"; -then +# Enable source NAT when explicitly enabled +if bashio::config.true "snat_subnet_routes"; then options+=(--snat-subnet-routes) else options+=(--snat-subnet-routes=false) fi # Get configured tags -tags=$(bashio::config "tags//[] | join(\",\")" "") +tags=$(bashio::config "tags | join(\",\")") options+=(--advertise-tags="${tags}") # Advertise subnet routes @@ -161,8 +145,7 @@ fi # Warn about colliding subnet routes if non-userspace networking and accepting routes are enabled if bashio::config.false "userspace_networking" && \ - (! bashio::config.has_value "accept_routes" || \ - bashio::config.true "accept_routes"); + bashio::config.true "accept_routes"; then readarray -t colliding_routes < <( \ comm -1 -2 \ @@ -184,9 +167,7 @@ then fi # Notify about userspace networking -if ! bashio::config.has_value "userspace_networking" || \ - bashio::config.true "userspace_networking"; -then +if bashio::config.true "userspace_networking"; then bashio::log.notice \ "The add-on uses userspace networking mode." bashio::log.notice \ diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/share-homeassistant/run b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/share-homeassistant/run index 93d37d838..fd9d76aae 100755 --- a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/share-homeassistant/run +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/share-homeassistant/run @@ -69,4 +69,4 @@ fi echo "" >&3 # Set up serve or funnel -exec /opt/tailscale $(bashio::config 'share_homeassistant') --https=$(bashio::config 'share_on_port' '443') --set-path=/ "http://127.0.0.1:$(bashio::core.port)" +exec /opt/tailscale $(bashio::config 'share_homeassistant') --https=$(bashio::config 'share_on_port') --set-path=/ "http://127.0.0.1:$(bashio::core.port)" diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/tailscaled/run b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/tailscaled/run index 8ea71ed7c..0bf6d4871 100755 --- a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/tailscaled/run +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/tailscaled/run @@ -23,10 +23,8 @@ if bashio::var.has_value "${udp_port}"; then options+=(--port=${udp_port}) fi -# Use userspace networking by default when not set, or when explicitly enabled -if ! bashio::config.has_value "userspace_networking" || \ - bashio::config.true "userspace_networking"; -then +# Use userspace networking when explicitly enabled +if bashio::config.true "userspace_networking"; then options+=(--tun=userspace-networking) fi diff --git a/tailscale/rootfs/etc/s6-overlay/scripts/stage2_hook.sh b/tailscale/rootfs/etc/s6-overlay/scripts/stage2_hook.sh index 30a1687c5..16a4b412f 100755 --- a/tailscale/rootfs/etc/s6-overlay/scripts/stage2_hook.sh +++ b/tailscale/rootfs/etc/s6-overlay/scripts/stage2_hook.sh @@ -59,30 +59,25 @@ if bashio::var.has_value "${proxy_and_funnel_port}"; then fi # Disable protect-subnets service when userspace-networking is enabled or accepting routes is disabled -if ! bashio::config.has_value "userspace_networking" || \ - bashio::config.true "userspace_networking" || \ +if bashio::config.true "userspace_networking" || \ bashio::config.false "accept_routes"; then rm /etc/s6-overlay/s6-rc.d/post-tailscaled/dependencies.d/protect-subnets fi -# If advertise_routes is configured, do not wait for the local network to be ready to collect subnet information -if bashio::config.exists "advertise_routes"; +# If local subnets are not configured in advertise_routes, do not wait for the local network to be ready to collect subnet information +if ! bashio::config "advertise_routes" | grep -Eq "^local.subnets$"; then rm /etc/s6-overlay/s6-rc.d/post-tailscaled/dependencies.d/local-network fi # Disable forwarding service when userspace-networking is enabled -if ! bashio::config.has_value "userspace_networking" || \ - bashio::config.true "userspace_networking"; -then +if bashio::config.true "userspace_networking"; then rm /etc/s6-overlay/s6-rc.d/user/contents.d/forwarding fi # Disable mss-clamping service when userspace-networking is enabled -if ! bashio::config.has_value "userspace_networking" || \ - bashio::config.true "userspace_networking"; -then +if bashio::config.true "userspace_networking"; then rm /etc/s6-overlay/s6-rc.d/user/contents.d/mss-clamping fi @@ -91,9 +86,7 @@ if bashio::config.false 'taildrop'; then rm /etc/s6-overlay/s6-rc.d/user/contents.d/taildrop fi -# Disable share-homeassistant service when share_homeassistant has not been explicitly enabled -if ! bashio::config.has_value 'share_homeassistant' || \ - bashio::config.equals 'share_homeassistant' 'disabled' -then +# Disable share-homeassistant service when it has been explicitly disabled +if bashio::config.equals 'share_homeassistant' 'disabled'; then rm /etc/s6-overlay/s6-rc.d/user/contents.d/share-homeassistant fi diff --git a/tailscale/rootfs/usr/bin/subnet-routes b/tailscale/rootfs/usr/bin/subnet-routes index 78d059cc4..2d772eb53 100755 --- a/tailscale/rootfs/usr/bin/subnet-routes +++ b/tailscale/rootfs/usr/bin/subnet-routes @@ -24,10 +24,20 @@ if bashio::cache.exists "subnet-routes-$1"; then readarray -t routes < <(bashio::cache.get "subnet-routes-$1") printf -v response "%s" "${routes[@]/%/$'\n'}" else - if [[ "$1" == "advertised" ]] && bashio::config.exists "advertise_routes"; then - # Configuration exists, use configured values + if [[ "$1" == "advertised" ]]; then + # Use configured values for address in $(bashio::config "advertise_routes"); do - addresses+=("${address}") + if [[ "${address}" =~ ^local.subnets$ ]]; then + # Handle special value, collect local subnets + readarray -t routes < <(subnet-routes local) + if (( 0 == ${#routes[@]} )); then + bashio::log.warning \ + "There are no local subnets to advertise!" \ + "Restart of the add-on is required after the issue is fixed!" + fi + else + addresses+=("${address}") + fi done else # Find interfaces and matching addresses from which we can extract routes @@ -37,7 +47,7 @@ else done fi - # Extract routes + # Extract routes from addresses for address in "${addresses[@]}"; do if bashio::var.has_value "${address}"; then # Skip local link addresses @@ -59,20 +69,11 @@ else fi done - # Remove duplicate entries + # Remove duplicate entries from routes readarray -t routes < <(printf "%s" "${routes[@]/%/$'\n'}" | sort -u) printf -v response "%s" "${routes[@]/%/$'\n'}" bashio::cache.set "subnet-routes-$1" "${response}" fi -if (( 0 == ${#routes[@]} )) && \ - [[ "$1" == "advertised" ]] && \ - ! bashio::config.exists "advertise_routes" -then - bashio::log.warning \ - "There are no local subnets to advertise!" \ - "Restart of the add-on is required after the issue is fixed!" -fi - printf "%s" "${response}" diff --git a/tailscale/translations/en.yaml b/tailscale/translations/en.yaml index c963994c3..6eb719d6e 100644 --- a/tailscale/translations/en.yaml +++ b/tailscale/translations/en.yaml @@ -5,20 +5,20 @@ configuration: description: >- If you are experiencing trouble with MagicDNS on this device and wish to disable, you can do so using this option. - When not set, this option is enabled by default. + This option is enabled by default. accept_routes: name: Accept routes description: >- This option allows you to accept subnet routes advertised by other nodes in your tailnet. - When not set, this option is enabled by default. + This option is enabled by default. advertise_exit_node: name: Advertise as an exit node description: >- This option allows you to advertise this Tailscale instance as an exit node. By setting a device on your network as an exit node, you can use it to route all your public internet traffic as needed, like a consumer VPN. - When not set, this option is enabled by default. + This option is enabled by default. advertise_connector: name: Advertise as an app connector description: >- @@ -26,14 +26,14 @@ configuration: accessible over your tailnet, and the domains for those applications. Any traffic for that application is then forced over the tailnet to a node running an app connector before egressing to the target domains. - When not set, this option is enabled by default. + This option is enabled by default. advertise_routes: name: Advertise subnet routes description: >- This option allows you to advertise routes to subnets (accessible on the network your device is connected to) to other clients on your tailnet. - When not set, the add-on by default will advertise routes to your subnets on all - supported interfaces. + The add-on by default will advertise routes to your subnets on all supported + interfaces by adding `local_subnets` to the list. exit_node: name: Use exit node description: >- @@ -59,7 +59,7 @@ configuration: This option allows you to enable Tailscale Serve or Funnel features to present your Home Assistant instance with a valid certificate on your tailnet or on the internet. - When not set, this option is disabled by default. + This option is disabled by default. share_on_port: name: Share on port description: >- @@ -67,7 +67,7 @@ configuration: will use to present your Home Assistant instance on the tailnet and on the internet. Only ports 443, 8443, and 10000 are allowed by Tailscale. - When not set, port 443 is used by default. + Port 443 is used by default. snat_subnet_routes: name: Source NAT subnet routes description: >- @@ -75,14 +75,14 @@ configuration: subnet router, and this simplifies routing configuration. To support advanced Site-to-site networking (eg. to traverse multiple networks), you can disable this functionality. - When not set, this option is enabled by default. + This option is enabled by default. stateful_filtering: name: Stateful packet filtering description: >- This option enables stateful packet filtering on packet-forwarding nodes (exit nodes, subnet routers, and app connectors), to only allow return packets for existing outbound connections. - When not set, this option is disabled by default. + This option is disabled by default. tags: name: Tags description: >- @@ -93,7 +93,7 @@ configuration: description: >- This option allows you to enable Taildrop, a file sharing service that allows you to share files with other Tailscale nodes. - When not set, this option is enabled by default. + This option is enabled by default. userspace_networking: name: Userspace networking mode description: >- @@ -101,7 +101,7 @@ configuration: If you need to access other clients on your tailnet from your Home Assistant instance, disable userspace networking mode, which will create a `tailscale0` network interface on your host. - When not set, this option is enabled by default. + This option is enabled by default. network: 41641/udp: >- UDP port to listen on for WireGuard and peer-to-peer traffic.