Skip to content

Operator API Quick Start ru

Nemu-x edited this page Jul 7, 2026 · 1 revision

Брендинг ClashFest — быстрый старт для оператора

🌐 English · Русский · 中文

Это для операторов панелей, которые хотят, чтобы их копия ClashFest выглядела как их сервис. Клиент читает HTTP-заголовки ответа с вашего URL подписки и подстраивается.

Если вы разработчик панели и хотите нативно вынести эти заголовки в свою админку — см. Справочник заголовков.

Что нужно

  1. По вашему URL подписки клиенты ходят GET <sub-url>.
  2. Ваша панель умеет добавлять кастомные HTTP-заголовки ответа. Любая современная Clash-панель это умеет — см. инструкции по панелям ниже.
  3. Публичный HTTPS-URL с вашим лого (PNG или WebP, рекомендуется 256×256, ≤200KB). Тема ClashFest по умолчанию тёмная, так что лого «под тёмный фон» достаточно; если хотите отдельное лого для светлой темы — разместите оба.

Минимальный жизнеспособный брендинг

⚠️ X-Branding-Enabled: true обязателен. Брендинг — opt-in на каждую подписку. Без этого мастер-переключателя все остальные X-Brand-* заголовки парсятся, но игнорируются, и приложение остаётся дефолтным. Это причина №1 «мой брендинг не показывается».

Мастер-переключатель плюс три идентити-заголовка дают заметный «брендированный» вид:

X-Branding-Enabled: true
X-Brand-Name: SwiftVPN
X-Brand-Logo-URL: https://cdn.example.com/swiftvpn-logo-dark.png
X-Brand-Accent-Color: #5E35B1

Чтобы откатить брендинг позже — уберите X-Branding-Enabled или поставьте false; клиент вернётся к дефолтному UI на следующем обновлении подписки.

Исключение: заголовки политики оператора, например X-Brand-Hide-Global-Mode, применяются по одному лишь наличию и не требуют X-Branding-Enabled. См. Справочник заголовков.

После этого заполните инфо оператора, чтобы экран About выглядел как настоящая визитка:

X-Brand-Website-URL: https://swiftvpn.example.com
X-Brand-Support-URL: https://t.me/swiftvpn_support
X-Brand-Telegram-URL: https://t.me/swiftvpn_news
X-Brand-Bot-URL: https://t.me/swiftvpn_bot
X-Brand-Privacy-URL: https://swiftvpn.example.com/privacy
X-Brand-Terms-URL: https://swiftvpn.example.com/terms
X-Brand-Help-URL: https://swiftvpn.example.com/help

Опционально — вариант лого для светлой темы:

X-Brand-Logo-Light-URL: https://cdn.example.com/swiftvpn-logo-light.png

Это всё для v1. v2 добавляет X-Brand-Status-URL, X-Brand-Renew-URL и статичный чип X-Brand-Max-Devices. v3 добавляет X-Brand-Hide-Routing для упрощённого UI юзера.

Настройка по панелям

Точные подписи UI меняются между версиями панелей. Принцип везде один: найти секцию «custom headers» для ответов подписки и вставить значения.

Pasarguard

  1. Админка → SettingsSubscription
  2. Прокрутите до Custom Headers (или Response Headers)
  3. Добавьте по одной записи на строку:
    X-Branding-Enabled: true
    X-Brand-Name: SwiftVPN
    X-Brand-Logo-URL: https://cdn.example.com/swiftvpn-logo-dark.png
    X-Brand-Accent-Color: #5E35B1
    X-Brand-Support-URL: https://t.me/swiftvpn_support
    
  4. Сохраните.
  5. Проверьте curl -I <subscription-url> — заголовки X-Brand-* должны быть в ответе.

Marzban

Marzban отдаёт заголовки подписки через host-level template-конфиг (/etc/marzban/.env или конфиг-файл вашей установки).

SUB_PROFILE_TITLE="vasya@example.com"
SUBSCRIPTION_PAGE_TEMPLATE="subscription/page.html"
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/"

Для произвольных X-Brand-* заголовков переопределите роутер подписки, расширив ответ через response.headers["X-Brand-Name"] = "SwiftVPN" в app/subscription/v2ray.py (или в том билдере ответа, что у вашей версии). Для большинства деплоеров проще поставить небольшой reverse-proxy (nginx / Caddy) впереди и добавить заголовки там — см. «Универсальный reverse proxy» ниже.

Marzneshin

В Marzneshin v0.5+ есть секция «Subscription branding» в админке под Settings → Branding. Вставьте заголовки прямо туда.

Для старых версий используйте reverse-proxy подход.

Remnawave

Админка → Hosts → выберите хост → Branding. Каждое поле маппится на один заголовок. Сохраните и перепроверьте curl -I.

3x-ui / X-UI

У 3x-ui есть панель «Subscription Settings». Ищите Response Headers в свежих сборках. Если в вашей версии нет — reverse-proxy подход.

Универсальный reverse proxy (работает с любой панелью)

Если панель не отдаёт кастомные заголовки — поставьте nginx (или Caddy) перед роутом подписки, пусть инжектит заголовки:

nginx:

location /sub/ {
    proxy_pass http://localhost:8080;

    add_header X-Branding-Enabled "true" always;
    add_header X-Brand-Name "SwiftVPN" always;
    add_header X-Brand-Logo-URL "https://cdn.example.com/swiftvpn-logo-dark.png" always;
    add_header X-Brand-Accent-Color "#5E35B1" always;
    add_header X-Brand-Website-URL "https://swiftvpn.example.com" always;
    add_header X-Brand-Support-URL "https://t.me/swiftvpn_support" always;
    add_header X-Brand-Telegram-URL "https://t.me/swiftvpn_news" always;
    add_header X-Brand-Privacy-URL "https://swiftvpn.example.com/privacy" always;
    add_header X-Brand-Terms-URL "https://swiftvpn.example.com/terms" always;
}

Флаг always важен — без него nginx пропускает заголовки на не-2xx ответах.

Caddy:

sub.swiftvpn.example.com {
    reverse_proxy localhost:8080

    header X-Branding-Enabled "true"
    header X-Brand-Name "SwiftVPN"
    header X-Brand-Logo-URL "https://cdn.example.com/swiftvpn-logo-dark.png"
    header X-Brand-Accent-Color "#5E35B1"
    header X-Brand-Website-URL "https://swiftvpn.example.com"
    header X-Brand-Support-URL "https://t.me/swiftvpn_support"
    header X-Brand-Telegram-URL "https://t.me/swiftvpn_news"
    header X-Brand-Privacy-URL "https://swiftvpn.example.com/privacy"
    header X-Brand-Terms-URL "https://swiftvpn.example.com/terms"
}

Проверка

После деплоя:

curl -I "https://your-domain.example/sub/<token>"

Вы должны увидеть свои X-Brand-* заголовки в ответе. Если нет — панель/прокси их не шлёт, проверьте конфиг.

Если заголовки есть, но приложение не реагирует — значения, скорее всего, не прошли валидацию. Частые проблемы:

  • URL лого http:// (нужен https://)
  • Файл лого слишком большой (>512KB) или неверного типа (не PNG / WebP / JPEG)
  • Акцент не ровно #RRGGBB (без #RGB, без rgba())
  • В имени бренда control-символы или >32 символов после trim

См. Безопасность для полных правил валидации.

Поведение сброса

Юзер может нажать Settings → Reset branding, чтобы убрать ваш брендинг и вернуться к дефолтной идентичности. Это не атака — это намеренный «аварийный выход», который приложение обязано предлагать (как «сброс к заводским»). Ваш брендинг вернётся на следующем фетче подписки, пока заголовки шлются.

Что брендинг НЕ меняет

By design, следующее остаётся дефолтом ClashFest независимо от брендинга:

  • Иконка лаунчера Android (юзер поставил «ClashFest» из стора — она и остаётся на домашнем экране)
  • Имя пакета Android и листинг в сторе
  • Строка «powered by ClashFest» на экране About
  • Settings → About → «App version» / идентификатор сборки

Если нужна полностью white-label презентация в сторе (своя иконка, свой листинг) — это другой скоуп: обсудите с нами полноценный форк / rebrand-сборку.

Clone this wiki locally