Fix HostAuthorization blocking k8s probes and Tailscale hostname #232

Merged
ldraney merged 1 commit from 231-fix-host-authorization into main 2026-06-16 02:33:43 +00:00
Owner

Summary

PR #230 added config.hosts << "landscaping-assistant.app" which enabled HostAuthorization with only one allowed host. k8s probes hit the pod IP directly and get 403, causing CrashLoopBackOff. Tailscale hostname is also blocked.

Changes

  • config/environments/production.rb — add Tailscale prod and dev hostnames to config.hosts; exclude /up from HostAuthorization so health probes always pass
  • docs/networking.md — add Allowed Hosts section documenting every entry in config.hosts and when to update

Test Plan

  • New pod passes liveness/readiness probes (no more CrashLoopBackOff)
  • Production accessible via landscaping-assistant.tail5b443a.ts.net and landscaping-assistant.app
  • Dev accessible via landscaping-dev.tail5b443a.ts.net
  • /up returns 200 regardless of Host header

Review Checklist

  • No production logic changes — config and docs only
  • Fixes incident: new pods crash-looping since pipeline #586
  • Docs updated (docs/networking.md)

None — config fix.

Closes #231
Regression from: #224 / PR #230
Prior HostAuthorization fix: #103

## Summary PR #230 added `config.hosts << "landscaping-assistant.app"` which enabled HostAuthorization with only one allowed host. k8s probes hit the pod IP directly and get 403, causing CrashLoopBackOff. Tailscale hostname is also blocked. ## Changes - `config/environments/production.rb` — add Tailscale prod and dev hostnames to `config.hosts`; exclude `/up` from HostAuthorization so health probes always pass - `docs/networking.md` — add Allowed Hosts section documenting every entry in `config.hosts` and when to update ## Test Plan - [ ] New pod passes liveness/readiness probes (no more CrashLoopBackOff) - [ ] Production accessible via `landscaping-assistant.tail5b443a.ts.net` and `landscaping-assistant.app` - [ ] Dev accessible via `landscaping-dev.tail5b443a.ts.net` - [ ] `/up` returns 200 regardless of Host header ## Review Checklist - [x] No production logic changes — config and docs only - [x] Fixes incident: new pods crash-looping since pipeline #586 - [x] Docs updated (`docs/networking.md`) ## Related Notes None — config fix. ## Related Closes #231 Regression from: #224 / PR #230 Prior HostAuthorization fix: #103
Fix HostAuthorization blocking k8s probes and Tailscale hostname
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
CI / scan_ruby (pull_request) Has been cancelled
CI / scan_js (pull_request) Has been cancelled
CI / lint (pull_request) Has been cancelled
0a986431da
Closes #231

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

PR #232 Review

DOMAIN REVIEW

Tech stack: Rails 8.1, k8s (k3s), Tailscale Funnel ingress.

HostAuthorization fix (production.rb lines 97-101):

  • Adding Tailscale prod and dev hostnames to config.hosts is correct. These match the URLs documented in docs/networking.md and CLAUDE.md.
  • Uncommenting the host_authorization exclude lambda for /up is the right fix. k8s liveness/readiness probes send requests with the pod IP as the Host header, which will never match a named host. Excluding /up lets probes pass without weakening DNS rebinding protection for the rest of the app.
  • The exclude lambda uses exact path match (request.path == "/up"), which is appropriately narrow. No path traversal risk.
  • The /up route is confirmed at config/routes.rb:4 (get "up" => "rails/health#show"), so the excluded path maps to a real, read-only health endpoint.

Environment consistency verified:

  • development.rb:76 already has config.hosts << "landscaping-dev.tail5b443a.ts.net" -- no action needed there.
  • test.rb:34-35 clears hosts and excludes all requests from host auth entirely -- appropriate for test environment, no conflict with this change.

Documentation (networking.md):

  • New "Allowed Hosts (HostAuthorization)" section is well-placed between the existing "Dev Proxy" section and "Local Development."
  • The table documenting each host and its purpose matches the actual config.hosts entries exactly.
  • The maintenance instruction ("add it to config.hosts in production.rb and update this table") is a good operational safeguard against future regressions.

BLOCKERS

None.

NITS

  1. config.action_mailer.default_url_options at line 70 still uses host: "example.com". Not introduced by this PR, but worth a follow-up ticket if mailer functionality is ever enabled.

SOP COMPLIANCE

  • Branch named after issue (231-fix-host-authorization references issue #231)
  • PR body follows template (Summary, Changes, Test Plan, Review Checklist, Related Notes, Related)
  • Closes #231 present in Related section
  • References regression source (PR #230, issue #224, prior fix #103)
  • No secrets, .env files, or credentials committed
  • No unnecessary file changes -- only production.rb config and docs/networking.md
  • Commit message is descriptive ("Fix HostAuthorization blocking k8s probes and Tailscale hostname")
  • Test coverage: existing spec/requests/health_spec.rb covers the /up endpoint. No new application logic was added -- this is config-only, so no new tests are required.

PROCESS OBSERVATIONS

This is a clean incident response: PR #230 introduced a regression (HostAuthorization enabled with incomplete host list), the fix is minimal and correctly scoped, and the documentation update prevents recurrence by documenting the maintenance procedure. The single-commit, two-file change keeps the blast radius small. Good DORA practice -- fast recovery from a config regression.

VERDICT: APPROVED

## PR #232 Review ### DOMAIN REVIEW **Tech stack:** Rails 8.1, k8s (k3s), Tailscale Funnel ingress. **HostAuthorization fix (production.rb lines 97-101):** - Adding Tailscale prod and dev hostnames to `config.hosts` is correct. These match the URLs documented in `docs/networking.md` and `CLAUDE.md`. - Uncommenting the `host_authorization` exclude lambda for `/up` is the right fix. k8s liveness/readiness probes send requests with the pod IP as the `Host` header, which will never match a named host. Excluding `/up` lets probes pass without weakening DNS rebinding protection for the rest of the app. - The exclude lambda uses exact path match (`request.path == "/up"`), which is appropriately narrow. No path traversal risk. - The `/up` route is confirmed at `config/routes.rb:4` (`get "up" => "rails/health#show"`), so the excluded path maps to a real, read-only health endpoint. **Environment consistency verified:** - `development.rb:76` already has `config.hosts << "landscaping-dev.tail5b443a.ts.net"` -- no action needed there. - `test.rb:34-35` clears hosts and excludes all requests from host auth entirely -- appropriate for test environment, no conflict with this change. **Documentation (networking.md):** - New "Allowed Hosts (HostAuthorization)" section is well-placed between the existing "Dev Proxy" section and "Local Development." - The table documenting each host and its purpose matches the actual `config.hosts` entries exactly. - The maintenance instruction ("add it to `config.hosts` in `production.rb` **and** update this table") is a good operational safeguard against future regressions. ### BLOCKERS None. ### NITS 1. `config.action_mailer.default_url_options` at line 70 still uses `host: "example.com"`. Not introduced by this PR, but worth a follow-up ticket if mailer functionality is ever enabled. ### SOP COMPLIANCE - [x] Branch named after issue (`231-fix-host-authorization` references issue #231) - [x] PR body follows template (Summary, Changes, Test Plan, Review Checklist, Related Notes, Related) - [x] `Closes #231` present in Related section - [x] References regression source (PR #230, issue #224, prior fix #103) - [x] No secrets, .env files, or credentials committed - [x] No unnecessary file changes -- only production.rb config and docs/networking.md - [x] Commit message is descriptive ("Fix HostAuthorization blocking k8s probes and Tailscale hostname") - [x] Test coverage: existing `spec/requests/health_spec.rb` covers the `/up` endpoint. No new application logic was added -- this is config-only, so no new tests are required. ### PROCESS OBSERVATIONS This is a clean incident response: PR #230 introduced a regression (HostAuthorization enabled with incomplete host list), the fix is minimal and correctly scoped, and the documentation update prevents recurrence by documenting the maintenance procedure. The single-commit, two-file change keeps the blast radius small. Good DORA practice -- fast recovery from a config regression. ### VERDICT: APPROVED
ldraney deleted branch 231-fix-host-authorization 2026-06-16 02:33:43 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/landscaping-assistant!232
No description provided.