ThingsBoard
IoT-платформа на вашем сервере: история показаний датчиков, тревоги и кабинет заказчика без разработки бэкенда с нуля. Развернули CE v4.2.2.7 на Fatmetal Cloud Server, замерили ресурсы, проверили телеметрию и доступ заказчика.
Вердикт
- интегратору: датчики уже передают данные, заказчик просит историю и тревоги
- оператору нескольких объектов: каждому клиенту нужен отдельный кабинет
- разработчику, который хочет собрать IoT-приложение вокруг готовой модели устройств
- для одного графика: отдельная IoT-платформа усложнит обслуживание
- для замены брокера без изменения произвольных MQTT-топиков
- если заказчику нужен готовый русский интерфейс
Что это и какую задачу решает
ThingsBoard принимает показания устройств, хранит историю, проверяет условия тревог и показывает результат пользователю. Устройство, профиль, заказчик и панель уже связаны между собой: эту часть приложения не приходится писать заново.
Пример - два склада с датчиками температуры. Оператор видит оба, владелец склада A получает доступ только к своему объекту. При перегреве появляется тревога, которую сотрудник подтверждает в интерфейсе.
В проверенной Community Edition этот сценарий работает без коммерческого ключа.
Яндекс IoT Core закрывается 1 декабря 2026 года. В инструкции Яндекса ThingsBoard предложен для сценариев с панелями и правилами. Устройства потребуется адаптировать; готовый перенос из Яндекса в этом разборе не проверен.
Виртуальные датчики передали значения по HTTP и MQTT, а история и подтвержденная тревога сохранились после остановки и запуска стека.
Что изменилось с прошлого разбора
Сентябрьская статья проверялась на v4.2.1.1: приложение и PostgreSQL находились в tb-postgres, очередь работала в памяти. Для v4.2.2.7 нужен другой состав установки.
| Было: v4.2.1.1 | Стало: v4.2.2.7 |
|---|---|
| thingsboard/tb-postgres | thingsboard/tb-node и отдельная PostgreSQL |
| PostgreSQL внутри образа приложения | База в собственном контейнере и томе |
В ветке 4.2.2 обновлен Angular, исправлены XSS, обход защиты от внутренних сетевых запросов и проблемы песочницы TBEL. Патч v4.2.2.7 обновляет часовые пояса Java/UI и Node.js.
Для старой установки существенен CVE-2026-22610: исправление вошло еще в v4.2.1.2. Лицензия выбранного тега остается Apache-2.0; в этом разборе используется именно CE v4.2.2.7.
Чем отличается от платных аналогов
Облако берет на себя обслуживание. Своя CE дает готовую модель устройств, но базу, очередь и копии обслуживает ваша команда. Сравнивать только цену сообщений с ценой платформы некорректно.
| Продукт | Цена на 24.10.2026 | Что покупаете |
|---|---|---|
| ThingsBoard CE | Лицензия 0; сервер от 1100 руб/мес | Свое приложение и данные; работа администратора отдельно |
| ThingsBoard Cloud Prototype | 49 $/мес, 50 устройств | Платформа у вендора |
| Ubidots Professional | 99 $/мес, 50 устройств | 10 млн точек/мес, хранение 6 месяцев |
| AWS IoT Core | В Ireland 1 $/млн сообщений | Транспорт; хранение и кабинет оплачиваются отдельно |
Источники: ThingsBoard Cloud, Ubidots, AWS. Цена сервера относится к CPU4-RAM8-DISK100; резервирование и труд администратора в нее не включены.
Для нового клиента из РФ AWS закрыт: Amazon остановил регистрации. Cloud ThingsBoard списывает оплату через Stripe; Stripe не поддерживает «Мир». Ubidots предлагает карту, перевод и PO.
Если нужен только прием MQTT, достаточно Mosquitto. Если уже есть база и требуется график, сравните с Grafana. ThingsBoard полезнее там, где устройства и доступ заказчика должны работать вместе.
Как устроен стек
Java 17 и Spring Boot обрабатывают устройства и правила, Angular рисует интерфейс. PostgreSQL хранит учетные записи, настройки и телеметрию; Kafka удерживает очередь событий на диске.
В установке четыре контейнера: ThingsBoard, PostgreSQL 16.15, Kafka 4.0.2 и Caddy 2.11.7. Caddy принимает HTTPS, приложение слушает localhost. Один брокер Kafka сохраняет очередь между перезапусками, но все компоненты находятся на одной машине.
MQTT API использует собственный токен каждого устройства и топик v1/devices/me/telemetry. HTTP API принимает тот же JSON. Токен устройства дает право отправлять его показания; пароль администратора для датчиков не используется.
Какой сервер выбрать
Для проверенного профиля рекомендуем CPU4-RAM8-DISK100: четыре ядра нужны при обработке пакетов, память оставляет запас JVM и системе. Пик в опыте достигал 3,6 ядра; средний простой потреблял 0,8 ядра.
Весь установленный сервер занимал 5,7 ГиБ диска. Суточная история 20 виртуальных датчиков с тремя показателями и минутным шагом добавила 13 МиБ PostgreSQL. На старте отдельное хранилище под такой объем не требуется.
В состав роста входят и новые устройства. Планируя срок хранения, считайте свои показатели и частоту: батарея раз в час и температура раз в секунду дают разный объем истории.
В маркетплейсе Fatmetal
Не хотите ставить руками?
Этот стек есть в маркетплейсе Fatmetal - можно не повторять установку из этого разбора вручную. Заказываете сервер, за пару минут получаете рабочий домен, валидный TLS и файл с доступами.
Рекомендуемая конфигурация:
4 vCPU · 8 ГБ RAM · 100 ГБ NVMe от 990 ₽/мес
Развертывание на Fatmetal Cloud Server
Нужны чистая Ubuntu 24.04 и знание Compose. Установка занимает около десяти минут плюс создание пользователей; база будет пустой.
На своем компьютере откройте SSH с туннелем для первого входа. Логин возьмите из панели; ваш-домен замените адресом X-Y-Z-W.fatmetal.net с IP сервера или собственным доменом с A-записью:
ssh -L 8080:127.0.0.1:8080 логин@ваш-доменУстановите Docker
В SSH выполните
sudo -i: команды идут от root.apt-get update && apt-get install -y docker.io docker-compose-v2 openssl curlЗадайте домен и секреты
Используйте выбранный адрес в APP_DOMAIN. Откройте входящие 80/443.
mkdir -p /opt/thingsboard && cd /opt/thingsboard umask 077 printf 'POSTGRES_PASSWORD=%s\nJWT_TOKEN_SIGNING_KEY=%s\nKAFKA_CLUSTER_ID=%s\nAPP_DOMAIN=ваш-домен\n' "$(openssl rand -hex 32)" "$(openssl rand -base64 64 | tr -d '\n')" "$(openssl rand -base64 16 | tr '+/' '-_' | tr -d '=\n')" > .envПодготовьте Kafka
Загрузите конфигурацию Apache Kafka 4.0.2. Три правки задают адрес брокера, каталог данных и суточное хранение очереди.
curl -fsSL https://raw.githubusercontent.com/apache/kafka/4.0.2/docker/server.properties -o kafka.properties sed -i 's|PLAINTEXT://localhost:9092|PLAINTEXT://kafka:9092|;s|/tmp/kraft-combined-logs|/var/lib/kafka/data|;s|log.retention.hours=168|log.retention.hours=24|' kafka.properties chmod 644 kafka.propertiesСохраните compose.yaml
Создайте файл в /opt/thingsboard. Приложение доступно через SSH; очередь и база снаружи закрыты.
cat > compose.yaml <<'COMPOSE' services: postgres: image: postgres:16.15-bookworm restart: unless-stopped environment: {POSTGRES_DB: thingsboard, POSTGRES_USER: thingsboard, POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"} volumes: ["postgres_data:/var/lib/postgresql/data"] kafka: image: apache/kafka:4.0.2 restart: unless-stopped environment: {CLUSTER_ID: "${KAFKA_CLUSTER_ID}", KAFKA_HEAP_OPTS: "-Xms256m -Xmx512m"} volumes: ["./kafka.properties:/mnt/shared/config/server.properties:ro", "kafka_data:/var/lib/kafka/data"] thingsboard: image: thingsboard/tb-node:4.2.2.7 restart: unless-stopped environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/thingsboard SPRING_DATASOURCE_USERNAME: thingsboard SPRING_DATASOURCE_PASSWORD: "${POSTGRES_PASSWORD}" JWT_TOKEN_SIGNING_KEY: "${JWT_TOKEN_SIGNING_KEY}" TB_QUEUE_TYPE: kafka TB_KAFKA_SERVERS: kafka:9092 JAVA_OPTS: '-Xms512m -Xmx2560m -Dhttp.proxyHost=api-proxy.fatmetal.net -Dhttp.proxyPort=8080 -Dhttps.proxyHost=api-proxy.fatmetal.net -Dhttps.proxyPort=8080 -Dhttp.nonProxyHosts=localhost|127.*|10.*|172.16.*|postgres|kafka|thingsboard' HTTP_PROXY: http://api-proxy.fatmetal.net:8080 HTTPS_PROXY: http://api-proxy.fatmetal.net:8080 NO_PROXY: localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,postgres,kafka,thingsboard SSRF_PROTECTION_ENABLED: 'true' ports: ["127.0.0.1:8080:8080", "127.0.0.1:1883:1883"] caddy: image: caddy:2.11.7 profiles: [public] restart: unless-stopped command: [caddy, reverse-proxy, --from, "${APP_DOMAIN}", --to, "thingsboard:8080"] ports: ["80:80", "443:443"] volumes: ["caddy_data:/data"] volumes: {postgres_data: {}, kafka_data: {}, caddy_data: {}} COMPOSEЗапустите базу и очередь
В журнале PostgreSQL дождитесь ready to accept connections, у Kafka - Kafka Server started. Оба сообщения нужны до установки схемы.
docker compose up -d postgres kafka docker compose logs --tail=30 postgres kafkaСоздайте схему и запустите приложение
Установщик схемы выполните один раз, без demo-аккаунтов. После запуска подождите минуту: проверка должна вернуть HTTP 200; при 000 смотрите журнал.
docker compose run --rm -e INSTALL_TB=true -e LOAD_DEMO=false thingsboard docker compose up -d thingsboard curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/loginСмените пароль до открытия сайта
В открытом туннеле на своем компьютере перейдите на http://localhost:8080, войдите как sysadmin@thingsboard.org с паролем sysadmin. В меню профиля выберите Security и задайте пароль сервера из панели.
Создайте владельца устройств
Откройте Tenants → +, создайте организацию. В ее строке откройте Manage tenant admins → +. Укажите tenant@thingsboard.org, выберите Display activation link. Откройте ссылку в приватном окне и задайте тот же пароль сервера. Demo-аккаунтов здесь нет.
Включите HTTPS
Теперь откройте сайт снаружи. Caddy выпускает сертификат автоматически; проверьте вход обоими новыми паролями. В /settings/general задайте Base URL = https://ваш-домен.
docker compose --profile public up -d caddy curl -I https://ваш-домен/login
От показания до кабинета заказчика
Войдите tenant@thingsboard.org. Откройте Entities → Devices → + → Add new device и создайте warehouse-a-01. В карточке выберите Manage credentials и скопируйте Access token; отправьте показание:
read -r -p 'Access token устройства: ' DEVICE_TOKEN
curl --fail -X POST "https://ваш-домен/api/v1/$DEVICE_TOKEN/telemetry" \
-H 'Content-Type: application/json' -d '{"temperature":33.7,"humidity":49,"battery":87}'Откройте Latest telemetry: должны появиться три ключа. В Device profiles → default → Alarm rules задайте temperature > 30, severity Critical; очистку - temperature < 28. Повторите отправку: в Alarms появится тревога.
Создайте Dashboard, добавьте виджет Time series chart, источник Entity - warehouse-a-01, ключ temperature. Для текущего значения используйте Value card. История и карточка читают одно устройство.
В Customers создайте Warehouse A. Назначьте ему устройство и панель через Assign to customer; через Manage customer users создайте пользователя. Откройте его активационную ссылку в отдельном окне и войдите.
В проверке клиент видел свой склад A; запрос к чужому устройству возвращал 403. Общую операторскую панель ему не назначали: разделение доступа строится на назначении объектов заказчику.
Что показали замеры
Стенд CPU4-RAM8-DISK100: Ubuntu 24.04.4, ThingsBoard CE v4.2.2.7, отдельные PostgreSQL и Kafka. Память ниже - рабочая память контейнеров без файлового кеша.
| Стек в простое | 2,3 ГиБ |
| Из них приложение / Kafka | 1,8 ГиБ / 547 МиБ |
| Образ ThingsBoard | 2,1 ГиБ |
| Холодное скачивание четырех образов | 2 мин 40 с |
| Создание схемы / запуск приложения | 2 мин 25 с / 1 мин 14 с |
| От чистой ОС до настройки и запуска прокси | 9 минут, без выпуска сертификата |
| Ответ /login снаружи | 0,11 с |
| Получение последних показаний | 0,09 с |
Для опыта с историей отправили 28 800 записей - 86 400 значений. Память выросла на 45 МиБ; SQL и интерфейс подтвердили сохраненные точки. После перезапуска данные, доступ клиента и тревога остались на месте.
При таком объеме первым практическим вопросом становится срок хранения. Проверяйте рост базы командой:
docker compose exec -T postgres psql -U thingsboard -c "SELECT pg_size_pretty(pg_database_size('thingsboard'));"
Проверено на версии v4.2.2.7, 24 октября 2026. На новых версиях результаты могут отличаться.
Где может сломаться
Причина. Номер свежего релиза приложения не гарантирует наличие старого объединенного образа.
Решение. Используйте thingsboard/tb-node:4.2.2.7 с отдельной PostgreSQL, как в compose выше. Проверьте образ: docker compose images.
Причина. Команда up уже завершилась, но Java-приложение еще запускается.
Решение. Дождитесь Started ThingsboardServerApplication в журнале и повторите curl. Установщик схемы запускается один раз.
docker compose logs --tail=100 thingsboardПричина. Переиспользованный адрес сервера исчерпал недельный лимит Let's Encrypt на это имя. Само приложение продолжает работать через SSH-туннель.
Решение. Найдите retry after в журнале:
docker compose logs --tail=100 caddyДождитесь срока либо задайте другое имя в APP_DOMAIN. Пересоздайте прокси:
docker compose --profile public up -d --force-recreate caddyДля временной проверки подойдет имя вида метка.ваш-IP.sslip.io: сервис DNS возвращает указанный в имени IP. Замените ваш-IP внешним адресом сервера и выберите свою метку.
Причина. В tb-postgres:4.2.1.1 база принадлежит thingsboard. Команда с -U postgres из прежнего разбора на этом образе не работает.
Решение. Выгрузите копию с правильной ролью:
docker exec thingsboard pg_dump -U thingsboard -d thingsboard -Fc > legacy.dumpБезопасность, резервная копия и восстановление
Держите .env с правами 600 и сохраняйте его отдельно от дампа. Он содержит пароль базы и ключ подписи входа; данные устройств, панели и учетные записи находятся в PostgreSQL.
Перед копией остановите прием новых показаний и дождитесь обработки отправленного. Команды выполняются из /opt/thingsboard; установите закрытые права и выгрузите базу:
umask 077
docker compose exec -T postgres pg_dump -U thingsboard -d thingsboard -Fc > thingsboard.dump
tar czf thingsboard-config.tgz .env compose.yaml kafka.propertiesЧтобы восстановить эту копию на той же версии, остановите приложение, завершите подключения и восстановите базу. Следующие команды полностью заменяют текущую базу копией; сначала проверьте список объектов дампа:
tar xzf thingsboard-config.tgz
docker compose stop thingsboard
docker compose exec -T postgres psql -U thingsboard -d postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='thingsboard' AND pid != pg_backend_pid();"
docker compose exec -T postgres pg_restore --list < thingsboard.dump > restore-list.txt
docker compose exec -T postgres dropdb -U thingsboard thingsboard
docker compose exec -T postgres createdb -U thingsboard thingsboard
docker compose exec -T postgres pg_restore --exit-on-error -U thingsboard -d thingsboard < thingsboard.dump
docker compose up -d thingsboardАрхив конфигурации храните вместе с указанием версии; копию выгружайте за пределы VM. После восстановления войдите, проверьте последнее показание и список тревог.
Для пересоздания контейнера закрепленной версии выполните:
docker compose pull thingsboard && docker compose up -d --no-deps thingsboardТег сам не меняется; проверенный переход со старого образа описан ниже.
Как перенести базу из tb-postgres
Для существующей v4.2.1.1 используйте новую машину и пустую PostgreSQL. Выполните шаги 1-5 установки выше; INSTALL_TB=true не запускайте: схему принесет дамп старой базы.
Остановите отправку показаний. На старом сервере, под обычным SSH-пользователем, выгрузите данные и остановите приложение. Логин и ваш-домен в scp замените доступом нового сервера:
umask 077
sudo docker exec thingsboard pg_dump -U thingsboard -d thingsboard -Fc > legacy.dump
sudo docker stop thingsboard
scp legacy.dump логин@ваш-домен:~/legacy.dumpНа новом сервере от root перейдите в каталог установки, скопируйте дамп из домашнего каталога SSH-пользователя и запустите приложение:
cd /opt/thingsboard
cp /home/логин/legacy.dump .
docker compose up -d postgres kafka
docker compose exec -T postgres pg_restore -U thingsboard -d thingsboard --no-owner < legacy.dump
docker compose up -d thingsboardВместо создания пользователей в шаге 8 проверьте старые учетки через туннель. Если сохранились демонстрационные tenant@ и customer@, смените им пароли или удалите ненужные аккаунты до открытия HTTPS.
Причина. UPGRADE_TB=true запускает установщик мажорного обновления.
Решение. Для перехода v4.2.1.1 → v4.2.2.7 нужен обычный запуск выше: приложение само применяет миграции LTS. В журнале дождитесь System data patch update completed successfully.
На стенде перенос из PostgreSQL 12 старого образа в PostgreSQL 16 сохранил устройство, два показателя и вход администратора. Возврат из резервной копии новой установки также сохранил ее показания.
Уязвимости прошлых версий
В выбранной v4.2.2.7 присутствуют перечисленные исправления ветки 4.2. Старую установку перед обновлением сохраните вместе с конфигурацией; простая замена контейнера не переносит базу из tb-postgres.
| Идентификатор | Уровень | Затронуто | Исправление | Что делать владельцу |
|---|---|---|---|---|
| CVE-2026-22610 | High, 8,5 | v4.2.1.1: Angular 18.2.13 | v4.2.1.2 | Обновить старый интерфейс: возможен XSS через SVG-атрибуты |
| PR-15412 | Вендор не указал | Точный диапазон не опубликован | v4.2.2.2 | Включить SSRF_PROTECTION_ENABLED=true: защита URL провайдера ИИ |
| PR-15585 | Вендор не указал | Точный диапазон не опубликован | v4.2.2.2 | Обновить песочницу TBEL: старый код мог обращаться к файлам и сети |
SSRF-защита включена в приведенном compose. Номер исправления взят из релизов вендора; эти исправления не заменяют закрытые порты и смену заводского пароля.
Связь с другими стеками
Прокси к внешним API входит в VPS и задан в JAVA_OPTS и HTTP(S)_PROXY. Для ИИ-модели укажите в ее настройках собственный ключ и провайдера; показания и тревоги обрабатываются без модели.
Для почтовых приглашений задайте свой SMTP в системных Mail server settings: адрес, порт, STARTTLS, логин и пароль, затем Send test mail. На стенде тестовое письмо и приглашение пользователя дошли.
MQTT оставлен на localhost:1883. Для удаленного издателя откройте SSH-туннель:
ssh -L 1883:127.0.0.1:1883 логин@ваш-доменПодключайте MQTT-клиент к localhost:1883, логин - токен устройства.
Объектное хранилище удобно для выгрузки копий. Саму телеметрию этот профиль пишет в PostgreSQL: подключение S3 не заменит базу и не освободит ее диск.
Когда это НЕ ваш выбор
Нужен только брокер
ThingsBoard ожидает собственные топики и модель устройств. Произвольный существующий MQTT-поток придется адаптировать; для прозрачной замены транспорта проще отдельный Mosquitto.
Нужен готовый русский кабинет
В CE v4.2.2.7 русского языка нет в живом переключателе. Показать англоязычный интерфейс заказчику стоит до выбора платформы.
Нужны отказоустойчивость и публичный MQTT с TLS сразу
Одна VM с одним брокером не дает высокой доступности. В этой конфигурации устройства снаружи отправляют данные по HTTPS; отдельный защищенный MQTT-вход потребует настройки.
Нужен один домашний график
Отдельные JVM, очередь и база дадут больше обслуживания, чем пользы. Готовая модель заказчиков оправдана, когда этим доступом действительно пользуются.
Частые вопросы
Где войти после установки?
По https://ваш-домен: sysadmin@thingsboard.org управляет системой, tenant@thingsboard.org - устройствами. Пароль обоим задается при установке; в описанном сценарии это пароль сервера из панели.
Почему приложение отвечает, а панель пуста?
Без LOAD_DEMO нет примеров. Создайте устройство, отправьте JSON, затем добавьте виджет с этим устройством как источником. Показания доступны в Latest telemetry.
Подтверждение тревоги ее закрывает?
Нет. Acknowledge фиксирует действие оператора, а Clear зависит от условия очистки. В примере оно срабатывает, когда температура становится ниже 28.
Пропадут ли графики после перезапуска?
Нет: устройства, история и панели сохранились после остановки и запуска PostgreSQL, Kafka и приложения с прежними томами. Не используйте docker compose down -v: флаг удаляет данные.
Как открыть журнал ошибок?
В каталоге установки выполните docker compose logs --tail=100 thingsboard. Состояние соседних компонентов покажет docker compose ps.
Итог
ThingsBoard CE связывает датчик, историю, тревогу и клиента в одном приложении. Интегратор получает основу кабинета, которую остается наполнить своими устройствами и правилами, а эксплуатация базы и очереди остается его задачей.
Рекомендуемая конфигурация для установки:
4 vCPU · 8 ГБ RAM · 100 ГБ NVMe
Не хотите устанавливать вручную?
Запустите ThingsBoard на этой конфигурации автоматически - от 990 ₽/мес.
Этот стек у нас запущен на тарифе CPU4-RAM8-DISK100. Нашли баг в гайде - напишите, поправим в течение дня.