# Tx OS — Caddy reverse proxy in HTTPS_MODE=auto.
#
# Issues + renews a real Let's Encrypt certificate for $PUBLIC_DOMAIN.
# Used when the operator points a stable custom domain (e.g.
# `tx.example.com`) at the box and wants automatic TLS — this keeps
# iPad Web Push subscriptions valid forever, because subscriptions
# are bound to the origin (host) they were created under and a stable
# hostname means they never get orphaned when Tailscale or the LAN IP
# changes.
#
# Requirements:
#   - PUBLIC_DOMAIN env var must be set (e.g. tx.example.com).
#   - DNS A/AAAA record for PUBLIC_DOMAIN points at this host.
#   - Ports 80 + 443 are reachable from the public internet (ACME
#     HTTP-01 / TLS-ALPN challenge). Behind a NAT/firewall you must
#     forward both. If only 443 is reachable, switch ACME to DNS-01
#     by extending this file with a DNS provider plugin.
#   - ACME_EMAIL env var SHOULD be set for renewal notifications.
#
# The site MUST stay single-origin so the API session cookie
# (sameSite=lax) keeps working across SPA + /api requests.

{
{$ACME_EMAIL_DIRECTIVE}
admin off
}

(api_proxy) {
@websocket {
header Connection *Upgrade*
header Upgrade websocket
}
reverse_proxy /api/socket.io/* api:8080
reverse_proxy /api/* api:8080
}

(spa_proxy) {
reverse_proxy web:80
}

# ---------- HTTPS site for the public custom domain ----------
# Caddy auto-issues + renews the cert via ACME when this host is
# reached over HTTPS for the first time.
{$PUBLIC_DOMAIN} {
encode zstd gzip
import api_proxy
import spa_proxy
}

# Plain HTTP → permanent redirect to HTTPS. Caddy still needs :80
# bound so the ACME HTTP-01 challenge can be answered.
:80 {
redir https://{host}{uri} permanent
}
