This repository contains a complete example that grabs device data from IoT-Network server, stores it in a database, and then displays the data using a web-based dashboard.
You can set this up on a Docker droplet from Digital Ocean (or on a Ubuntu VM from DreamCompute, or on a "Ubuntu + Docker" VM from the Microsoft Azure store ) with minimal effort. You should set up this service to run all the time so as to capture the data from your devices; you then access the data at your convenience using a web browser.
- Introduction
- Definitions
- Security
- Assumptions
- Composition and External Ports
- Data Files
- Reuse and removal of data files
- Node-RED and Grafana Examples
- MQTTS Examples
- Setup Instructions
- Influxdb Backup and Restore
- Meta
This SETUP.md
explains the Application Server Installation and its setup. Docker and Docker Compose are used to make the installation and
setup easier.
This dashboard uses docker-compose to set up a group of five primary docker containers, backed by two auxiliary container:
-
An instance of Nginx, which proxies the other services, handles access control, gets SSL certificates from Let's Encrypt, and faces the outside world.
-
An instance of Node-RED, which processes the data from the individual nodes, and puts it into the database.
-
An instance of InfluxDB, which stores the data as time-series measurements with tags and provides backup support for the databases.
-
An instance of Grafana, which gives a web-based dashboard interface to the data.
-
An instance of Mqtt, which provides a lightweight method of carrying out messaging using a publish/subscribe model
The auxiliary containers are:
-
Postfix, which (if configured) handles outbound mail services for the containers (for now,
Influxdb
,Node-red
,cron-backup
andGrafana
). -
cron-backup, which provides backup support for the
Nginx
,Node-red
,Grafana
andMqtts
containers and pushed the backed up data to S3-compatible storage.
To make things more specific, most of the description here assumes use of Digital Ocean. However, this was tested on Ubuntu 20.04 with no issues (apart from the additional complexity of setting up apt-get
to fetch docker, and the need for a manual install of docker-compose
), on Dream Compute, and on Microsoft Azure. This will work on any Linux or Linux-like platform that supports docker
and docker-compose
. Note: Its likelihood of working with Raspberry Pi has not been tested as yet.
-
The host system is the system that runs Docker and Docker-compose.
-
A container is one of the virtual systems running under Docker on the host system.
-
A file on the host is a file present on the host system (typically not visible from within the container(s)).
-
A file in container X (or a file in the X container) is a file present in a file-system associated with container X (and typically not visible from the host system).
All communication with the Nginx server is encrypted using SSL with auto-provisioned certificates from Let's Encrypt. Grafana is the primary point of access for most users, and Grafana's login is used for that purpose. Access to Node-RED and InfluxDB is via special URLs (base/node-red/ and base/influxdb:8086/, where base is the URL served by the Nginx container). These URLs are protected via Nginx htpasswd
file entries. These entries are files in the Nginx container, and must be manually edited by an Administrator.
The initial administrator's login password for Grafana must be initialized prior to starting; it's stored in .env
. (When the Grafana container is started for the first time, it creates grafana.db
in the Grafana container, and stores
the password at that time. If grafana.db
already exists, the password in grafana/.env is ignored.)
Note:- Microsoft Azure, by default, will not open any of the ports to the outside world, so the user will need to open port 443 for SSL access to Nginx.
For concreteness, the following table assumes that base is “dashboard.example.com”.
To access | Open this link | Notes |
---|---|---|
Node-RED | https://dashboard.example.com/node-red/ | Port number is not needed and shouldn't be used. Note trailing '/' after node-red. |
InfluxDB API queries | https://dashboard.example.com/influxdb:8086/ | Port number is needed. Also note trailing '/' after influxdb. |
Grafana | https://dashboard.example.com/ | Port number is not needed and shouldn't be used. |
Mqtt | wss://dashboard.example.com/mqtts/ | Mqtt client is needed. To test it via Mqtt web portal |
This can be visualized as shown in the figure below:
-
The host system must have docker-compose version 1.9 or later (for which https://github.com/docker-compose -- be aware that apt-get normally doesn't grab this; if configured at all, it frequently gets an out-of-date version).
-
The environment variable
IOT_DASHBOARD_DATA
, if set, points to the common directory for the data. If not set, docker-compose will quit at start-up. (This is by design!)-
${IOT_DASHBOARD_DATA}node-red
will have the local Node-RED data. -
${IOT_DASHBOARD_DATA}influxdb
will have the local InfluxDB data (this should be backed-up) -
${IOT_DASHBOARD_DATA}grafana
will have all the dashboards -
${IOT_DASHBOARD_DATA}docker-nginx
will have.htpasswd
credentials folderauthdata
and Let's Encrypt certs folderletsencrypt
-
${IOT_DASHBOARD_DATA}mqtt/credentials
will have the user credentials
-
Within the containers, the individual programs use their usual ports, but these are isolated from the outside world, except as specified by docker-compose.yml
file.
In docker-compose.yml
, the following ports on the docker host are connected to the individual programs.
- Nginx runs on 80/tcp and 443/tcp. (All connections to port 80 are redirected to 443 using SSL).
The below ports are exposed only for the inter-container communication; These ports can't be accessed by host system.
-
Grafana runs on 3000/tcp.
-
Influxdb runs on 8086/tcp.
-
Node-red runs on 1880/tcp.
-
Postfix runs on 25/tcp.
Remember, if the server is running on a cloud platform like Microsoft Azure or AWS, one needs to check the firewall and confirm that the ports are open to the outside world.
When designing this collection of services, there were two choices to store the data files:
-
we could keep them inside the docker containers, or
-
we could keep them in locations on the host system.
The advantage of the former is that everything is reset when the docker images are rebuilt. The disadvantage of the former is that there is a possibility to lose all the data when it’s rebuilt. On the other hand, there's another level of indirection when keeping things on the host, as the files reside in different locations on the host and in the docker containers.
Because IoT data is generally persistent, we decided that the the extra level of indirection was required. To help find things, consult the following table. Data files are kept in the following locations by default.
Component | Data file location on host | Location in container |
---|---|---|
Node-RED | ${IOT_DASHBOARD_DATA}node-red |
/data |
InfluxDB | ${IOT_DASHBOARD_DATA}influxdb |
/var/lib/influxdb |
Grafana | ${IOT_DASHBOARD_DATA}grafana |
/var/lib/grafana |
Mqtt | ${IOT_DASHBOARD_DATA}mqtt/credentials |
/etc/mosquitto/credentials |
Nginx | ${IOT_DASHBOARD_DATA}docker-nginx/authdata |
/etc/nginx/authdata |
Let's Encrypt certificates | ${IOT_DASHBOARD_DATA}docker-nginx/letsencrypt |
/etc/letsencrypt |
As shown, one can easily change locations on the host (e.g. for testing). This can be done by setting the environment variable IOT_DASHBOARD_DATA
to the absolute path (with trailing slash) to the containing directory prior to
calling docker-compose up
. The above paths are appended to the value of IOT_DASHBOARD_DATA
. Directories are created as needed.
Normally, this is done by an appropriate setting in the .env
file.
Consider the following example:
$ grep IOT_DASHBOARD_DATA .env
IOT_DASHBOARD_DATA=/dashboard-data/
$ docker-compose up –d
In this case, the data files are created in the following locations:
Table Data Location Examples
Component | Data file location |
---|---|
Node-RED | /dashboard-data/node-red |
InfluxDB | /dashboard-data/influxdb |
Grafana | /dashboard-data/grafana |
Mqtt | /dashboard-data/ mqtt/credentials |
Nginx | /dashboard-data/docker-nginx/authdata |
Certificates | /dashboard-data/docker-nginx/letsencrypt |
Since data files on the host are not removed between runs, as long as the files are not removed between runs, the data will be preserved.
Sometimes this is inconvenient, and it is necessary to remove some or all of the data. For a variety of reasons, the data files and directories are created owned by root, so the sudo
command must be used to remove the data files. Here's an example of how to do it:
source .env
sudo rm -rf ${IOT_DASHBOARD_DATA}node-red
sudo rm -rf ${IOT_DASHBOARD_DATA}influxdb
sudo rm -rf ${IOT_DASHBOARD_DATA}Grafana
sudo rm –rf ${IOT_DASHBOARD_DATA}mqtt/credentials
This version requires that you set up Node-RED, the Influxdb database and the Grafana dashboards manually, but we hope to add a reasonable set of initial files in a future release.
There is one point that is somewhat confusing about the connections from Node-RED and Grafana to InfluxDB. Even though InfluxDB is running on the same host, it is logically running on its own virtual machine (created by docker). Because of this, Node-RED and Grafana cannot use local host
when connecting to InfluxDB. A special name is provided by docker: influxdb
. Note that there's no DNS suffix. If influxdb
is not used, Node-RED and Grafana will not be able to connect.
On the login screen, the initial user name is "admin
". The initial password is given by the value of the variable IOT_DASHBOARD_GRAFANA_ADMIN_PASSWORD
in .env
. Note that if you change the password in .env
after the first time you launch the grafana container, the admin password does not change. If you somehow lose the previous value of the admin password, and you don't have another admin login, it's very hard to recover; easiest is to remove grafana.db
and start over.
-
Set the URL (under HTTP Settings) to http://influxdb:8086.
-
Select the database.
-
Leave the username and password blank.
-
Click "Save & Test".
Mqtts can be accessed in the following ways:
Method | Hostname/Path | Port | Credentials |
---|---|---|---|
MQTT over Nginx proxy | wss://dashboard.example.com/mqtts/ | 443 | Username/Password come from mosquitto’s configuration (password_file) |
MQTT over TLS/SSL | dashboard.example.com | 8883 | Username/Password come from mosquitto’s configuration (password_file) |
WebSockets over TLS/SSL | wss://dashboard.example.com/ | 8083 | Username/Password come from mosquitto’s configuration (password_file) |
MQTT over TCP protocol (not secure) | dashboard.example.com | 1883 | Username/Password come from mosquitto’s configuration (password_file) |
Please refer to SETUP.md
for detailed set-up instructions.
Please refer to influxdb/README.md
.
-
v2.0.0 includes the following changes
- Included auxiliary backup container (
cron-backup
) for providing backup support forNginx
,Node-red
,Grafana
andMqtts
containers. - Updated the base images used in all
Dockerfile
from bionic to focal. - Added Mosquitto (MQTT client) Ubuntu ppa repository to install the latest version and fixed ownership issue when accessing Let's Encrypt certs.
- Added TLS/SSL based SMTP authentication support in
Postfix
container. - Some minor changes in the following files: Dockerfile, docker-compose.yml, setup.md and shell scripts.
- Included auxiliary backup container (
-
v1.0.0 has the following changes
-
Influxdb:
- Backup script is updated for backing up online (live) databases and to push the backup to Amazon bucket.
- Crontab was set for automatic backup.
- supports sending email for backup alerting.
-
Nginx:
- The Apache setup is migrated to Nginx.
- Proxy-ing the services like (influxdb, grafana, node-red, mqtts over proxy) was updated.
-
Node-red:
- supports data flowing via MQTT channel and HTTPS Endpoint
- supports sending email.
-
MQTTS:
- supports different connections as below:
- Mqtt Over Nginx proxy.
- Mqtt over TCP (disabled by default)
- Mqtt over TLS/SSL
- Mqtt over Websockets (WSS)
- supports different connections as below:
-
Postfix:
- Configured to Relay mails via External SMTP Auth (Tested with Gmail and Mailgun).
- Mails generated from Containers like Grafana,Influxdb and Node-red will be relayed through Postfix container.
-