Обновлено 24 октября 2026 г.
Аналитика и метрики

ThingsBoard

IoT-платформа на вашем сервере: история показаний датчиков, тревоги и кабинет заказчика без разработки бэкенда с нуля. Развернули CE v4.2.2.7 на Fatmetal Cloud Server, замерили ресурсы, проверили телеметрию и доступ заказчика.

Проверено на версии v4.2.2.7, 24 октября 2026~11 минут чтенияFatmetal Team
IoT-платформаApache-2.04 контейнераCE v4.2.2.7

Вердикт

Подходит
  • интегратору: датчики уже передают данные, заказчик просит историю и тревоги
  • оператору нескольких объектов: каждому клиенту нужен отдельный кабинет
  • разработчику, который хочет собрать IoT-приложение вокруг готовой модели устройств
Не подходит
  • для одного графика: отдельная IoT-платформа усложнит обслуживание
  • для замены брокера без изменения произвольных MQTT-топиков
  • если заказчику нужен готовый русский интерфейс
Тариф: CPU4-RAM8-DISK100RAM стека в простое: 2,3 ГиБ без файлового кешаСложность: средняяГлавный риск: заводской пароль при первом стартеЭксплуатация: PostgreSQL, Kafka, резервные копии
Задача

Что это и какую задачу решает

ThingsBoard принимает показания устройств, хранит историю, проверяет условия тревог и показывает результат пользователю. Устройство, профиль, заказчик и панель уже связаны между собой: эту часть приложения не приходится писать заново.

Пример - два склада с датчиками температуры. Оператор видит оба, владелец склада A получает доступ только к своему объекту. При перегреве появляется тревога, которую сотрудник подтверждает в интерфейсе.

В проверенной Community Edition этот сценарий работает без коммерческого ключа.

Яндекс IoT Core закрывается 1 декабря 2026 года. В инструкции Яндекса ThingsBoard предложен для сценариев с панелями и правилами. Устройства потребуется адаптировать; готовый перенос из Яндекса в этом разборе не проверен.

Виртуальные датчики передали значения по HTTP и MQTT, а история и подтвержденная тревога сохранились после остановки и запуска стека.

https://ваш-домен
Два виртуальных склада, температура и критическая тревога в ThingsBoard CE v4.2.2.7
Рабочая панель: реальные записи виртуальных датчиков, четыре исторические точки перегрева и подтвержденная тревога.
Обновление

Что изменилось с прошлого разбора

Сентябрьская статья проверялась на v4.2.1.1: приложение и PostgreSQL находились в tb-postgres, очередь работала в памяти. Для v4.2.2.7 нужен другой состав установки.

Было: v4.2.1.1Стало: v4.2.2.7
thingsboard/tb-postgresthingsboard/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 Prototype49 $/мес, 50 устройствПлатформа у вендора
Ubidots Professional99 $/мес, 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. Токен устройства дает право отправлять его показания; пароль администратора для датчиков не используется.

Java 17Spring BootPostgreSQL 16KafkaMQTT / HTTPSDocker Compose
Ресурсы

Какой сервер выбрать

Для проверенного профиля рекомендуем 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 логин@ваш-домен
  1. Установите Docker

    В SSH выполните sudo -i: команды идут от root.

    apt-get update && apt-get install -y docker.io docker-compose-v2 openssl curl
  2. Задайте домен и секреты

    Используйте выбранный адрес в 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
  3. Подготовьте 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
  4. Сохраните 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
  5. Запустите базу и очередь

    В журнале PostgreSQL дождитесь ready to accept connections, у Kafka - Kafka Server started. Оба сообщения нужны до установки схемы.

    docker compose up -d postgres kafka
    docker compose logs --tail=30 postgres kafka
  6. Создайте схему и запустите приложение

    Установщик схемы выполните один раз, без 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
  7. Смените пароль до открытия сайта

    В открытом туннеле на своем компьютере перейдите на http://localhost:8080, войдите как sysadmin@thingsboard.org с паролем sysadmin. В меню профиля выберите Security и задайте пароль сервера из панели.

  8. Создайте владельца устройств

    Откройте Tenants → +, создайте организацию. В ее строке откройте Manage tenant admins → +. Укажите tenant@thingsboard.org, выберите Display activation link. Откройте ссылку в приватном окне и задайте тот же пароль сервера. Demo-аккаунтов здесь нет.

  9. Включите 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. История и карточка читают одно устройство.

https://ваш-домен
Latest telemetry устройства warehouse-a-01
Три ключа реального объекта: температура, влажность и батарея. Источник - отправленный JSON.
https://ваш-домен
Критическая тревога перегрева с подтверждением оператора
Оператор подтвердил тревогу через Acknowledge; подтверждение не означает, что температура уже снизилась.

В Customers создайте Warehouse A. Назначьте ему устройство и панель через Assign to customer; через Manage customer users создайте пользователя. Откройте его активационную ссылку в отдельном окне и войдите.

В проверке клиент видел свой склад A; запрос к чужому устройству возвращал 403. Общую операторскую панель ему не назначали: разделение доступа строится на назначении объектов заказчику.

https://ваш-домен
Отдельный вход заказчика с данными только склада A
Кабинет заказчика: собственная панель, собственный датчик и его тревога.
Замеры

Что показали замеры

Стенд CPU4-RAM8-DISK100: Ubuntu 24.04.4, ThingsBoard CE v4.2.2.7, отдельные PostgreSQL и Kafka. Память ниже - рабочая память контейнеров без файлового кеша.

Стек в простое2,3 ГиБ
Из них приложение / Kafka1,8 ГиБ / 547 МиБ
Образ ThingsBoard2,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. На новых версиях результаты могут отличаться.

Диагностика

Где может сломаться

manifest unknown: thingsboard/tb-postgres

Причина. Номер свежего релиза приложения не гарантирует наличие старого объединенного образа.

Решение. Используйте thingsboard/tb-node:4.2.2.7 с отдельной PostgreSQL, как в compose выше. Проверьте образ: docker compose images.

curl: Failed to connect to 127.0.0.1 port 8080

Причина. Команда up уже завершилась, но Java-приложение еще запускается.

Решение. Дождитесь Started ThingsboardServerApplication в журнале и повторите curl. Установщик схемы запускается один раз.

docker compose logs --tail=100 thingsboard
too many certificates already issued for this exact set of identifiers

Причина. Переиспользованный адрес сервера исчерпал недельный лимит 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 внешним адресом сервера и выберите свою метку.

FATAL: role "postgres" does not exist

Причина. В 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.

is not supported for upgrade. Supported versions are: [4.2.0]

Причина. 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-22610High, 8,5v4.2.1.1: Angular 18.2.13v4.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, очередь и база дадут больше обслуживания, чем пользы. Готовая модель заказчиков оправдана, когда этим доступом действительно пользуются.

FAQ

Частые вопросы

Где войти после установки?

По 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 ₽/мес.

Запустить ThingsBoard →
Анонсы новых разборов в Telegram-канале Новые гайды и карточки в маркетплейсе первыми @fatmetal_channel →

Этот стек у нас запущен на тарифе CPU4-RAM8-DISK100. Нашли баг в гайде - напишите, поправим в течение дня.