Skip to content

#8 docs: Tailscale DNS proven across a graceful reboot - #10

Merged
gregoryfoster merged 4 commits into
mainfrom
8-reboot-proof
Oct 1, 2026
Merged

gregoryfoster merged 4 commits into
mainfrom
8-reboot-proof

Conversation

@gregoryfoster

@gregoryfoster gregoryfoster commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Refs #8. Follows #9.

What the reboot showed

This was a graceful sudo systemctl reboot of co-processor on 2026-10-01 at 16:41:59Z. A one-shot boot unit, since removed, timed each lookup from tailscaled's start. It would have rolled DNS back if public names had failed for 90 s.

  • tailscaled started 1.1 s into boot, at oom_score_adj -950, with CorpDNS: true.
  • Public names resolved on the probe's first try (+0.5 s), through exe.dev's resolver, before tailscaled took over. tailscaled wrote its own resolv.conf at +1.46 s (exact, from the file's mtime), and broker resolved by +1.65 s. The probe polled every 0.25 s, so the lookup times are upper bounds.
  • The boot's journal has no name-resolution error, and no units failed. tests/test_tailscaled.py passes on the node, 18 of 18, none skipped.

Corrected in DEPLOYMENT.md

  • Who writes /etc/resolv.conf. #8 co-processor runs Tailscale --accept-dns=true; tailscaled OOM drop-in; the broker by name #9 said exe-init writes it at every boot. That isn't what the reboot showed. exe.dev wrote it at the VM's first boot: it has the same 2026-09-29 mtime as /etc/hosts, and the reboot rewrote neither file. Both already held exe.dev's content, though, so whether exe.dev rewrites a file that differs at boot is unknown.
  • What restored the original file. The packaged unit's ExecStopPost=/usr/sbin/tailscaled --cleanup puts it back on a clean stop; the previous boot's journal shows the cleanup process running at shutdown. tailscaled then takes the file over again when it starts.
  • "At boot" now records the measurement. It notes that a hard reset (exe.dev restart) skips the stop hook, and that what follows is untested: either tailscaled's file is still there at boot, or exe.dev rewrites it first. It also says where the probe, its unit and its log are kept, so that path can be measured the same way.

Also posted to observo#631 (authorized): https://github.com/CannObserv/observo/issues/631#issuecomment-5936333096

Review

CR --fix, findings 10–12, one commit each:

  • CR 10: whether exe.dev rewrites resolv.conf at boot, and what the hard-reset path does, are now marked unknown. The reboot couldn't tell.
  • CR 11: the lookup times are marked as upper bounds from a 0.25 s poll; only the takeover (+1.46 s, from the file's mtime) is exact.
  • CR 12: the runbook says where the probe, its unit and its log live: /var/backups/processor/8/.

The observo#631 comment carried the same two claims and was corrected in place.

Gate

uv run pytest: 215 passed. ruff check, ruff format --check and uv lock --locked are clean, and the scratch Redis is clean.

🤖 Generated with Claude Code

gregoryfoster and others added 4 commits October 1, 2026 17:00
….conf at creation, not each boot

The 2026-10-01 reboot measured the boot path and disproved the runbook's claim
that exe-init rewrites /etc/resolv.conf at boot. The packaged unit's
ExecStopPost=tailscaled --cleanup restores the original on a clean stop. A
hard reset skips that hook and is untested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-different, so the hard-reset path is stated as unknown

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y the takeover (+1.46 s, mtime) is exact

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…its log live, for the hard-reset measurement

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant