# Managed by Ansible — do not edit manually. api.{{ domain }} { # MQTT auth is no longer an HTTP backend c2-core exposes (it moved to # mosquitto's own built-in dynamic-security plugin, administered over MQTT # control topics — see app/internal/dynsec.py) — there is currently no # /internal/* route in c2-core at all. This block stays anyway as defence # in depth: c2-core's app-wide reverse_proxy below forwards every path by # default, so this guarantees any FUTURE /internal/* route (or a # regression that reintroduces one) is still unreachable from the public # internet unless someone also deliberately deletes this block. `route` # forces top-to-bottom evaluation instead of Caddy's automatic directive # sorting, so this is guaranteed to run before reverse_proxy. route { respond /internal/* 404 reverse_proxy localhost:8888 { header_up X-Forwarded-For {remote_host} } } } # mqtt.{{ domain }} has no application behind it — mosquitto's TLS listener # (8883) is a raw MQTT socket, not HTTP, so Caddy can't reverse_proxy to it. # This block's only job is to make Caddy request+manage a Let's Encrypt cert # for the name via ACME HTTP-01, which infra/ansible's cert-sync unit then # copies out to mosquitto. The DNS A record for mqtt.{{ domain }} must exist # before this runs, or ACME issuance fails (see MQTT-PUBLIC-AUTH-PLAN.md). mqtt.{{ domain }} { respond 404 } # Frontend is served on the bare domain, not app.{{ domain }}: only drb and api # have public DNS records. A vhost for a name with no A record still starts, # but Caddy retries ACME against it forever and logs a failure each time. # To move it to app.{{ domain }}, create the A record first, then change this # line — the reverse_proxy target stays the same either way. {{ domain }} { route { # Firebase Auth's sign-in handler, served from our own origin. # # signInWithPopup opens {{ firebase_auth_handler_host | default('discord-radio-bot-461301.firebaseapp.com') }}/__/auth/handler and # then reads back state the opener wrote. Chrome now partitions third-party # storage, so when that handler is on a different site from the app the # popup cannot see that state: it opens, fails, and closes instantly with no # console or network trace. The handler page says so itself if you visit it # directly ("storage-partitioned browser environment"). # # Proxying the handler through this domain makes it same-site, which is # Google's documented fix. Host must be rewritten upstream or Firebase # Hosting will not recognise the request. # # NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN must be set to {{ domain }} in the CI # build secrets to match, and {{ domain }} must be listed in the Firebase # console's authorised domains. Changing only one of the three does nothing. handle /__/auth/* { reverse_proxy https://{{ firebase_auth_handler_host | default('discord-radio-bot-461301.firebaseapp.com') }} { header_up Host {{ firebase_auth_handler_host | default('discord-radio-bot-461301.firebaseapp.com') }} } } reverse_proxy localhost:3000 { header_up X-Forwarded-For {remote_host} } } }