Files
mempalace/deploy/unraid/Caddyfile
T
2026-05-09 10:52:25 -05:00

62 lines
2.0 KiB
Caddyfile

# 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
}
}