Installing ThingsBoard PE on CentOS/RHEL
This guide covers installing ThingsBoard Professional Edition (PE) on CentOS/RHEL Server. By the end, you will have a fully functional ThingsBoard instance up and running.
Prerequisites
Section titled “Prerequisites”RHEL 8/9/10, CentOS 8/9, or derivatives (AlmaLinux, Rocky Linux, Oracle Linux, etc.)
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 | 100 GB SSD | ThingsBoard, PostgreSQL, Kafka |
| Production (recommended) | 4+ cores | 16+ GB | 200+ GB SSD | ThingsBoard, PostgreSQL, Kafka, Cassandra |
Install required tools. Choose your OS version:
sudo dnf install -y wgetsudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpmsudo dnf install -y wgetsudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpmStep 1. Install Java (OpenJDK)
Section titled “Step 1. Install Java (OpenJDK)”ThingsBoard requires Java 17 or higher. We recommend installing OpenJDK 21:
sudo dnf install -y java-21-openjdk-headlessSet Java 21 as the default version. Use the non-interactive command:
sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk/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 dnf install -y harfbuzz fontconfig dejavu-sans-fontsDownload and install the ThingsBoard PE 4.3.1.1PE package.
wget https://dist.thingsboard.io/thingsboard-4.3.1.1pe.rpmsudo rpm -Uvh thingsboard-4.3.1.1pe.rpmVerify the installation:
rpm -qa | grep 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 the PostgreSQL repository for your OS version:
sudo dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpmsudo dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpmInstall and start PostgreSQL 18:
sudo dnf -qy module disable postgresqlsudo dnf -y install postgresql18 postgresql18-server postgresql18-contribsudo /usr/pgsql-18/bin/postgresql-18-setup initdbsudo systemctl enable --now postgresql-18Export 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 the PostgreSQL repository for your OS version:
sudo dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpmsudo dnf -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpmInstall and start PostgreSQL 18:
sudo dnf -qy module disable postgresqlsudo dnf -y install postgresql18 postgresql18-server postgresql18-contribsudo /usr/pgsql-18/bin/postgresql-18-setup initdbsudo systemctl enable --now postgresql-18Export 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:
sudo rpm --import https://downloads.apache.org/cassandra/KEYSsudo tee /etc/yum.repos.d/cassandra.repo > /dev/null <<'EOF'[cassandra]name=Apache Cassandrabaseurl=https://redhat.cassandra.apache.org/50x/gpgcheck=1repo_gpgcheck=0gpgkey=https://downloads.apache.org/cassandra/KEYSEOFsudo dnf -y update && sudo dnf -y install cassandra cassandra-tools chkconfigsudo systemctl daemon-reexecsudo systemctl start cassandra.servicesudo chkconfig cassandra onVerify 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 CentOS/RHEL.
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 CentOS/RHEL.
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.rpmInstall required libraries:
sudo dnf install -y pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc unzip nssInstall Roboto fonts:
sudo dnf install -y google-roboto-fontsInstall and start the WebReport service:
sudo rpm -Uvh tb-web-report-4.3.1.1pe.rpmsudo 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 CentOS/RHEL 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.