Installing ThingsBoard PE on Ubuntu Server
This guide covers installing ThingsBoard Professional Edition (PE) on Ubuntu Server. By the end, you will have a fully functional ThingsBoard instance up and running.
Prerequisites
Section titled “Prerequisites”- Ubuntu 22.04 LTS or 24.04 LTS
Ensure your server meets the minimum requirements:
| Use case | CPU | RAM | Storage | Recommended services |
|---|---|---|---|---|
| Development / PoC | 1 core | 4 GB | 20 GB | ThingsBoard, PostgreSQL |
| Production (small) | 2 cores | 8 GB | 50 GB SSD | ThingsBoard, PostgreSQL, Kafka |
| Production (recommended) | 4+ cores | 16+ GB | 100+ GB SSD | ThingsBoard, PostgreSQL, Kafka, Cassandra |
Step 1. Install Java (OpenJDK)
Section titled “Step 1. Install Java (OpenJDK)”ThingsBoard requires Java 17 or higher. We recommend installing OpenJDK 21:
sudo apt update && sudo apt install -y openjdk-21-jdk-headlessSet Java 21 as the default version. Use the non-interactive command:
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-$(dpkg --print-architecture)/bin/javaOr, if you have multiple Java versions installed and want to choose interactively:
sudo update-alternatives --config javaVerify the installation:
java -versionStep 2. Install ThingsBoard package
Section titled “Step 2. Install ThingsBoard package”Install required font libraries needed by the reporting component:
sudo apt update && sudo apt install -y libharfbuzz0b fontconfig fonts-dejavu-coreDownload and install the ThingsBoard PE 4.3.1.1PE package.
wget https://dist.thingsboard.io/thingsboard-4.3.1.1pe.debsudo dpkg -i thingsboard-4.3.1.1pe.debVerify the installation:
dpkg -l thingsboardStep 3. Obtain and configure license key
Section titled “Step 3. Obtain and configure license key”We assume you have already chosen your subscription plan or decided to purchase a perpetual license. If not, navigate to the pricing page to select the best license option for your case. See How to get a pay-as-you-go subscription or How to get a perpetual license for details.
Export your license secret as an environment variable, replacing YOUR_LICENSE_SECRET with the actual value:
TB_LICENSE_SECRET=YOUR_LICENSE_SECRETThen apply it to the configuration file:
sudo sed -i "s/# export TB_LICENSE_SECRET=.*/export TB_LICENSE_SECRET=$TB_LICENSE_SECRET/" /etc/thingsboard/conf/thingsboard.confStep 4. Configure database
Section titled “Step 4. Configure database”ThingsBoard supports two database configurations:
- PostgreSQL only — stores all data (entities and time-series) in PostgreSQL. Recommended for most deployments handling up to 5,000 messages per second. Simple to operate with minimal infrastructure requirements.
- Hybrid (PostgreSQL + Cassandra) — stores entities in PostgreSQL and time-series data in Cassandra. Designed for high-throughput deployments exceeding 5,000 messages per second or with millions of devices. Requires significant additional resources: at least 8 GB RAM, a dedicated multi-core CPU, and fast SSD storage for the Cassandra node.
Install PostgreSQL 18:
sudo apt install -y postgresql-commonsudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.shsudo apt update && sudo apt -y install postgresql-18sudo systemctl start postgresqlExport your PostgreSQL password as an environment variable — this value will be used in the following steps:
TB_DB_PASSWORD=YOUR_PASSWORDSet the password for the postgres user and create the ThingsBoard database:
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '$TB_DB_PASSWORD';"sudo -u postgres psql -c "CREATE DATABASE thingsboard;"Add the database configuration to the ThingsBoard configuration file:
sudo tee -a /etc/thingsboard/conf/thingsboard.conf > /dev/null << EOF# DB Configurationexport DATABASE_TS_TYPE=sqlexport SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/thingsboardexport SPRING_DATASOURCE_USERNAME=postgresexport SPRING_DATASOURCE_PASSWORD=$TB_DB_PASSWORDEOFInstall PostgreSQL 18:
sudo apt install -y postgresql-commonsudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.shsudo apt update && sudo apt -y install postgresql-18sudo systemctl start postgresqlExport your PostgreSQL password as an environment variable — this value will be used in the following steps:
TB_DB_PASSWORD=YOUR_PASSWORDSet the password for the postgres user and create the ThingsBoard database:
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '$TB_DB_PASSWORD';"sudo -u postgres psql -c "CREATE DATABASE thingsboard;"Install Cassandra:
echo "deb [signed-by=/etc/apt/keyrings/apache-cassandra.asc] https://debian.cassandra.apache.org 50x main" | sudo tee /etc/apt/sources.list.d/cassandra.sources.listsudo curl -o /etc/apt/keyrings/apache-cassandra.asc https://downloads.apache.org/cassandra/KEYSsudo apt-get update && sudo apt-get install -y cassandra cassandra-toolsVerify Cassandra is running:
nodetool statusThe status column should show UN (Up/Normal). Wait a few moments for Cassandra to initialize if needed.
Add the database configuration to the ThingsBoard configuration file:
sudo tee -a /etc/thingsboard/conf/thingsboard.conf > /dev/null << EOF# DB Configurationexport DATABASE_TS_TYPE=cassandraexport SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/thingsboardexport SPRING_DATASOURCE_USERNAME=postgresexport SPRING_DATASOURCE_PASSWORD=$TB_DB_PASSWORDEOFIf you are using an external Cassandra cluster, also add the following to /etc/thingsboard/conf/thingsboard.conf:
export CASSANDRA_CLUSTER_NAME="Thingsboard Cluster"export CASSANDRA_KEYSPACE_NAME=thingsboardexport CASSANDRA_URL=127.0.0.1:9042export CASSANDRA_USE_CREDENTIALS=falseexport CASSANDRA_USERNAME=export CASSANDRA_PASSWORD=Step 5. Choose queue service
Section titled “Step 5. Choose queue service”ThingsBoard uses a message queue to route messages between its internal services. Select the option that matches your infrastructure:
- In Memory (default) — built-in queue, no extra setup required. Suitable for development and PoC. Not recommended for production or multi-node deployments.
- Kafka — high-throughput, durable queue. Run it yourself or use a managed service such as AWS MSK.
- Confluent Cloud — fully managed Kafka service. Use this if you want Kafka without managing the infrastructure yourself.
In Memory queue is built-in and enabled by default. No configuration needed.
This example runs Kafka as a Docker container on the same host. If you already have a Kafka broker or use a managed service (e.g. AWS MSK), skip the Docker setup and update TB_KAFKA_SERVERS to point to your broker.
Install Docker: see Docker for Ubuntu.
Create a directory for your Docker Compose files and add the Kafka configuration:
mkdir -p ~/thingsboardsudo tee ~/thingsboard/docker-compose-kafka.yml > /dev/null << 'EOF'services: kafka: restart: always image: bitnamilegacy/kafka:4.0 ports: - 9092:9092 - 9093 - 9094 environment: ALLOW_PLAINTEXT_LISTENER: "yes" KAFKA_CFG_LISTENERS: "OUTSIDE://:9092,CONTROLLER://:9093,INSIDE://:9094" KAFKA_CFG_ADVERTISED_LISTENERS: "OUTSIDE://localhost:9092,INSIDE://kafka:9094" KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: "INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT,CONTROLLER:PLAINTEXT" KAFKA_CFG_INTER_BROKER_LISTENER_NAME: "INSIDE" KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "false" KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1" KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: "1" KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: "1" KAFKA_CFG_PROCESS_ROLES: "controller,broker" KAFKA_CFG_NODE_ID: "0" KAFKA_CFG_CONTROLLER_LISTENER_NAMES: "CONTROLLER" KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: "0@kafka:9093" volumes: - kafka-data:/bitnamivolumes: kafka-data: driver: localEOFStart Kafka:
docker compose -f ~/thingsboard/docker-compose-kafka.yml up -dAdd the following configuration to /etc/thingsboard/conf/thingsboard.conf:
sudo tee -a /etc/thingsboard/conf/thingsboard.conf > /dev/null << 'EOF'export TB_QUEUE_TYPE=kafkaexport TB_KAFKA_SERVERS=localhost:9092EOFFirst create a Confluent Cloud account, create a Kafka cluster, and obtain your API Key. Add the following lines to /etc/thingsboard/conf/thingsboard.conf, replacing CLUSTER_API_KEY, CLUSTER_API_SECRET, and localhost:9092 with your Confluent Cloud values:
sudo tee -a /etc/thingsboard/conf/thingsboard.conf > /dev/null << 'EOF'export TB_QUEUE_TYPE=kafkaexport TB_QUEUE_KAFKA_USE_CONFLUENT_CLOUD=trueexport TB_KAFKA_SERVERS=localhost:9092export TB_QUEUE_KAFKA_REPLICATION_FACTOR=3export TB_QUEUE_KAFKA_CONFLUENT_SASL_JAAS_CONFIG='org.apache.kafka.common.security.plain.PlainLoginModule required username="CLUSTER_API_KEY" password="CLUSTER_API_SECRET";'export TB_QUEUE_CORE_POLL_INTERVAL_MS=1000export TB_QUEUE_CORE_PARTITIONS=2export TB_QUEUE_RULE_ENGINE_POLL_INTERVAL_MS=1000export TB_QUEUE_TRANSPORT_REQUEST_POLL_INTERVAL_MS=1000export TB_QUEUE_TRANSPORT_RESPONSE_POLL_INTERVAL_MS=1000export TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS=1000export TB_QUEUE_VC_INTERVAL_MS=1000export TB_QUEUE_VC_PARTITIONS=1EOFYou can update the default Rule Engine queue configuration using the UI. See Rule Engine Queues for details.
Step 6. [Optional] Memory configuration
Section titled “Step 6. [Optional] Memory configuration”By default, ThingsBoard has no explicit memory limit — the JVM can consume all available RAM, which may cause the OS to kill the process under memory pressure. Set the heap size to half of your total RAM. The values below are approximate and suited for a single-node setup with In Memory queue and PostgreSQL database:
sudo tee -a /etc/thingsboard/conf/thingsboard.conf > /dev/null << 'EOF'# Maximum heap size — set to half of available RAM.# Example: 2G for a 4 GB server, 4G for an 8 GB server, 8G for a 16 GB server.export JAVA_OPTS="$JAVA_OPTS -Xms4G -Xmx4G -Xss512k -XX:+AlwaysPreTouch"EOFWe recommend adjusting these parameters depending on your server resources. It should be set to at least 2G (gigabytes), and increased accordingly if there is additional RAM space available. Usually, you need to set it to 1/2 of your total RAM if you do not run any other memory-intensive processes (e.g. Cassandra), or to 1/3 otherwise.
Step 7. Run installation script
Section titled “Step 7. Run installation script”Run the installation script to initialize the database schema and load default system data. Choose the option that matches your goal:
- With demo data — also loads a sample tenant account, pre-built dashboards, and demo devices. Useful for exploring the platform before deploying to production.
- Clean install — initializes the database with system data only (rule chains, widget bundles, system dashboards).
sudo /usr/share/thingsboard/bin/install/install.sh --loadDemosudo /usr/share/thingsboard/bin/install/install.shStep 8. Start ThingsBoard
Section titled “Step 8. Start ThingsBoard”Start the ThingsBoard service:
sudo systemctl start thingsboardMonitor the startup. The line confirming the platform is ready will be highlighted:
tail -f /var/log/thingsboard/thingsboard.log | grep --line-buffered --color=always -E 'Started ThingsboardServerApplication|$'Open the following ports in your firewall:
| Port | Protocol | Description |
|---|---|---|
| 8080 | TCP | Web UI and REST API. Not required if using a load balancer. |
| 1883 | TCP | MQTT |
| 8883 | TCP | MQTT over SSL |
| 5683 | UDP | CoAP |
| 5684 | UDP | CoAP over DTLS |
| 5685 | UDP | LwM2M CoAP |
| 5686 | UDP | LwM2M CoAP over DTLS |
| 5687 | UDP | LwM2M (Bootstrap) |
| 5688 | UDP | LwM2M over DTLS (Bootstrap) |
| 161 | UDP | SNMP |
| 7070 | TCP | Edge RPC (gRPC) |
| 9090 | TCP | Remote Integration Executor (gRPC) |
Open http://localhost:8080 in your browser (or http://<your-server-ip>:8080 if accessing remotely). You should see the ThingsBoard login page. Use the following default credentials:
| Role | Password | With demo data | Clean install | |
|---|---|---|---|---|
| System Administrator | [email protected] | sysadmin | ✅ | ✅ |
| Tenant Administrator | [email protected] | tenant | ✅ | ❌ |
| Customer User | [email protected] | customer | ✅ | ❌ |
See Getting Started for your next steps after login.
Step 9. Install ThingsBoard WebReport component
Section titled “Step 9. Install ThingsBoard WebReport component”The WebReport service generates PDF and PNG reports from dashboards. Choose one of the installation methods below:
Install Docker: see Docker for Ubuntu.
Create the Docker Compose file ~/thingsboard/tb-web-report.yml:
mkdir -p ~/thingsboardsudo tee ~/thingsboard/tb-web-report.yml > /dev/null << 'EOF'services: tb-web-report: container_name: tb-web-report restart: always image: "thingsboard/tb-pe-web-report:4.3.1.1PE" ports: - "8383:8383" environment: HTTP_BIND_ADDRESS: "0.0.0.0" HTTP_BIND_PORT: "8383" LOGGER_LEVEL: "info" LOG_FOLDER: "logs" LOGGER_FILENAME: "tb-web-report-%DATE%.log" DOCKER_MODE: "true" DEFAULT_PAGE_NAVIGATION_TIMEOUT: "120000" DASHBOARD_IDLE_WAIT_TIME: "3000" USE_NEW_PAGE_FOR_REPORT: "true"EOFStart the WebReport service:
docker compose -f ~/thingsboard/tb-web-report.yml up -dCheck the container logs:
docker logs -f tb-web-reportDownload the WebReport installation package:
wget https://dist.thingsboard.io/tb-web-report-4.3.1.1pe.debInstall required libraries:
sudo apt install -yq libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \ libexpat1 libfontconfig1 libgcc-s1 libgdk-pixbuf-2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \ libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \ ca-certificates fonts-liberation libnss3 lsb-release xdg-utils unzip wget libgbm-devInstall Roboto fonts:
sudo apt install -y fonts-robotoInstall Noto fonts (Japanese, Chinese, etc.):
mkdir ~/noto && cd ~/notowget https://src.fedoraproject.org/repo/extras/chromium/NotoSansCJKjp-hinted.zip/sha512/e7bcbc53a10b8ec3679dcade5a8a94cea7e1f60875ab38f2193b4fa8e33968e1f0abc8184a3df1e5210f6f5c731f96c727c6aa8f519423a29707d2dee5ada193/NotoSansCJKjp-hinted.zipunzip NotoSansCJKjp-hinted.zipsudo mkdir -p /usr/share/fonts/notosudo cp *.otf /usr/share/fonts/notosudo chmod 655 -R /usr/share/fonts/noto/sudo fc-cache -fvcd .. && rm -rf ~/notoInstall and start the WebReport service:
sudo dpkg -i tb-web-report-4.3.1.1pe.debsudo systemctl start tb-web-reportConfigure HAProxy (HTTPS)
Section titled “Configure HAProxy (HTTPS)”You may want to configure HTTPS access using HAProxy. This is possible if you are hosting ThingsBoard in the cloud and have a valid DNS name assigned to your instance.
See Configure HAProxy on Ubuntu for instructions on installing HAProxy and generating a valid SSL certificate using Let’s Encrypt.
Upgrading
Section titled “Upgrading”See the Upgrade Instructions for detailed steps.
Troubleshooting
Section titled “Troubleshooting”Check the service status:
sudo systemctl status thingsboardThingsBoard logs are stored in /var/log/thingsboard. Check for errors:
grep ERROR /var/log/thingsboard/thingsboard.logMonitor logs in real time:
tail -f /var/log/thingsboard/thingsboard.logOr via journalctl:
sudo journalctl -u thingsboard.service -f --no-pagerFor more troubleshooting tips, see the Troubleshooting guide.