Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions packaging/caddy/Caddyfile.template
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@
reverse_proxy 127.0.0.1:8080
}

# Public allowlist — paths that MUST be reachable without basic_auth
# so the first-run wizard can bootstrap before any credential exists,
# and so monitoring tools can scrape liveness without holding creds.
#
# This list mirrors the PUBLIC_PATHS frozenset in
# src/hal0/api/middleware/auth.py — keep them in sync. The `path`
# matcher is exact-match (no trailing-slash or prefix expansion), which
# matches the `request.url.path in PUBLIC_PATHS` check on the API side.
#
# This block MUST stay above the default `handle {}` below — Caddy
# evaluates `handle` blocks in source order and the first match wins,
# so listing `@public` later would let basic_auth swallow the wizard
# probes (see issue #28).
@public path /api/health/system \
/api/status \
/api/metrics \
/api/features \
/api/install/state \
/api/install/complete \
/api/config/urls \
/api/auth/status \
/api/auth/login \
/api/auth/logout \
/v1/models
handle @public {
reverse_proxy 127.0.0.1:8080
}

# Dashboard + management API — Caddy basicauth at the edge. Forwards
# the identity as X-Forwarded-Email so the hal0 API trusts the user
# as admin (see hal0.api.middleware.auth precedence).
Expand Down
15 changes: 12 additions & 3 deletions tests/harness/installer-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,20 @@ else
HAL0_HOSTNAME=hal0-harness.local HAL0_TLS_EMAIL=harness@hal0.test \
HAL0_NO_PROBE=1 HAL0_PLAIN=1 \
sudo -E bash "${REPO_ROOT}/installer/install.sh" --auth=basic --no-start >"${LOG4}" 2>&1; then
# Regression for #28: the rendered Caddyfile must carry the
# @public matcher + `handle @public` block BEFORE the default
# basicauth handler, else the first-run wizard's pre-auth
# /api/install/state + /api/config/urls probes 401 and the
# SPA can't bootstrap. Asserting both halves (matcher + handle)
# so a future edit that drops one without the other is caught.
if [[ -f /etc/hal0/Caddyfile ]] && grep -q basicauth /etc/hal0/Caddyfile \
&& grep -q HAL0_AUTH_ENABLED=1 /etc/hal0/api.env; then
add_row "auth-basic" "pass" "$(since_ms "${start}")" "Caddyfile + api.env auth wiring rendered"
&& grep -q HAL0_AUTH_ENABLED=1 /etc/hal0/api.env \
&& grep -q '@public path' /etc/hal0/Caddyfile \
&& grep -q 'handle @public' /etc/hal0/Caddyfile \
&& grep -q '/api/install/state' /etc/hal0/Caddyfile; then
add_row "auth-basic" "pass" "$(since_ms "${start}")" "Caddyfile + api.env auth wiring rendered (incl. @public allowlist)"
else
add_row "auth-basic" "fail" "$(since_ms "${start}")" "Caddyfile or api.env auth flag missing post-install"
add_row "auth-basic" "fail" "$(since_ms "${start}")" "Caddyfile or api.env auth flag missing post-install (check @public allowlist for #28)"
fi
else
rc=$?
Expand Down
Loading