docs(plans): scope Caddy form-based auth (caddy-security plugin)#129
Merged
smartwatermelon merged 4 commits intomainfrom Apr 20, 2026
Merged
docs(plans): scope Caddy form-based auth (caddy-security plugin)#129smartwatermelon merged 4 commits intomainfrom
smartwatermelon merged 4 commits intomainfrom
Conversation
Plan for replacing basic_auth with a form-based login so 1Password can auto-fill. Single user, no MFA, JWT session cookie, local bcrypt store. Custom Caddy rebuild with caddy-security alongside existing caddy-dns/cloudflare — same pattern as the current binary. Not implementing today. ~5-6 hours wall-clock when picked up. Includes rollback steps and a list of deliberately out-of-scope follow-ups (MFA, OIDC, per-path auth) that slot in later without rearchitecting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…template
Sentry bug-prediction flagged that Task 5 Step 3 proposed a users.json
template with __MONITORING_EMAIL__ but never instructed extending
caddy-setup.sh's substitute_template() to handle that placeholder. A
future implementer following the plan verbatim would deploy a users.json
containing the literal string __MONITORING_EMAIL__ as the user's email,
which caddy-security's local identity store would reject.
Fix (matches Sentry's primary suggested fix):
- Task 5 Step 3: call out that substitute_template's sed list must add
-e "s|__MONITORING_EMAIL__|${MONITORING_EMAIL}|g" and that
caddy-setup.sh must load MONITORING_EMAIL from config.conf.
- Task 6: insert a new Step 1 preflight check that MONITORING_EMAIL is
non-empty before any substitution runs; renumber the remaining steps.
Post-push loop iteration 1: addresses sentry[bot] finding on
docs/plans/2026-04-19-caddy-forms-auth.md:346
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sentry bug-prediction flagged that Task 7 Step 6's rollback cp reference a Caddyfile.pre-forms-auth backup that no prior step creates — only the binary backup (Task 1 Step 2) and a parenthetical reminder *after* the rollback command existed. A linear reader would overwrite the Caddyfile in Step 2 without backing it up first, and discover the rollback recipe is broken only when they need it. Fix (matches Sentry's primary suggested fix): - Insert explicit Task 7 Step 2 "Back up the current deployed Caddyfile" before the caddy-setup.sh invocation. - Renumber subsequent Step 3..8. - Drop the confusing parenthetical at the old Step 6. - Update the CLAUDE.md operations-doc bullet that referenced old step 6. Post-push loop iteration 2: addresses sentry[bot] finding on docs/plans/2026-04-19-caddy-forms-auth.md:544 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ran the adversarial reviewer locally on the full plan (not just the one
line Sentry flagged) to catch everything in one pass and stop the CI
ping-pong. Applies every substantive finding plus the previously
uncommitted cross-midnight rollback fix:
- Task 1 Step 3: clarify Homebrew pin is on TILSIT, not dev machine
(the dev machine builds via the Caddy download API, not brew).
- Task 2 Step 3: JWT keychain install must go through
`ssh andrewrich@tilsit.local` (not operator) — non-interactive SSH as
operator cannot run sudo without a TTY, and System keychain writes
require root.
- Task 5 Step 3: explicit placement instructions for the three
caddy-setup.sh edits. users.json deploy must happen BEFORE `caddy
validate` runs, otherwise caddy-security's `local identity store`
directive sees a missing file and rejects the config.
- Task 5 removes the broken "validate locally" sub-step that referenced
/tmp/Caddyfile.substituted — a file no prior step produces. Rely on
caddy-setup.sh's built-in validate after deploy.
- Task 7 Step 2 expected-output strings now match what caddy-setup.sh
actually emits ("✓ Copied Caddyfile to ..." not "✓ Installed ...").
- Task 7 Step 5 functional tests: split into on-TILSIT (LAN bypass only)
and from-dev-machine (external path). Previous version ran all curls
from TILSIT itself, which hits the @local_network matcher and makes
every external assertion pass for the wrong reason.
- Task 7 Step 7 rollback: uses `ls -t | head -1` glob lookup instead of
`$(date +%Y%m%d)` reconstruction, which would break if the cutover
rolls past midnight — exactly when rollback is most needed.
Post-push-loop iteration 3: addresses sentry[bot] cross-midnight finding
(docs/plans/2026-04-19-caddy-forms-auth.md:555) + seven additional
local-review findings caught pre-push, not post-push.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner
Author
|
Pre-merge note — NEUTRAL checks are benign
All findings from the post-push loop on this PR are resolved:
Consolidated exhaustive local-review pass in 6d552d0 also addressed seven additional findings pre-push. Safe to merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/plans/2026-04-19-caddy-forms-auth.md— a task-by-task implementation plan for replacing Caddy'sbasic_authwith a form-based login that 1Password can auto-fill.Approach (from the plan)
Rebuild the custom Caddy binary with the
caddy-securityplugin alongside the existingcaddy-dns/cloudflaremodule. Same pattern already used for DNS-01. JWT session cookie, bcrypt password hash in ausers.json, single user, no MFA. LAN bypass matcher is preserved.Effort estimate: ~5–6 hours wall-clock across 8 tasks. Rollback procedure and deliberately-parked follow-ups (MFA, OIDC, per-path auth) are documented in the plan.
Test plan
markdownlint --config ~/.config/markdownlint-cli/.markdownlint.jsonpasses🤖 Generated with Claude Code
Tracks #130.