🚀 NOW WE ENTER PHASE 5
🎯 WHAT YOU WILL GET AFTER PHASE 5
✔️ A backend server running on Node.js
✔️ An MQTT ingestion service that listens for device messages
✔️ Inserts telemetry into TimescaleDB
✔️ A REST API that your frontend dashboard will use
✔️ Device registration + device keys
✔️ Secure token-based authentication
✔️ All running as systemd services (like real production systems)
No Docker needed.
Straight Linux + Node.js.
🧱 PHASE 5 — Step-by-Step
We will do this in proper order:
🔹 STEP 1 — Install Node.js LTS on Ubuntu (the correct method)
We will install Node.js 20 LTS (stable for production).
Run:
sudo apt update
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
Then verify:
node -v
npm -v
Successful output looks like:
v20.x.x
10.x.x
🔹 STEP 2 — Create Directory for Your IoT Server
We will place it in:
/home/user/iot-server
Run:
mkdir ~/iot-server
cd ~/iot-server
in the command mkdir ~/iot-server, there is no space between the tilde (~) and the /iot-server part of the path.
mkdir: This is the “make directory” command, used to create new directories.~: The tilde symbol is a special character that represents the current user’s home directory (e.g.,/home/username/on Linux).iot-server: This is the name of the new directory that will be created.
After running this command, you will have a new, empty directory ready for use at the path ~/iot-server (e.g., /home/username/iot-server).
🔹 STEP 3 — Initialize the Project
Run:
npm init -y
This creates package.json.
🔹 STEP 4 — Install Required Libraries
Run:
npm install mqtt pg express cors dotenv
These libraries will be used for:
| Library | Purpose |
|---|---|
mqtt | Connect to the local Mosquitto broker |
pg | PostgreSQL + TimescaleDB client |
express | REST API server |
cors | Allow browser dashboard to access the API |
dotenv | Load passwords safely |
🔹 STEP 5 — Create Basic Backend Files
We will create:
1. .env → store DB and MQTT credentials
2. server.js → REST API
3. mqttWorker.js → MQTT ingestion worker
4. db.js → PG connection pool
I will generate full code for all files once you confirm Step 1 is complete.
🧪 Your Turn
Please run:
node -v
npm -v
And paste the output here.
Once Node.js is installed successfully, I will generate the full backend structure and code for you.
💬 Reply with the Node.js + npm versions, and we proceed to full backend creation.
O/P
1.) ~/iot-server$ node -v npm -v v20.19.5 10.8.2,
2.) ~/iot-server$ npm install mqtt pg express cors dotenv added 126 packages, and audited 127 packages in 11s 22 packages are looking for funding run npm fund for details found 0 vulnerabilities
🔥 Perfect! Perfect! Perfect!
Your Node.js environment is ready for a real production IoT backend.
You now have:
- Node.js v20 LTS ✔
- npm v10 ✔
- All required libraries installed ✔
mqttpgexpresscorsdotenv
Now we can build the backend + MQTT ingestion engine that connects Mosquitto → Node.js → TimescaleDB.
This is the core of your IoT platform.
We will proceed cleanly, with full explanation of what each line does.
🚀 PHASE 5 — Create Your IoT Backend Structure
Inside:
~/iot-server
We will create 3 main files:
1️⃣ db.js
Connection to PostgreSQL (TimescaleDB)
2️⃣ mqttWorker.js
Listens to MQTT messages (from Mosquitto)
Parses them
Stores into TimescaleDB
3️⃣ server.js
REST API server (Express)
For device management, dashboard API, etc.
4️⃣ .env
Secure credentials (never hard-code passwords)
🔹 STEP 1 — Create the .env file
Run:
nano .env
Put this inside (replace passwords accordingly):
# PostgreSQL
PG_HOST=127.0.0.1
PG_PORT=5432
PG_USER=iotadmin
PG_PASSWORD=your_pg_password
PG_DATABASE=iotdb
# MQTT
MQTT_HOST=mqtt://127.0.0.1
MQTT_USERNAME=iotdevice
MQTT_PASSWORD=your_iotdevice_password
MQTT_TOPIC=devices/+/data
Explanation:
devices/+/datameans:- Any device ID
- Topic format like:
devices/device123/data
- This is good for scalable device structures.
Save:
CTRL + O → Enter
CTRL + X
🔹 STEP 2 — Create db.js (PostgreSQL connection)
Run:
nano db.js
Paste:
const { Pool } = require('pg');
require('dotenv').config();
const pool = new Pool({
host: process.env.PG_HOST,
port: process.env.PG_PORT,
user: process.env.PG_USER,
password: process.env.PG_PASSWORD,
database: process.env.PG_DATABASE,
});
module.exports = pool;
Explanation:
- Uses connection pool (recommended)
- Automatically loads credentials from
.env - We export
poolto use everywhere
Save and exit.
🔹 STEP 3 — Create mqttWorker.js (MQTT ingestion service)
Run:
nano mqttWorker.js
Paste:
const mqtt = require('mqtt');
const pool = require('./db');
require('dotenv').config();
const client = mqtt.connect(process.env.MQTT_HOST, {
username: process.env.MQTT_USERNAME,
password: process.env.MQTT_PASSWORD,
});
client.on('connect', () => {
console.log('MQTT connected');
client.subscribe(process.env.MQTT_TOPIC, (err) => {
if (err) console.error('Subscription error:', err);
else console.log(`Subscribed to ${process.env.MQTT_TOPIC}`);
});
});
client.on('message', async (topic, message) => {
try {
const payload = message.toString();
const parts = topic.split('/'); // devices/deviceId/data
const deviceId = parts[1];
console.log(`Message from ${deviceId}:`, payload);
await pool.query(
`INSERT INTO telemetry (time, device_id, payload)
VALUES (NOW(), $1, $2::jsonb)`,
[deviceId, payload]
);
console.log('Data inserted into TimescaleDB');
} catch (err) {
console.error('Insert error:', err);
}
});
What this does:
- Connects to MQTT broker
- Subscribes to all device data topics
- Every message is:
- Time-stamped
- Device ID extracted from topic
- Stored into TimescaleDB telemetry hypertable
This is a TRUE IoT backend ingestion engine.
Save and exit.
🔹 STEP 4 — Create server.js (REST API)
Run:
nano server.js
Paste:
const express = require('express');
const cors = require('cors');
const pool = require('./db');
require('dotenv').config();
const app = express();
app.use(cors());
app.use(express.json());
// Simple test route
app.get('/', (req, res) => {
res.send('IoT Backend API running');
});
// Get latest telemetry for a device
app.get('/api/device/:id/latest', async (req, res) => {
try {
const result = await pool.query(
`SELECT * FROM telemetry
WHERE device_id = $1
ORDER BY time DESC
LIMIT 1`,
[req.params.id]
);
res.json(result.rows[0] || {});
} catch (err) {
console.error(err);
res.status(500).send('Database error');
}
});
const PORT = 3000;
app.listen(PORT, () => console.log(`API running on port ${PORT}`));
[req.params.id]
); res.json(result.rows[0] || {}); } catch (err) { console.error(err); res.status(500).send(‘Database error’); } }); const PORT = 3000; app.listen(PORT, () => console.log(`API running on port ${PORT}`));
This:
- Creates API
- Adds endpoint:
/api/device/<id>/latest - Fetches latest message from TimescaleDB
- Prepares foundation for dashboard
Save and exit.
🔹 STEP 5 — Run MQTT Worker + API
Open two terminal tabs.
Tab 1 — Start MQTT Worker
node mqttWorker.js
Should show:
MQTT connected
Subscribed to devices/+/data
Tab 2 — Start API
node server.js
Should show:
API running on port 3000
🧪 Send Test MQTT Message (simulate a device)
From any terminal:
mosquitto_pub \
-h 127.0.0.1 \
-u iotdevice \
-P 'yourpassword' \
-t devices/deviceA/data \
-m '{"temp": 25.5, "hum": 60}'
MQTT worker should log:
Message from deviceA: {"temp": 25.5, "hum": 60}
Data inserted into TimescaleDB
📩 Your Turn — Reply with:
1. Output of "node mqttWorker.js" after starting
2. Output of "node server.js"
3. Run the mosquitto_pub test message and paste MQTT worker output
Once all this works, we move to:
🚀 PHASE 6 — Turning MQTT Worker + API into Background Services (systemd)
This will make your backend run 24/7, automatically on reboot.