fix: reset stale Tailscale funnel/serve state on restart#2600
Conversation
- Purpose: clear stale Tailscale Serve and Funnel state when a Docker template changes mode or disables serving. - Before: switching a container from Funnel or Serve to No removed the env vars but left the persisted Tailscale config active after restart. - Why: the hook only applied new serve settings when TAILSCALE_SERVE_PORT was present and never reset the existing serve or funnel config stored in the Tailscale state directory. - What: reset both tailscale funnel and tailscale serve state after tailscale comes online, then reapply the current template-managed mode if one is configured. - How: add explicit reset commands in the container hook before the Serve/Funnel capability check and before any new serve or funnel command is issued. - Verification: bash -n share/docker/tailscale_container_hook
WalkthroughA Docker hook script now clears persisted Tailscale Serve and Funnel configuration by executing Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~5 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
🔧 PR Test Plugin AvailableA test plugin has been generated for this PR that includes the modified files. Version: 📥 Installation Instructions:Install via Unraid Web UI:
Alternative: Direct Download
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@share/docker/tailscale_container_hook`:
- Around line 305-306: The two silent reset calls (tailscale funnel reset and
tailscale serve reset) should not discard all errors; run each reset, capture
its stdout/stderr and exit code, and if the exit code is non-zero log a clear
warning including the command name (tailscale funnel reset / tailscale serve
reset) and the captured output so failures like permission or runtime errors are
visible; optionally retry once or escalate to a non-fatal error path (exit only
if you detect a fatal condition such as permission denied) so startup isn’t
silently allowed to continue with stale state.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 800d4fa3-7332-426e-b5e9-a74bf413c3cb
📒 Files selected for processing (1)
share/docker/tailscale_container_hook
| tailscale funnel reset >/dev/null 2>&1 || true | ||
| tailscale serve reset >/dev/null 2>&1 || true |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Are tailscale funnel resetandtailscale serve reset available in all currently supported stable Tailscale CLI versions, and which version first introduced each command?
💡 Result:
Yes, tailscale funnel reset and tailscale serve reset are available in all currently supported stable Tailscale CLI versions. Tailscale's current stable versions are in the 1.9x series (e.g., up to 1.96.4 as of March 2026), and all supported stable versions are 1.52 and later. Both commands were first introduced in Tailscale v1.52 (October 2023), as part of a CLI rework for funnel and serve subcommands that added status and reset subcommands. Official docs (updated January 2026) confirm: "The CLI commands for both Tailscale Funnel and Tailscale Serve have changed in the 1.52 version" and document tailscale funnel reset and tailscale serve reset. The blog post "Reintroducing Serve and Funnel" (October 30, 2023) announces these changes for v1.52 or later. Funnel/Serve originated earlier (v1.38+), but the reset subcommands came with the v1.52 syntax update. No changelog entries contradict this, and security bulletins reference v1.52 for related serve/funnel fixes.
Citations:
- 1: https://tailscale.com/docs/reference/tailscale-cli/funnel
- 2: https://tailscale.com/docs/reference/tailscale-cli/serve
- 3: https://tailscale.com/blog/reintroducing-serve-funnel
- 4: https://www.apkbgmi.com
- 5: https://tailscale.com/security-bulletins/
- 6: https://releasealert.dev/github/tailscale/tailscale
- 7: cmd/tailscale/cli: [serve] rework commands based on feedback tailscale/tailscale#6521
Evaluate failure handling for reset commands; CLI availability is confirmed, but silent failures can hide stale state.
Lines 305–306 suppress all reset errors (>/dev/null 2>&1 || true), which can mask runtime failures and leave stale persisted config active. While tailscale funnel reset and tailscale serve reset are available in all supported Tailscale versions (v1.52+), silent suppression hides other failure modes (permissions, runtime errors) that could prevent the reset from completing while allowing startup to proceed normally.
Consider capturing reset failures explicitly:
💡 Proposed fix
echo "Resetting Tailscale Serve/Funnel configuration"
-tailscale funnel reset >/dev/null 2>&1 || true
-tailscale serve reset >/dev/null 2>&1 || true
+RESET_FAILED="false"
+if ! tailscale funnel reset >/dev/null 2>&1; then
+ echo "WARNING: Failed to reset Tailscale Funnel configuration."
+ RESET_FAILED="true"
+fi
+if ! tailscale serve reset >/dev/null 2>&1; then
+ echo "WARNING: Failed to reset Tailscale Serve configuration."
+ RESET_FAILED="true"
+fi
+
+# If template-managed Serve/Funnel is disabled, failing reset means stale exposure
+# may persist; do not continue silently.
+if [ "${RESET_FAILED}" = "true" ] && [ -z "${TAILSCALE_SERVE_PORT}" ]; then
+ echo "ERROR: Could not clear persisted Serve/Funnel state while Tailscale Serve is disabled."
+ error_handler
+fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@share/docker/tailscale_container_hook` around lines 305 - 306, The two silent
reset calls (tailscale funnel reset and tailscale serve reset) should not
discard all errors; run each reset, capture its stdout/stderr and exit code, and
if the exit code is non-zero log a clear warning including the command name
(tailscale funnel reset / tailscale serve reset) and the captured output so
failures like permission or runtime errors are visible; optionally retry once or
escalate to a non-fatal error path (exit only if you detect a fatal condition
such as permission denied) so startup isn’t silently allowed to continue with
stale state.
🧹 PR Test Plugin Cleaned UpThe test plugin and associated files for this PR have been removed from the preview environment. 🤖 This comment is automatically generated when a PR is closed. |
- Purpose: backport PR #2600 to the 7.2 branch so Docker template changes clear old Tailscale Serve and Funnel exposure.\n- Before: switching a container from Funnel or Serve to No removed the env vars but left the persisted Tailscale serve/funnel config active after restart.\n- Why: the container hook only applied new serve settings when TAILSCALE_SERVE_PORT was present and never reset existing serve state stored in the Tailscale state directory.\n- What: reset both tailscale funnel and tailscale serve state after tailscale comes online, then reapply the current template-managed mode when configured.\n- How: add explicit reset commands before the Serve/Funnel capability check and before issuing any new serve or funnel command.\n- Source: cherry-picked from b90ca2f.
Summary
tailscale upTailscale Serve = Nofrom keeping an old funnel exposure after restartRoot cause
The container hook persisted serve/funnel state in the Tailscale state directory. When a user changed the Docker template from
FunnelorServetoNo, the related env vars disappeared, but the hook never cleared the old state before startup completed.Verification
bash -n share/docker/tailscale_container_hookRelated report
Notes
Summary by CodeRabbit