An iotstack raspberry pi setup gives you Node-RED, InfluxDB and Grafana as Docker containers that you can rebuild, update and back up with a few commands. In this tutorial you will install IOTstack, select the containers you need, connect Node-RED to an external MQTT broker instead of a local Mosquitto container, store readings in InfluxDB and chart them in Grafana. By the end you will have a reproducible stack and a clear idea of what belongs on the Pi and what does not.
What IOTstack Is and Why It Helps
IOTstack is a community project that wraps Docker Compose in a menu. You pick services from a list, it generates a docker-compose.yml with sensible volumes and ports, and you start everything with one command. The benefits over installing each tool natively are real:
- Isolation. Node-RED's Node.js version cannot conflict with anything else on the Pi.
- Reproducibility. The whole stack is described in one file plus a
volumesfolder. Copy both to a new Pi and you are back in business. - Clean upgrades. Pull a newer image, recreate the container, and roll back if it misbehaves.
The menu offers a Mosquitto container too, and many guides install it by reflex. Think about whether you need it. A local broker only serves devices that can reach the Pi. If your sensors live in more than one place, if you want to reach data from your phone without opening ports, or if you simply do not want to maintain broker security yourself, an external broker is the better choice. Here we use the ConnectMQ cloud broker, and the Pi becomes a pure processing and storage node.
| Service | Container in this tutorial | Port |
|---|---|---|
| Node-RED | Yes | 1880 |
| InfluxDB 1.8 | Yes | 8086 |
| Grafana | Yes | 3000 |
| Portainer CE | Optional | 9000 |
| Mosquitto | No, replaced by a cloud broker | n/a |
Install IOTstack on the Raspberry Pi
Start from Raspberry Pi OS Lite or Desktop, 64-bit, fully updated. The IOTstack installer sets up Docker, the Compose plugin and the IOTstack folder in your home directory:
sudo apt update && sudo apt full-upgrade -y
curl -fsSL https://raw.githubusercontent.com/SensorsIot/IOTstack/master/install.sh | bash
The script may ask you to reboot so your user joins the docker group. After rebooting, check Docker works without sudo:
docker version
docker compose version
Then launch the menu:
cd ~/IOTstack
./menu.sh
Choose Build Stack, then use the space bar to select nodered, influxdb and grafana (and portainer-ce if you like a web UI for containers). When you select Node-RED, the menu offers add-on nodes. Tick node-red-contrib-influxdb and node-red-dashboard (or the newer Dashboard 2.0 package if listed). Leave mosquitto unselected. Exit the menu and start the stack:
cd ~/IOTstack
docker compose up -d
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
All three containers should report Up. Data lives under ~/IOTstack/volumes/, one folder per service.
Create the InfluxDB Database
The influxdb service in IOTstack is InfluxDB 1.8, which uses InfluxQL and has no setup wizard. Create a database and a retention policy from inside the container:
docker exec -it influxdb influx
CREATE DATABASE sensors
CREATE RETENTION POLICY "ninety_days" ON "sensors" DURATION 90d REPLICATION 1 DEFAULT
SHOW DATABASES
exit
Containers in the same Compose project share a network and reach each other by service name. That is why Node-RED and Grafana will use http://influxdb:8086, not localhost.
Connect Node-RED to an External MQTT Broker
Open Node-RED at http://<pi-ip>:1880. Drag an mqtt in node onto the canvas and edit its server:
- Server:
broker.connectmq.com - Port:
1883for testing on the public broker - Protocol: MQTT V5 (or 3.1.1)
- Client ID: something unique and non-empty, for example
iotstack-nr-5d02e8 - Topic:
connectmq/demo/5d02e8/+/climate - Output: a parsed JSON object
The public broker needs no credentials, so you can test right away. Remember that the free public MQTT broker is readable by anyone, which is why the topic contains a random segment. If you are new to Node-RED's MQTT nodes, the Node-RED MQTT tutorial covers the config node in depth.
The Node-RED Flow: MQTT to InfluxDB
Import the flow below with Menu, Import. It subscribes to every room's climate topic, extracts the room name from the topic and writes a point to InfluxDB.
[
{
"id": "mqttIn1",
"type": "mqtt in",
"name": "climate in",
"topic": "connectmq/demo/5d02e8/+/climate",
"qos": "1",
"datatype": "json",
"broker": "broker1",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140, "y": 100,
"wires": [["toPoint1"]]
},
{
"id": "toPoint1",
"type": "function",
"name": "to InfluxDB point",
"func": "const room = msg.topic.split('/')[3];\nconst p = msg.payload;\nif (typeof p.t !== 'number') { return null; }\nmsg.measurement = 'climate';\nmsg.payload = [\n { temperature: p.t, humidity: p.rh },\n { room: room }\n];\nreturn msg;",
"outputs": 1,
"x": 360, "y": 100,
"wires": [["influxOut1"]]
},
{
"id": "influxOut1",
"type": "influxdb out",
"influxdb": "influxCfg1",
"name": "write sensors",
"measurement": "",
"precision": "",
"retentionPolicy": "",
"x": 580, "y": 100,
"wires": []
},
{
"id": "broker1",
"type": "mqtt-broker",
"name": "ConnectMQ public",
"broker": "broker.connectmq.com",
"port": "1883",
"clientid": "iotstack-nr-5d02e8",
"autoConnect": true,
"usetls": false,
"protocolVersion": "5",
"keepalive": "60",
"cleansession": true
},
{
"id": "influxCfg1",
"type": "influxdb",
"hostname": "influxdb",
"port": "8086",
"database": "sensors",
"name": "IOTstack InfluxDB",
"influxdbVersion": "1.x"
}
]
The function node returns an array of two objects, fields first and tags second, which is the format node-red-contrib-influxdb expects for a single point with tags. Deploy, then publish a test reading:
mosquitto_pub -h broker.connectmq.com -p 1883 -i tester-5d02e8 -q 1 \
-t connectmq/demo/5d02e8/office/climate -m '{"t":22.4,"rh":41}'
Check that it arrived:
docker exec -it influxdb influx -database sensors \
-execute 'SELECT * FROM climate ORDER BY time DESC LIMIT 5'
Grafana on the IOTstack Raspberry Pi
Open Grafana at http://<pi-ip>:3000, log in with the default admin account and change the password. Add a data source:
- Connections, Data sources, Add, InfluxDB.
- Query language: InfluxQL.
- URL:
http://influxdb:8086. - Database:
sensors. No user or password needed with the default IOTstack config. - Save and test.
Create a dashboard with a Time series panel and this query:
SELECT mean("temperature") FROM "climate"
WHERE $timeFilter
GROUP BY time($__interval), "room" fill(none)
Enter $tag_room in the query editor's ALIAS field and you get one clearly labelled line per room. If you prefer InfluxDB 2 and Flux, IOTstack also offers an influxdb2 service; the Raspberry Pi Grafana InfluxDB tutorial shows the Flux side in detail.
Production: Private Broker Credentials and TLS
For real deployments, replace the public broker with a private one. On a hosted MQTT broker like ConnectMQ, you create a broker in the portal and receive a username, password and client ID. In Node-RED, edit the mqtt-broker config node:
- Port
8883, tick Use TLS and add a TLS config with Verify server certificate enabled. ConnectMQ uses a Let's Encrypt certificate, so no custom CA file is needed. - Client ID:
YOUR_CLIENT_ID. ConnectMQ binds client IDs to issued credentials, so use exactly the one shown in the portal. - Security tab:
YOUR_USERNAMEandYOUR_PASSWORD.
Node-RED stores credentials encrypted in flows_cred.json inside ~/IOTstack/volumes/nodered/data. Set a credentialSecret in settings.js in the same folder so the encryption key is stable across container rebuilds.
Backups and Updates
IOTstack's strength is that everything you care about is in two places: docker-compose.yml and volumes/. A simple routine:
- Stop the stack briefly with
docker compose stop(or use IOTstack's backup scripts if you installed them). - Archive the folder:
sudo tar czf ~/iotstack-$(date +%F).tgz -C ~ IOTstack/docker-compose.yml IOTstack/volumes. - Start again with
docker compose up -dand copy the archive off the Pi.
To update images:
cd ~/IOTstack
docker compose pull
docker compose up -d
docker image prune -f
Pin image tags in docker-compose.yml for services where a surprise major upgrade would hurt, InfluxDB in particular.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Node-RED MQTT node stays "connecting" | Wrong port or TLS setting | 1883 without TLS, 8883 with TLS |
| Node-RED shows "disconnected" right after connecting | Duplicate client ID | Each client needs its own ID |
InfluxDB node error ENOTFOUND influxdb |
Host set to localhost |
Use the service name influxdb |
| Grafana "database not found" | Database not created | Run CREATE DATABASE sensors |
| Containers stop after reboot | Restart policy missing | IOTstack sets restart: unless-stopped, check the file |
Get Started with ConnectMQ
Let IOTstack do the processing and let a managed broker handle the connections. Create a free account at app.connectmq.com, choose the Serverless plan with no credit card, and paste the generated credentials into your Node-RED config node. More Pi projects are collected in the Raspberry Pi MQTT tutorial.
Frequently Asked Questions
Do I need the Mosquitto container in IOTstack?
Only if every device is on the same local network and you want the broker on the Pi. With an external cloud broker, Node-RED subscribes over the internet and you avoid maintaining broker security on the Pi.
Which InfluxDB version does IOTstack use?
The influxdb service is InfluxDB 1.8 with InfluxQL, and a separate influxdb2 service provides version 2 with Flux. Pick one and stick with it, since the Node-RED and Grafana settings differ.
Can I run IOTstack on a 32-bit Raspberry Pi OS?
Some images still publish 32-bit builds, but support is shrinking. A 64-bit OS avoids most image compatibility problems.
How do I move IOTstack to a new Raspberry Pi?
Install IOTstack on the new Pi, stop it, then restore your docker-compose.yml and volumes folder and run docker compose up -d.



