*Полностью открытый IP-KVM, который собирается из двух плат без единой капли припоя, прошивается прямо из браузера и умеет уже почти всё, что умеет “взрослый” KVM-over-IP. В этой статье - вся история проекта: от “сервер не грузится, а монитор на антресоли” до маленького круглого экранчика, который показывает IP прямо на корпусе.
С чего всё началось
А началось всё с того, что коллега - пусть будет Олег - забэкал на Kickstarter JetKVM. Маленький аккуратный IP-KVM, приехал, работает, красота. Я посмотрел на это как гик: с одной стороны - реально классная штука, хочу такую же. С другой - за плечами был кое-какой опыт с ESP, руки чесались, и вместо “просто купить” включилось родное “а могу ли я сам?”.
Напомню на всякий, что такое IP-KVM и зачем он вообще нужен. Это коробочка, которая видит HDMI-выход вашей машины, притворяется для неё USB-клавиатурой и мышью и отдаёт всё это в браузер. Вы садитесь за ноутбук/планшет/телефон(O_o) на другом конце квартиры (или города) и видите ровно то, что было бы на мониторе - вплоть до BIOS и меню загрузки. Никакого агента, никакой ОС на целевой машине не нужно: ей вообще всё равно, есть ли там операционка.
Сценарий, ради которого это всё, знаком любому, у кого дома живёт сервер. Стоит где-то за коробками гипервизор/NAS, и в один прекрасный момент не грузится: не пингуется, по SSH молчит, веб-морда мертва. То ли BIOS ушёл в настройки, то ли ядро запаниковало, то ли ждёт нажатия F1 после новой планки памяти. Чтобы узнать - надо тащить к железке монитор с клавиатурой. А с IP-KVM ты просто открываешь браузер.
Штука известная и, в общем, не новая: собрать KVM на ESP пытаются давно - на ESP8266, на ESP32-S3, кто во что горазд. Упирается всё в видеозахват: вытащить HDMI на копеечном микроконтроллере - задача нетривиальная.
И тут появляется ESP32-P4 - довольно свежий чип от Espressif с интерфейсом камеры (MIPI-CSI), кучей PSRAM и USB 2.0 HS. Раз есть вход для камеры - значит, к нему можно прицепить мост HDMI->CSI и получить видеозахват. За копейки.
Но дело было не только в “дешевле”. JetKVM - правда хороший продукт, придраться особо не к чему. Но именно поэтому стало интересно: а можно ли на ESP сделать не “ну, для микроконтроллера сойдёт”, а по-настоящему качественное решение - в первую очередь по софту? Хотелось довести веб-консоль до уровня, на котором её не стыдно поставить рядом с полированными коммерческими продуктами: чтобы UI был отзывчивым, аккуратным и приятным, а не “инженерным интерфейсом на минималках”.
Так, вместо того чтобы просто заказать себе JetKVM вслед за Олегом, я сел паять… то есть, забегая вперёд, - как раз ничего не паять. Так родился ESP-KVM.
Ссылки сразу, чтобы не искать:
Сайт с прошивалкой и живым демо: https://espkvm.io/
Исходники: https://github.com/espkvm/espkvm

Откуда взялся видеозахват
Оказалось, что к той же мысли - “а давайте на P4” - пришёл не только я. jrowny в проекте p4kvm уже проделал самую муторную часть: поднял мост Toshiba TC358743 и вытащил кадры из CSI-приёмника ESP32-P4.
Изобретать этот кусок заново смысла не было, поэтому “железный” низ я взял у него, а всё, что выше - веб-консоль, ввод, безопасность, виртуальные носители, питание, сеть, интерфейс - написал с нуля.
Из чего это собрать
Вся прелесть в том, что паять не нужно (кроме опционального ATX - там пара проводков в готовый модуль оптопар). Нужны две платы и шлейф:
Waveshare ESP32-P4-ETH (Но лучше сразу брать ESP32-P4 Function EV rev 3.2 или другую p4x) - мозг: ESP32-P4, 32 МБ PSRAM, 16 МБ флеша, 100-мегабитный Ethernet (для KVM за глаза), слот microSD и USB OTG. Плюс 40-пиновый разъём в стиле Raspberry Pi.
Geekworm C790 - мост HDMI->CSI на TC358743. Превращает HDMI-сигнал в поток, который понимает интерфейс камеры P4. Держит до 1080p и даже вытаскивает звук с HDMI по I2S (пока не задействовано).
Шлейф MIPI-CSI, которым эти две платы соединяются.
Плюс два USB-кабеля и HDMI. Итого - сумма, за которую готовый IP-KVM даже не улыбнётся в вашу сторону. Ладно, улыбнётся, NanoKVM. Но вы же здесь не за этим. Или за этим?
Важный нюанс с ревизией чипа. У меня плата с ESP32-P4 ревизии v1.3. От ревизии зависит очень многое, особенно скорость H.264: на свежих кремниевых ревизиях (v3.0+) встроен аппаратный конвертер цвета, и там картинка летает. На старых - нет, и это отдельная сага (см. ниже). Подробности - в HARDWARE-NOTES.
Прошивка за пять минут прямо из браузера
Вот тут я старался сделать по-человечески. Никаких idf.py flash, тулчейнов и танцев с бубном (хотя если хотите собрать сами - исходники открыты, всё описано).
Заходите на https://espkvm.io/ из браузера на движке Chromium (Chrome, Edge - им нужен Web Serial).
Втыкаете ESP32-P4-ETH в USB.
Жмёте кнопку прошивки, выбираете COM-порт - прошивальщик сам зальёт последнюю сборку.
Причём сборка берётся прямо из релизов на GitHub, собранных в CI. То есть вы прошиваете ровно тот бинарник, который публичный и воспроизводимый, а не “доверься мне, братан”.
Дальше - физика: шлейф между платами, HDMI с целевой машины в C790, USB от неё в OTG-порт P4 (по нему устройство притворится клавиатурой и мышью), Ethernet в сеть, питание. Через несколько секунд устройство поднимется под именем espkvm.local. При первом входе логин admin/admin, и консоль сразу заставит задать нормальный пароль - причём на уровне прошивки, а не только в интерфейсе (пока дефолтный пароль в силе, сессия дотягивается только до auth-эндпоинтов, устройство нельзя рулить по проводу).

Что оно умеет сегодня
Чтобы не растекаться - честный список того, что работает уже сейчас, без “скоро завезём”:
Видео с автоопределением режима. Меняется разрешение на целевой машине - картинка подстраивается сама. Видно и BIOS в 640x480, и загрузчик, и рабочий стол в 1080p. Уснула машина, выдернули HDMI, сменилось разрешение при загрузке - поток восстанавливается сам.
Два кодека: MJPEG (простой, ~20 fps) и аппаратный H.264 (экономный по трафику).
Точная мышь. Абсолютное позиционирование - курсор попадает ровно туда, куда кликнули, без “уплывания” из-за акселерации на целевой стороне. Есть и относительный режим для игр/pointer-lock.
Полноценная клавиатура, медиа-клавиши,
Ctrl+Alt+Delи другие макросы одной кнопкой, вставка текста с учётом раскладки.Работа с телефона. Нормальный мобильный интерфейс с тач-трекпадом и экранной клавиатурой, а не сломанная десктопная вёрстка. Ставится как PWA на домашний экран. Но там нужно добавить CA сертификат в браузер. Потому как сертификат самоподписанный. (Можно скачать в интерфейсе)
Несколько зрителей одновременно, управляет один - с “перехватом управления”.
Виртуальный привод. Грузите целевую машину с ISO/IMG на microSD или с маленького “спасательного” образа во встроенной флешке.
.isoотдаётся как CD-ROM, всё остальное - как флешка. На rev-3.x картой можно отдать целиком, на чтение-запись. Но со скоростью записи и чтения SD карты есть проблемы. К сожалению скорость минимальная. :(Управление питанием (ATX). Кнопки Power/Reset материнки через оптопары + чтение индикатора питания. И Wake-on-LAN в придачу.
Определение ОС целевой машины по тому, как она опрашивает USB-дескрипторы.
HTTPS с самоподписанным сертификатом (или своим), логин с PBKDF2, физический сброс пароля кнопкой, обновление прошивки по сети с откатом, тепловая защита, диагностика.
Home Assistant через MQTT - авто-обнаружение сенсоров и кнопок питания.
VPN: WireGuard или нативный Tailscale (об этом ниже - там тоже интересно).
Чего пока нет: звука с HDMI - мост его отдаёт, но для KVM это низкий приоритет (подробнее в конце).

А теперь про грабли
Расскажу обо что именно я споткнулся.
H.264 упёрся не туда, куда я думал
Логика подсказывала: аппаратный кодер H.264 -> мало трафика -> много кадров. На практике на моей ревизии чипа (v1.3) в блоке H.264 нет конвертера цвета, и кадр приходится гонять через отдельный аппаратный преобразователь RGB->YUV (PPA). А он упирается в пропускную способность PSRAM: конвертер таскает ~9 МБ на кадр, и когда он работает параллельно с энкодером, они дерутся за шину памяти.
Итог: 1080p по H.264 на старом кремнии выдаёт около 7 fps - довольно печально. Я даже развёл конвертацию и энкод на две задачи через два YUV-буфера в надежде распараллелить - прирост оказался копеечным (~6.7 -> ~7.3 fps), потому что бутылочное горлышко не в вычислениях, а именно в памяти. Поэтому MJPEG со своими ~20 fps остался основным вариантом, а H.264 - для узких каналов.
На rev 3.0+ эта проблема снимается встроенным конвертером - и там H.264 уже 22 fps. Но это уже другая плата, и до неё мы ещё дойдём.
microSD на этой плате - отдельная сага
На дефолтных 20 МГц карта нормально читает одиночные секторы: смонтировалась, показала каталог - вроде живая. Но валит любое многоблочное чтение - а именно так её читает USB-хост. То есть целевая машина образ прочитать не могла в принципе, при внешне рабочей карте.
Помогло только опускание шины до 4 МГц (медленно, ~1.5 МБ/с, зато читается 200 МБ без единой ошибки) и отказ от UHS/DDR-режимов. Запись на старом кремнии так и осталась ненадёжной, поэтому там карта только на чтение, а образы готовятся во внешнем картридере. На rev 3.x запись работает штатно - проверено на железе. Это известное ограничение ESP32-P4, а не мой косяк (я себя в этом убедил).
Кнопка сброса пароля чуть не убила сеть
Физический сброс пароля я повесил на кнопку BOOT (GPIO 35). Оказалось, этот пин делит функцию с Ethernet, и стоит захватить его после подъёма сети - сеть умирает намертво: устройство живёт, логи идут, но не отвечает даже на ARP. Пришлось читать кнопку ровно один раз, в узком окне сразу после старта, до инициализации Ethernet, и тут же отдавать пин обратно. Нашёл, как водится, не с первого раза.
Два устройства с дефолтным именем ссорились сертификатами
Устройство при первом старте само становится маленьким удостоверяющим центром, выписывает себе сертификат и подписывает его. Красиво - пока у вас не появилось два устройства с дефолтным хостнеймом espkvm: их самоподписанные CA получали одинаковое имя (CN), и, доверившись одному, браузер отвергал другой с ERR_CERT_AUTHORITY_INVALID. Лечится добавлением в имя CA суффикса из MAC-адреса и авто-перевыпуском.
Бонус: WebSocket, которого не было
Один из самых обидных. В какой-то версии в браузере вдруг отвалились H.264, клавиатура и мышь - при том, что все REST-роуты работали. Оказалось, таблица обработчиков HTTP-сервера была ровно на единицу меньше нужного: эндпоинты ATX её переполнили, а /video и /ws регистрировались последними - их-то молча и выкидывало. Поднял лимит с запасом.
Как проект оброс сетью: WiFi, Tailscale и WireGuard
KVM без нормального удалённого доступа - не KVM вовсе. Поэтому дальше история пошла в сторону сети.
WiFi. У ESP32-P4 нет своего радио. Но на плате ESP32-P4 Function EV рядом стоит ESP32-C6, и P4 общается с WiFi через него по SDIO. Появился выбор линка - Ethernet / WiFi / собственная точка доступа, - со сменой на лету из статус-бара. Плюс спасательный хотспот: если устройство не достучалось до своей сети, оно поднимает свою ESP-KVM-xxxx, а само продолжает ломиться в сеть и переподключается, как только та вернётся. И captive-портал - подключился телефоном к точке, консоль открылась сама, как в отеле.
Tailscale, нативно. Хотелось дотягиваться до устройства из любой точки без проброса портов и VPS. Классический вариант - WireGuard-клиент (split-tunnel, ключ генерится на устройстве, только свой туннельный адрес идёт через VPN). Но я пошёл дальше и прикрутил нативный Tailscale: устройство само вступает в tailnet, получает 100.x-адрес (или MagicDNS-имя), доступный откуда угодно, а обход NAT (через DERP/DISCO) берёт на себя. Под капотом - нативный ts2021-клиент (microlink), портированный на ESP-IDF 6. Сертификат консоли при этом перевыпускается так, чтобы быть валидным и по адресу в tailnet. Работает и с self-hosted control-сервером (Headscale/Ionscale).
Оба VPN-бэкенда живут на одном WireGuard-стеке и выбираются в рантайме - это отдельно пришлось разруливать, чтобы символы двух реализаций не конфликтовали в одной прошивке.
Вторая итерация железа: приехала новая плата
“Бутерброд из двух плат на проводах” просился в нормальный форм-фактор, а старый кремний v1.3 держал H.264 за горло. Поэтому я очень ждал плату ESP32-P4 Function EV ревизии 3.2 - со свежим кремнием, где H.264 наконец должен полететь.
Она приехала.

И новый камушек подтвердил ожидания. На rev 3.x картинка захватывается сразу в YUV422 прямо в оба энкодера, минуя проход цветоконвертации: это освободило ~4 МБ PSRAM и поставило H.264 и JPEG на один формат. Плюс третий буфер захвата, чтобы энкодер не ждал камеру. Результат: 1080p по H.264 поднялся с ~15 до ~22 fps, а на 720p - под 28-34. H.264, который на старой плате еле полз, здесь наконец стал юзабельным. Причём старый путь для rev <3.0 я аккуратно не трогал - обе платы продолжают работать.

Заодно у P4 Function EV есть ESP32-C6, ради которого и появился весь WiFi-функционал. Короче нормальный получился апгрейд. Не понятно только почему Espressif выпускает эту плату ка P4 хотя камушек при этом знатно переработан.
Маленький экранчик (IYKWIM)
Мне прилетел вполне резонный feature-request: когда устройство работает как “безголовая” коробочка где-то рядом с сервером, найти его IP - это лезть в DHCP-таблицу роутера, а проверить, что HDMI-сигнал ловится, - открывать веб-консоль. А хочется просто посмотреть на саму железку и всё понять.
Самое прекрасное в этом запросе было то что именно в этот момент я уже был на завершающем этапе добавления поддержки этих oled экранов.
Так в v0.21.0 появился маленький статус-дисплей. Втыкаете в пины крошечный OLED (SSD1306 или SH1106 - они авто-детектятся на той же I2C-шине, что и мост захвата), включаете в настройках - и устройство показывает прямо на панели свой IP, состояние линка, статус захвата и здоровье: циклом страницы с иконками и прогрессбарами температуры/RAM. Работает мимо энкодера, так что на стриминг не влияет. (Уже не влияет :) )

А потом я не удержался и добавил поддержку круглого цветного LCD GC9A01 - того самого “часового” кругляша. Он не только красивее, но и показывает больше: тот же статус плюс, например, адрес в Tailscale.

Оба варианта включаются одной галкой, а пины назначаются прямо из консоли: в этом же релизе настройки пинов стали выпадающими списками свободных GPIO, появилась вкладка Pins с полной картой (что зарезервировала плата, что вы назначили, что свободно), и ATX-пины тоже переехали на эту карту - чтобы ничего молча не столкнулось.
Как круглый GC9A01 выглядит вживую - на видео (без звука, просто короткая демонстрация):
https://www.youtube.com/watch?v=-snDjOOjbSA
Немного о безопасности
KVM - это полный доступ к машине, поэтому выпускать его в сеть “как есть” нельзя. Что сделано:
HTTPS с самовыпущенным CA (импортируете корневой один раз - браузер перестаёт ругаться, а заодно включается H.264, которому WebCodecs требует “защищённого контекста”). Можно и свой сертификат подсунуть.
Логин с PBKDF2-хешем пароля, ограничение перебора и обязательная смена дефолтного пароля - на уровне прошивки.
Физический сброс пароля кнопкой - логика простая: кто может дотянуться до кнопки, тот и так может выдернуть питание.
Весь интерфейс самодостаточный: никаких внешних CDN, шрифтов и запросов наружу. Устройство обязано работать в изолированной сети.
Не выставляйте это в публичный интернет. Логин и TLS есть, но security-review проект не проходил, а железка, держащая клавиатуру на чужой машине, стоит для атакующего дороже почти всего остального в сети. Держите её в доверенной сети или дотягивайтесь через VPN/Tailscale.
Что дальше и как поучаствовать
Из очевидного, чего пока нет, - звук с HDMI. Руки до него не доходят, для KVM звук - штука не то чтобы сильно важная (ну правда, часто вам нужно слышать зависший BIOS?), а вокруг хватает задач куда интереснее. Так что лежит и ждёт настроения. Полный roadmap - в репозитории.
С корпусом, кстати, тоже пока не очень. Я начал было рисовать его под Waveshare-“бутерброд” - а тут приехала плата совсем другого форм-фактора, и весь чертёж отправился в стол. Так что корпус пока отложен: смысла вылизывать коробку под железо, которое на глазах меняется, немного. Сначала - определиться с “эталонной” платой, потом уже одевать её.
Проект живой и открытый (Apache-2.0). Если хочется:
потрогать - прошивалка и интерактивное демо на https://espkvm.io/;
покопаться в коде - https://github.com/espkvm/espkvm, там же Issues и Discussions;
портировать на свою плату - есть PORTING.md, поддержка разных плат в проект уже заложена.
И напоследок - ради чего всё затевалось. Представьте: дома или на даче стоит машина, к которой в норме никто не подходит - NAS, медиасервер, ретро-ПК. Что-то пошло не так - а вы с телефона из метро заходите, видите зависший BIOS, жмёте пару клавиш, при необходимости монтируете загрузочный образ и переставляете систему. Или чините компьютер родителям в другом городе, не объясняя им по телефону, “какую кнопочку нажать”. Вот ради этих сценариев оно и делалось.
Спасибо, что дочитали. И если проект окажется полезным - скиньте ссылку на статью/проект другу-гику и звёздочку в репе поставьте если не жалко :)
Комментарии (57)

IDDQDesnik
12.08.2026 09:30Есть готовый набор? Что бы и корпус и все что надо в комплекте? Желательно в России.

Dexif Автор
12.08.2026 09:30К сожалению не в моих силах. Платы легко заказываются на али. А с корпусом как и писал пока напряг потому что сам не определился ещё окончательно с вариантом платы.

not-allowed-here
12.08.2026 09:30нарисуйте да торгуйте DIY китами.... идея в целом классная надо попробовать самому такое собрать

Dexif Автор
12.08.2026 09:30Ну это вопрос готовности заниматься таким. Мне когда-то в начале карьеры хватило фриланса чтобы понять что я не хочу разруливать что-либо с заказчиками. Потому что я не продажник и мне сложно продавать себя. Мало того вряд-ли это будет выгодно. А геморроя явно дофига. Любой китайский производитель с лёгкостью перебьёт моё предложение. На самом деле на это у меня и был расчёт. Что какой-нить lilygo или waveshare решит что норм тема выпустить платку а возможно даже сразу в корпусе с учётом что софт уже существует. Я бы и сам купил такое :)

withkittens
12.08.2026 09:30Неужели вы сами так плохо пишете, что нельзя было не прогонять статью через LLM? Такая здоровенная бочка мёда, и не забыли добавить ложку дёгдя. Эх.

Dexif Автор
12.08.2026 09:30Конечно можно было бы и не прогонять. ;)
Вопрос лишь в том что граммар нацци потом взбунтовались бы...
Некоторые вещи были в статье перегруппированы благодаря модельке чтобы читалось более плавно и легко.
Если вам важно прогнать детектор аяя, а не узнать о проекте - штош.
Моя идея донести информацию, а не париться, что кто-то найдёт в статье следы аяя. :)
Не нравится проект - тоже не беда. Каждому своё.

withkittens
12.08.2026 09:30Ни разу не пользовался детекторами LLM. И здесь он был не нужен. Текст настолько набит честными ИИ-змами и рандомными выделениями жирным, что всё очевидно любому, кто читает больше двух статей в месяц. И вот, к сожалению, в погоне за более плавным и лёгким вы пришли к прямо противоположному :с
Void-Cowboy
ах, старый добрый хабр все еще прорывается в ленту)
вот это я понимаю опенсорс, а не навайбкодженые за неделю сайтики, чей исходный код "коммерческая тайна"
успехов вам в вашем начинании, очень круто! Вечером еще код гляну предметно, может отпишусь в ишью.
Dexif Автор
Спасибо. Очень надеюсь, что проект обрастает сообществом которое поможет развивать его.
sashz
https://github.com/espkvm/espkvm/blob/main/AGENTS.md
Guidance for AI coding agents (and new contributors) working in this repo. Keep it accurate; update it when the build, layout, or conventions change.
ЗЫ Ничего против ИИ не имею.
Dexif Автор
Да это если будут кодить агентами чтобы агентам было проще рулить проектом. Время такое. Сейчас в опенсурсе сложно потому что если проект популярный - туда начинают пуллреквестить все кто может. И желательно если это хоть как-то будет контролироваться. Вам это и какой-нибудь Линус Торвальдс сейчас скажет :) https://3dnews.ru/1146632/ii-uskoril-razrabotku-linux-i-dobavil-raboti-linusu-torvaldsu У него сейчас работы прибавилось знатно... ;)