Запланировано как 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 — active
  • api.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

Источники

Источники: 1 2 3.

Сноски

  1. CF for SaaS docs, accessed 2026-05-17, https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/.

  2. CF Transform Rules, accessed 2026-05-17, https://developers.cloudflare.com/rules/transform/.

  3. Сессия ildar/871a7608, 2026-02-13 — design + Slack thread с Артёмом про CNAME routing для Африки.