Запланировано как Phase 2 поверх hash-based-subdomain (Phase 1). В продакшене не задействовано.
Cloudflare-managed механизм для проксирования client-owned доменов на наш origin. Бывшее название — “SSL for SaaS”. Используется GitBook, Shopify, Notion, и т.п. для white-label custom domains.
Что делает
Клиент добавляет CNAME запись на стороне своего DNS (patient.pzalab.com → {our-origin}). Мы регистрируем hostname через Cloudflare API. CF автоматически:
- Выпускает SSL certificate (через ACME)
- Маршрутизирует traffic на наш origin
- Верифицирует ownership (CNAME совпадает → confirmed)
Клиенту нужна одна CNAME запись (плюс optional CAA для restrict CA).
Использование в BloodGPT
Status: planned (Phase 2). В Phase 1 — hash-based subdomain {hash}.portal.bloodgpt.tech (см. hash-based-subdomain).
Когда Phase 2 — клиент в B2B portal вводит patient.pzalab.com. Наш backend:
POST cf-api.com/zones/{zone_id}/custom_hostnames
{ "hostname": "patient.pzalab.com", "ssl": { "method": "txt", "type": "dv" } }
→ verification_token
Inngest scheduled function poll-ит verification status каждые 5 мин → UI обновляется (“Домен подключён”).
См. saas-tenant-routing для full integration flow.
Транформация Host header — критичный нюанс
CF прокидывает оригинальный Host (patient.pzalab.com) → GKE HTTPRoute не сматчит. Решение — CF Transform Rule переписывает Host:
When: (not http.host contains "bloodgpt")
Then:
Set dynamic header: X-Original-Host = http.host
Set static header: Host = portal.bloodgpt.tech
Одно правило на всех custom-domain tenants — не надо руками добавлять hostname в HTTPRoute (как сейчас для Африки). NextJS middleware читает X-Original-Host для tenant resolution.
Существующее использование (manual)
Для Африки уже использовалось вручную через CF Dashboard:
app.smartcarelabs.africa— activeapi.smartcarelabs.africa— broken (TXT validation timed out — забыли поставить TXT-запись)
Phase 2 = автоматизация через CF API + auto-poll, чтобы не зависеть от ручной координации.
Связано
- workos — auth flow для custom domains требует token-redirect (cross-domain cookie)
- saas-tenant-routing — full routing + auth integration
- hash-based-subdomain — Phase 1 default pattern (без CF Custom Hostnames)
- inngest — provisioning + verification poll functions
Источники
Сноски
-
CF for SaaS docs, accessed 2026-05-17, https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/. ↩
-
CF Transform Rules, accessed 2026-05-17, https://developers.cloudflare.com/rules/transform/. ↩
-
Сессия
ildar/871a7608, 2026-02-13 — design + Slack thread с Артёмом про CNAME routing для Африки. ↩