SmartestHome/tools/generate-caddyfile.sh

119 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Generate the reverse proxy's Caddyfile from CoreSystemConfig.json.
#
# Called by the container-host ISO builder and by setup-container-host.sh, so the proxy
# is configured from the same single source as everything else — the hostname it serves,
# the ports it forwards to, and which services exist at all.
#
# tools/generate-caddyfile.sh <destination-path>
#
# See proxy/README.md for why this exists (short version: the admin panel's token is in
# a URL, the registration camera needs a secure context, and a mixed-content page can't
# call its own API).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/coreconfig.sh
source "${SCRIPT_DIR}/lib/coreconfig.sh"
DEST="${1:-}"
[[ -n "$DEST" ]] || core_die "Usage: $0 <destination Caddyfile path>"
core_load
if [[ "$CORE_PROXY_ENABLED" != "true" ]]; then
core_warn "proxy.enabled is false — nothing to generate."
exit 0
fi
# TLS directive. `tls internal` is Caddy's own CA; the custom branch points at mounted
# files. Note the paths are the CONTAINER's, not the host's — the compose service
# mounts them read-only at these locations.
if [[ "$CORE_PROXY_TLS" == "custom" ]]; then
TLS_LINE=" tls /etc/caddy/certs/cert.pem /etc/caddy/certs/key.pem"
else
TLS_LINE=" tls internal"
fi
# Only proxy services that exist. A route to a container that was never started would
# give a 502 that looks like a proxy fault rather than a service that isn't enabled.
PANTRY_ROUTE=""
if [[ "$CORE_ENABLE_PANTRY_VISION" == "true" ]]; then
PANTRY_ROUTE="
# pantry-vision's API, same prefix-stripping as identity's.
handle_path /api/pantry/* {
reverse_proxy pantry-vision:${CORE_PORT_PANTRY_VISION}
}
"
fi
mkdir -p "$(dirname "$DEST")"
cat > "$DEST" <<EOF
# GENERATED from CoreSystemConfig.json by tools/generate-caddyfile.sh.
# Edit the config and re-run; edits here are overwritten on the next build.
#
# One HTTPS front door for this repo's own services. Home Assistant, Grocy, Frigate,
# Portainer and the rest keep their own ports and are deliberately NOT behind this —
# fronting HA in particular brings its own auth and websocket concerns, and none of the
# problems this proxy solves (see proxy/README.md) need it.
{
# No ACME account e-mail: with 'tls internal' there is no public CA involved, and
# with 'custom' the certificate is already issued. Neither path talks to Let's
# Encrypt, which is what keeps this working on a network with no WAN access at all.
admin off
}
# --- HTTP: redirect everything, permanently -----------------------------------------
# Caddy does this automatically for a site with TLS, but it is written out explicitly
# because "the tool probably handles it" is a poor thing to rely on for the one rule
# that stops a token being sent in cleartext.
http://${CORE_PROXY_HOSTNAME} {
redir https://{host}{uri} permanent
}
# --- HTTPS ---------------------------------------------------------------------------
https://${CORE_PROXY_HOSTNAME} {
${TLS_LINE}
# identity's API. handle_path strips the matched prefix, so /api/identity/people
# reaches the container as /people — the service is unchanged and unaware it is
# behind a proxy.
handle_path /api/identity/* {
reverse_proxy identity:${CORE_PORT_IDENTITY}
}
${PANTRY_ROUTE}
# Everything else is the static frontend: dashboard.html, register.html, admin.html.
handle {
reverse_proxy identity-web:80
}
# The admin panel's token is in its URL, so keep that URL out of shared caches and
# out of anything that might log a referer to a third party.
header {
Referrer-Policy "no-referrer"
Cache-Control "no-store"
X-Content-Type-Options "nosniff"
# HSTS is deliberately NOT set. With 'tls internal' it would pin browsers to
# HTTPS for a hostname whose CA they may not trust yet, turning a dismissible
# warning into a hard failure that is genuinely awkward to undo.
}
log {
output stderr
format console
}
}
EOF
core_log "Wrote ${DEST}"
echo " Front door : https://${CORE_PROXY_HOSTNAME}"
echo " Admin panel: ${CORE_ADMIN_URL}"
if [[ "$CORE_PROXY_TLS" == "internal" ]]; then
echo
echo " TLS is Caddy's internal CA. Browsers will warn until you install its root:"
echo " tools/export-proxy-ca.sh"
fi