# Caddyfile — единый HTTP/HTTPS public boundary Chatballs (ADR-HUB-0028 §gateway). # Подставляется в release bundle и монтируется в контейнер gateway. # # Свежая установка не знает своего домена: человек поднимает докер на сервере и # открывает её по IP. Поэтому здесь нет блоков с зашитым именем хоста — они бы # заставили Caddy выпускать сертификат и уводить http на https до того, как # домен вообще появился. Вместо них: :80 отвечает по http на любом адресе, а # https обслуживает любой хост, который одобрил ask-эндпоинт (домены порталов и # домен установки, заданный в UI). Сертификаты выписываются по мере надобности, # без перезапуска шлюза. { # ACME-контакт не задаётся при установке: пока домена нет, нет и выпуска # сертификатов. Адрес для уведомлений добавляется вместе с доменом в UI. # Caddy admin API не публикуется наружу (default localhost:2019). on_demand_tls { ask http://backend-platform:8000/api/v1/gateway/help-domain/ } # Установку часто ставят за прокси панели (aaPanel, nginx хоста), который # снимает TLS и ходит сюда по http. Его X-Forwarded-Proto/For принимаются # только из частных сетей — оттуда, где такой прокси и стоит; клиент из # интернета подделать их не может. servers { trusted_proxies static private_ranges } } (surfaces) { # Host уходит с портом: браузер шлёт Origin с портом (http://ip:8081), и # без него CSRF-проверка Django отвергала любой POST на нестандартном # порту. X-Forwarded-Proto Caddy ставит сам: {scheme}, а за доверенным # прокси — то, что прислал прокси (https, если TLS снят перед нами). # Платформенная поверхность живёт на своём домене; пока он не задан, # матчер намеренно не совпадает ни с чем. @platform host {$CHATBALLS_PLATFORM_DOMAIN:platform.invalid} handle @platform { reverse_proxy backend-platform:8000 { header_up Host {hostport} header_up X-Real-IP {client_ip} header_up X-Forwarded-For {client_ip} } } # Всё остальное — приложение и публичные порталы: маршрутизация внутри # frontend-контейнера. handle { reverse_proxy frontend:80 { header_up Host {hostport} header_up X-Real-IP {client_ip} header_up X-Forwarded-For {client_ip} } } } # Обычный http на любом адресе: IP сервера, localhost, ещё не подтверждённый # домен. Редиректа на https здесь нет намеренно — его делает блок ниже, когда # для хоста реально выписан сертификат. :80 { encode gzip zstd import surfaces } # Дополнительные сайты из постоянного тома сохраняются при обновлении шлюза. import /config/sites/*.caddy # Любой хост, которому ask-эндпоинт разрешил сертификат. https:// { encode gzip zstd tls { on_demand } import surfaces }