Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export LOG_FD
# Home Assistant Community App: Tailscale
# Runs after the machine has been logged in into the Tailscale network
# ==============================================================================

shopt -s extglob

declare interface
declare -a options
declare -a routes=()
Expand All @@ -13,6 +16,9 @@ declare -a colliding_routes=()
declare login_server
declare tags
declare keyexpiry
declare error_message
declare backend_state
declare nostate_started_timestamp

# Default options
options+=(--hostname "$(bashio::info.hostname)")
Expand Down Expand Up @@ -90,17 +96,41 @@ IFS=","
options+=(--advertise-routes="${routes[*]}")
unset IFS

# Wait for the network to be available and logged in
# Wait for the network to be available
# Loop here while BackendState is:
# - Starting
# - NoState (first time connecting to control) for less than 30s, to handle potential startup transients
# Move on to tailscale up, when BackendState is:
# - NoState (first time connecting to control) for more than 30s
# - Stopped (result of a manual tailscale down command)
# - NeedsLogin
# - NeedsMachineAuth
# - Running
# Note: {} is used instead of () to achieve && precedence over || without subshell,
# subshell would not update the value of nostate_started_timestamp here
while ! bashio::fs.socket_exists "/var/run/tailscale/tailscaled.sock" || \
! /opt/tailscale status --json --peers=false --self=false \
| jq --exit-status '.BackendState == "Running" or .BackendState == "NeedsLogin" or .BackendState == "Stopped"' > /dev/null;
! backend_state=$( \
/opt/tailscale status --json --peers=false --self=false \
| jq -rcM '.BackendState') || \
[[ ! "${backend_state}" = @(NoState|Stopped|NeedsLogin|NeedsMachineAuth|Running) ]] || \
{ [[ "${backend_state}" == "NoState" ]] && \
(( $(date +"%s") - ${nostate_started_timestamp:=$(date +"%s")} < 30 )) }
do
sleep 2
done

# Start Tailscale
if ! /opt/tailscale up "${options[@]}"; then
bashio::exit.nok "Unable to start up Tailscale"
# Capture stderr in a variable but write it to the log also
if ! { error_message=$(/opt/tailscale up "${options[@]}" 2> >(tee /dev/fd/2) 1>&3); } 3>&1; then
if [[ $error_message != *"can't change --login-server without --force-reauth"* ]]; then
bashio::exit.nok "Unable to start up Tailscale"
fi
# Execute this only, if tailscale up explicitly complained about this
bashio::log.warning "The login server option has changed, forcing reauthentication"
options+=(--force-reauth)
if ! /opt/tailscale up "${options[@]}"; then
bashio::exit.nok "Unable to start up Tailscale"
fi
fi

# Wait for the network to be available and logged in
Expand Down
Loading