Industrial sensors, smart building systems, fleet tracking devices, and agricultural monitoring equipment across Asia-Pacific generate continuous streams of time-series data. A Hong Kong VPS with CN2 GIA routing makes an ideal IoT platform hub for the region — MQTT devices in mainland China connect at 30–50ms, data flows into InfluxDB for time-series storage, and Grafana dashboards visualise real-time sensor readings for operations teams.
Architecture
<code">
[IoT Devices in China/Asia] ──MQTT── [EMQX Broker on HK VPS]
│
[Node-RED Processing]
│
[InfluxDB Time-Series DB]
│
[Grafana Dashboards + Alerts]
Step 1: Deploy EMQX MQTT Broker
<code">docker run -d \ --name emqx \ --restart unless-stopped \ -p 1883:1883 \ # MQTT (plaintext — use only in trusted networks) -p 8883:8883 \ # MQTT over TLS (production) -p 8083:8083 \ # MQTT over WebSocket -p 18083:18083 \ # EMQX Dashboard (restrict to localhost in production) -e EMQX_DASHBOARD__DEFAULT_PASSWORD=StrongDashboardPass! \ emqx/emqx:latest # Restrict dashboard to localhost (expose via Nginx with auth) # In production, close port 1883 (plaintext) and use only 8883 (TLS) ufw allow 8883/tcp # MQTT TLS from IoT devices ufw allow 8083/tcp # WebSocket MQTT ufw deny 1883/tcp # Block plaintext MQTT from public internet
Configure MQTT TLS
<code"># Use your Let's Encrypt certificate for MQTT TLS # EMQX can be configured to use existing certs: docker exec emqx emqx_ctl conf set listeners.ssl.default.ssl_options.certfile \ /etc/letsencrypt/live/iot.yourdomain.com/fullchain.pem docker exec emqx emqx_ctl conf set listeners.ssl.default.ssl_options.keyfile \ /etc/letsencrypt/live/iot.yourdomain.com/privkey.pem
Step 2: Deploy InfluxDB for Time-Series Storage
<code">docker run -d \ --name influxdb \ --restart unless-stopped \ -p 127.0.0.1:8086:8086 \ -v /opt/influxdb:/var/lib/influxdb2 \ -e DOCKER_INFLUXDB_INIT_MODE=setup \ -e DOCKER_INFLUXDB_INIT_USERNAME=admin \ -e DOCKER_INFLUXDB_INIT_PASSWORD=StrongInfluxPass! \ -e DOCKER_INFLUXDB_INIT_ORG=myorg \ -e DOCKER_INFLUXDB_INIT_BUCKET=iot_data \ -e DOCKER_INFLUXDB_INIT_RETENTION=90d \ # Keep 90 days of sensor data influxdb:2 # Get admin token for API access docker exec influxdb influx auth list --user admin | grep Token
Step 3: Node-RED for Data Processing
<code">docker run -d \ --name nodered \ --restart unless-stopped \ -p 127.0.0.1:1880:1880 \ -v /opt/nodered:/data \ nodered/node-red:latest # Install InfluxDB nodes docker exec nodered npm install @influxdata/influxdb-client node-red-contrib-influxdb
Example Node-RED Flow: MQTT → InfluxDB
<code"># Import this flow in Node-RED UI (Dashboard → Import):
[
{
"id": "mqtt-in",
"type": "mqtt in",
"topic": "sensors/#", // Subscribe to all sensor topics
"broker": "emqx",
"name": "All Sensors"
},
{
"id": "parse-json",
"type": "json",
"name": "Parse JSON"
},
{
"id": "prepare-influx",
"type": "function",
"name": "Format for InfluxDB",
"func": "// MQTT topic: sensors/building-a/floor-3/temperature\nconst parts = msg.topic.split('/');\nconst [, building, floor, measurement] = parts;\n\nmsg.payload = [{\n measurement: measurement,\n tags: { building, floor, device_id: msg.payload.device_id },\n fields: { value: msg.payload.value },\n timestamp: new Date()\n}];\nreturn msg;"
},
{
"id": "influxdb-out",
"type": "influxdb out",
"database": "iot_data",
"measurement": "sensor_readings"
}
]Step 4: IoT Device Connection (Python/MicroPython)
<code"># Python device client (runs on Raspberry Pi, edge gateway, etc.)
import paho.mqtt.client as mqtt
import json
import time
import ssl
# Connect to HK VPS MQTT broker over TLS
client = mqtt.Client(client_id="sensor-bj-001")
client.username_pw_set("device_user", "DevicePassword!")
client.tls_set(cert_reqs=ssl.CERT_REQUIRED) # Validates server certificate
client.connect("iot.yourdomain.com", 8883, keepalive=60)
client.loop_start()
def read_sensors():
"""Read your actual sensors here"""
return {
"temperature": 23.5,
"humidity": 65.2,
"pressure": 1013.2,
"device_id": "sensor-bj-001",
"timestamp": int(time.time())
}
# Publish sensor readings every 30 seconds
while True:
data = read_sensors()
topic = "sensors/building-a/floor-2/environment"
client.publish(topic, json.dumps(data), qos=1)
print(f"Published: {data}")
time.sleep(30)<code"># MicroPython for ESP32/ESP8266 devices:
from umqtt.robust import MQTTClient
import ujson
import time
client = MQTTClient(
"esp32-sensor-01",
"iot.yourdomain.com",
port=8883,
user="device_user",
password="DevicePassword!",
ssl=True
)
client.connect()
while True:
# Read sensor (example: DHT22 temperature/humidity)
data = {"temp": 24.1, "humidity": 58.3, "device": "esp32-01"}
client.publish(b"sensors/factory/line-1/env", ujson.dumps(data))
time.sleep(60)Step 5: Grafana IoT Dashboard
<code"># Configure Grafana with InfluxDB data source: # Grafana → Data Sources → Add → InfluxDB # Query Language: Flux # URL: http://localhost:8086 # Organisation: myorg # Token: YOUR_INFLUX_TOKEN # Default Bucket: iot_data # Sample Flux query for temperature time-series: # from(bucket: "iot_data") # |> range(start: -24h) # |> filter(fn: (r) => r._measurement == "temperature") # |> filter(fn: (r) => r.building == "building-a") # |> aggregateWindow(every: 5m, fn: mean) # Key dashboard panels: # - Real-time temperature gauge per floor/room # - 24h trend line per sensor # - Alert indicator (green/red) for out-of-range values # - Device connectivity status (last seen timestamp)
Step 6: Alerting for Out-of-Range Sensors
<code"># Grafana alert rule: temperature exceeds threshold
# Query: from InfluxDB → temperature for building-a
# Condition: IS ABOVE 35 (degrees Celsius)
# For: 5 minutes
# Contact point: Email + WeChat Work webhook
# Node-RED alert flow (alternative — runs at MQTT layer):
# MQTT in → Filter node (if value > threshold) → HTTP request (WeChat Work webhook)
# WeChat Work webhook message for temperature alert:
curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"msgtype": "text",
"text": {
"content": "🚨 温度告警\n地点: 北京A楼3层\n当前温度: 38.2°C\n超过阈值: 35°C\n时间: 2026-08-25 14:32"
}
}'Scale: Capacity on a Hong Kong VPS
| Metric | 2 GB VPS | 4 GB VPS | 8 GB VPS |
|---|---|---|---|
| Concurrent MQTT connections | 1,000 | 5,000 | 20,000+ |
| Messages/second | 5,000 | 20,000 | 100,000+ |
| InfluxDB data retention | 30 days | 90 days | 1 year+ |
| Grafana dashboards | Basic | Full | Full + alerting |
Conclusion
An IoT platform on a Hong Kong VPS with CN2 GIA routing serves as the ideal data hub for Asia-Pacific deployments — devices in mainland China, Taiwan, Southeast Asia, and Japan all connect to the MQTT broker at 30–80ms latency, far better than connecting to US or EU cloud IoT services. InfluxDB efficiently stores billions of time-series data points, Node-RED processes and routes data without code, and Grafana provides operations teams with real-time visibility and alerting for their sensor networks.
Build your IoT platform: Browse Server.HK Hong Kong VPS plans — a 4 GB plan handles 5,000 concurrent MQTT devices with InfluxDB and Grafana for most industrial IoT deployments.