# MemPalace Caddy reverse-proxy config.
# -----------------------------------------------------------------------------
# Listens on :8443 with a self-signed (Caddy-internal) cert. Enforces a
# bearer-token check on every request and proxies authenticated traffic to
# the mempalace container.
#
# Two upstream paths:
#   /sse, /messages*  -> mempalace:8765  (mcp-proxy SSE for MCP tool calls)
#   /ingest*          -> mempalace:8766  (in-process HTTP ingest endpoint)
#   /healthz          -> mempalace:8766  (no auth, for liveness probes)
#
# Token comes from the MEMPAL_TOKEN env var (set in deploy/unraid/.env).
# -----------------------------------------------------------------------------

{
	# Disable the admin API — never expose it from a container that's
	# reachable from clients.
	admin off
	# Ship access logs to stderr so `docker logs caddy` is useful.
	log {
		output stderr
		format console
	}
}

:8443 {
	tls internal

	# Liveness probe — no auth so Docker / external monitors can hit it
	# without holding the bearer token.
	handle /healthz {
		reverse_proxy mempalace:8766
	}

	# Auth gate. matcher passes only when the Authorization header is
	# exactly `Bearer ${MEMPAL_TOKEN}`. Header matching is exact-match.
	@authorized header Authorization "Bearer {$MEMPAL_TOKEN}"

	# MCP-over-SSE: the MCP transport sends events on /sse and accepts
	# JSON-RPC POSTs on /messages (path varies by mcp-proxy version, so
	# proxy the whole prefix tree).
	handle @authorized {
		# SSE responses are streamed — disable buffering and force HTTP/1.1
		# upstream to keep the event stream open.
		reverse_proxy /sse* /messages* mempalace:8765 {
			flush_interval -1
			transport http {
				versions 1.1
			}
		}
		reverse_proxy /ingest* mempalace:8766
	}

	# Default: anything not matched above (or unauthenticated traffic) is
	# rejected. Returning 401 instead of 403 is correct here — clients with
	# no/invalid token can re-attempt with credentials.
	respond 401 {
		body "Unauthorized"
		close
	}
}
