CDN и доставка медиа
Хранилище медиа, использующее Telegram (MTProto) как бэкенд.
Dev-storyЗадача
Хотели где-то хранить и отдавать медиа продуктов, не платя за объектное хранилище или CDN под каждый проект.
Что делали
Бэкенд, загружающий файлы в Telegram по протоколу MTProto (используя его как бесплатное хранилище), и Vue-админка, чтобы организовать и раздавать медиа; раздача через кэширующий слой, чтобы файлы грузились быстро.
Результат
Медиа живёт на инфраструктуре Telegram без затрат на хранение, а приложения получают и ведут файлы через одну админку, а не платный bucket.
Dev-story статья
CDN и доставка медиа: как создавался проект
Telegram будет бесплатно держать неограниченное число файлов, но это не CDN: он тормозит через FLOOD_WAIT, не имеет модели публичной раздачи и ничего не знает про браузерный CORS или кеширование. Напряжение проекта — превратить чат-бэкенд в то, что реальный фронтенд может долбить 400+ запросами картинок на одну страницу, не поймав лимит на аккаунт и не показав файлы одного пользователя другому. Большая часть работы — это кромка перед MTProto, а не само хранилище.
Разделы
05
Модули
05
Стек
JavaScript + Vue
Почему появился проект
Хотели где-то хранить и отдавать медиа продуктов, не платя за объектное хранилище или CDN под каждый проект.
Telegram будет бесплатно держать неограниченное число файлов, но это не CDN: он тормозит через FLOOD_WAIT, не имеет модели публичной раздачи и ничего не знает про браузерный CORS или кеширование. Напряжение проекта — превратить чат-бэкенд в то, что реальный фронтенд может долбить 400+ запросами картинок на одну страницу, не поймав лимит на аккаунт и не показав файлы одного пользователя другому. Большая часть работы — это кромка перед MTProto, а не само хранилище.
Что было создано
Бэкенд, загружающий файлы в Telegram по протоколу MTProto (используя его как бесплатное хранилище), и Vue-админка, чтобы организовать и раздавать медиа; раздача через кэширующий слой, чтобы файлы грузились быстро.
Медиа-хранилище, где загрузки попадают в Saved Messages аккаунта Telegram, а каждый файл отдаётся обратно по публичному URL. Node-сервис на uWebSockets.js говорит по MTProto через gramjs, стримит байты файла и извлекает миниатюры; слой Nginx кеширует почти каждый ответ, так что Telegram дёргается редко; а панель на Vue управляет папками, поиском, перемещением, корзиной и API-ключами проектов. Работает на двух VPS-узлах за HAProxy.
Основные модули и путь пользователя
Адаптер хранилища MTProto (gramjs на uWebSockets.js), который загружает в Saved Messages, стримит байты файла обратно и пересылает сообщения между папками для перемещения и поиска — включая вручную пропатченный mime.getExtension, чтобы скачивания получали правильное расширение файла
Кеширующая кромка Nginx с ключом по Origin плюс заголовок Vary: Origin, после того как ответы <img> без CORS кешировались и потом ошибочно отдавались запросам fetch(), которым нужны CORS-заголовки
Аутентификация и защита от злоупотреблений: белый список номера телефона при отправке кода, 3 кода за 10 минут чтобы не вызвать Telegram FLOOD_WAIT на аккаунте, экспоненциальная задержка при неверных паролях и лимиты по IP, поднятые до 300 r/m с burst 100 для страниц, насыщенных картинками
Публичные эндпоинты миниатюр без аутентификации (/thumb, /vthumb), потому что <img src> не может отправить Bearer-токен — кадры видео вытягиваются через ffmpeg и кешируются как jpg
Конфигурация HAProxy на два узла со stick-table, привязывающей каждого клиента к одному backend, потому что токены панели живут в in-memory Map на каждом узле, тогда как публичная раздача файлов остаётся без состояния на обоих
Архитектура и технологические решения
Сделано на JavaScript, Vue, Edge delivery.
Node на uWebSockets.js, говорящий по MTProto через gramjs, перед которым Nginx для кеширования и заголовков безопасности и HAProxy для round-robin по двум узлам со sticky-сессиями; фронтенд на Vue с небольшим хранилищем папок на IndexedDB и самописным кешем запросов stale-while-revalidate вместо подключения TanStack Query.
Результат и выводы
Медиа живёт на инфраструктуре Telegram без затрат на хранение, а приложения получают и ведут файлы через одну админку, а не платный bucket.
Рабочий, self-hosted медиа-CDN на бесплатном хранилище Telegram, закалённый длинным хвостом реальных багов CORS, кеширования и аутентификации; честно — прототип на два узла, а не флот, но такой, что отдаёт библиотеку изображений масштаба приложения без счёта за хранилище.
Связанные статьи
Читать дальше
Связанные истории проектов
Эти проекты близки по техническим или продуктовым решениям и показывают, как тот же принцип работает в другом контексте.
Dev-storyCMS
Динамический headless-CMS на webedge-db — типы контента, медиа, роли и публичный read-API, питающий наши сайты и статьи.
Реактивная база данных
Реактивная база данных
Наш реактивный BaaS на native SpacetimeDB — ~200k realtime-доставок/с, p95<20мс.
Dev-storyMTP-RDMA инференс-кластер
Тензорный 27B на двух Mac по Thunderbolt RDMA — ~70 → 90–100 tok/s.
Есть похожая идея?
Обсудить проект