Skip to content

chore: rewrite Tailscale dashboard security with serve approach#90

Merged
TechNickAI merged 5 commits into
mainfrom
chore/tailscale-dashboard-rewrite
Apr 19, 2026
Merged

chore: rewrite Tailscale dashboard security with serve approach#90
TechNickAI merged 5 commits into
mainfrom
chore/tailscale-dashboard-rewrite

Conversation

@TechNickAI
Copy link
Copy Markdown
Owner

Summary

  • Rewrites Tailscale dashboard security doc with tailscale serve + /etc/resolver approach (replaces manual TLS cert management)
  • Adds Tailscale DNS troubleshooting guide
  • Updates machine-setup.md with Tailscale serve integration steps
  • Removes tailnet-specific suffixes from example commands

Test plan

  • PII scan clean — all generic placeholders
  • Pre-commit hooks pass

🤖 Generated with Claude Code

Nick Sullivan added 4 commits April 19, 2026 09:27
- Add Approach 2 (funnel) for machines missing Tailscale network extension
- Document why serve fails when network extension isn't installed (DNS resolves to public ingress IPs)
- Add troubleshooting section for common issues (etag mismatch, DNS, bind:loopback)
- Update machine-setup.md gateway section with remote dashboard access checklist
- Document funnel persistence (no launchd needed - Tailscale manages it)
- Document /etc/resolver/ts.net DNS fix for Homebrew-installed Tailscale
  (utun interface can't intercept DNS without network extension)
- Rewrite security doc around serve (tailnet-only) instead of funnel
- Update machine-setup.md with DNS fix as step 1
- Add troubleshooting for DNS resolution failures
- Security: loopback bind + token auth + device auth + serve = 4 layers
- Funnel moved to fallback section with explicit warnings
Homebrew Tailscale uses utun (no network extension), so *.ts.net DNS
queries aren't intercepted. The fix is /etc/resolver/ts.net pointing
to 100.100.100.100. Must be applied on every machine, not just server.
Document covers why it breaks, how to fix, how to verify (don't use dig),
and common mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 430430489a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

3. **Use a gateway password** as an explicit multi-factor check instead of just an
opaque token.
```bash
echo "nameserver 100.100.100.100" | sudo tee /etc/resolver/ts.net
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Create resolver directory before writing ts.net resolver

The fix command writes directly to /etc/resolver/ts.net, but on clean macOS installs /etc/resolver often does not exist, so this step fails and leaves DNS unconfigured. In that state, the later tailscale serve setup won’t persist (the exact failure this doc is trying to prevent). Add sudo mkdir -p /etc/resolver before the tee command.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — added sudo mkdir -p /etc/resolver in all three docs (security, troubleshooting, machine-setup). Fixed in 994a75c.

Comment thread devops/machine-setup.md Outdated
Comment on lines +236 to +237
3. **Verify:** `curl -sS https://<hostname>.ts.net/ | head -1` — should return
`HTTP/2 200`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify HTTPS with response headers, not page body

This verification command checks the first line of the response body but the text says it should return HTTP/2 200, which is a status line only present in headers. Without -i, -I, or a -w status formatter, users will see HTML content instead of status and may incorrectly conclude the setup is broken.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — changed to curl -sS -o /dev/null -w "%{http_code}" https://<hostname>.ts.net/ which correctly shows the HTTP status code. Fixed in 994a75c.

Comment thread devops/tailscale-dns-troubleshooting.md Outdated
curl -sS --max-time 5 https://<hostname>.ts.net/ -o /dev/null -w "%{remote_ip}\n"

# Node.js (uses system resolver)
node -e "require('dns').resolve4('<hostname>.ts.net', (e,a) => console.log(a))"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use dns.lookup for system resolver validation

The troubleshooting section says this Node.js command uses the system resolver, but require('dns').resolve4(...) uses DNS queries directly rather than OS name-resolution behavior. That can produce 209.x results even when /etc/resolver/ts.net is correctly configured, making this check misleading in exactly the scenario being diagnosed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — dns.resolve4 makes direct DNS queries bypassing /etc/resolver. Changed to dns.lookup which uses getaddrinfo (system resolver). Fixed in 994a75c.

- Add `mkdir -p /etc/resolver` before writing resolver file (all 3 docs)
- Fix curl verify command to show HTTP status code instead of body
- Fix Node.js DNS example to use `dns.lookup` (system resolver) not `dns.resolve4`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@TechNickAI TechNickAI merged commit 9e6a6f2 into main Apr 19, 2026
12 checks passed
@TechNickAI TechNickAI deleted the chore/tailscale-dashboard-rewrite branch April 19, 2026 14:39
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