User Tools

Site Tools


inhabitat:kaunas:day03:details

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
inhabitat:kaunas:day03:details [2026/05/28 08:38] – created jan.sonntaginhabitat:kaunas:day03:details [2026/05/28 11:51] (current) jan.sonntag
Line 14: Line 14:
 <WRAP center round tip 80%> <WRAP center round tip 80%>
 **You are not expected to copy this 1:1.** \\ **You are not expected to copy this 1:1.** \\
-The multi-instance, NGINX-fronted, automated-deployment version is overkill for a single person learning Node-RED. If you just want a local NIG stack on your own laptop, jump to [[#running_it_locally|Running it locally]] at the end of this page. The middle sections are reference material for the people maintaining the workshop server.+The multi-instance, NGINX-fronted, automated-deployment version is overkill for a single person learning Node-RED. If you just want a local NIG stack on your own laptop, jump to [[#running_a_local_nig_instance_from_the_repository|Running a local NIG instance]] at the end of this page. The middle sections are reference material for the people maintaining the workshop server.
 </WRAP> </WRAP>
  
 All scripts, configs and the Node-RED management flow shown below live in our public repository: All scripts, configs and the Node-RED management flow shown below live in our public repository:
  
-  * **Repository:** <PLACEHOLDER: link to https://github.com/EOLab-HSRW/nig-workshop-stack>+  * **Repository:** [[https://github.com/EOLab-HSRW/nig-workshop-stack|github.com/EOLab-HSRW/nig-workshop-stack]]
  
 ===== Architecture overview ===== ===== Architecture overview =====
Line 380: Line 380:
 Login uses the ''USER_NAME'' / ''USER_PASSWORD'' from the CSV. The same credentials work for both Node-RED and Grafana — this is convenient for workshops and unacceptable for anything else. Login uses the ''USER_NAME'' / ''USER_PASSWORD'' from the CSV. The same credentials work for both Node-RED and Grafana — this is convenient for workshops and unacceptable for anything else.
  
-===== Running it locally =====+===== Running a local NIG instance from the repository =====
  
-If you want to play with the stack on your own machine — which is what we recommend for actually //learning// Node-RED and Grafana — you do not need any of the aboveNo NGINX, no Certbot, no inventory script. Just Docker.+You don't need the reverse proxy to use this repo. The NGINX layer only exists to give many users clean public URLs on one server — for a single local instance you can skip it entirely and just let Docker publish the ports directly to your machineWe've run it this way and it works fine without NGINX.
  
 ==== Minimum requirements ==== ==== Minimum requirements ====
Line 388: Line 388:
   * Docker   * Docker
   * Docker Compose   * Docker Compose
 +  * Python 3 (used by ''deploy.sh'' to generate the instance files)
  
-==== A minimal local compose.yml ====+==== Steps ====
  
-Drop the following into an empty folder. It is a stripped-down version of the workshop ''compose.yml'' with all the multi-user, sub-path and reverse-proxy concerns removed:+Clone the repo and enter it:
  
-<code yaml compose.yml+<code bash
-services: +git clone https://github.com/EOLab-HSRW/nig-workshop-stack 
-  node-red: +cd nig-workshop-stack 
-    image: nodered/node-red:4.1.10-22 +</code>
-    restart: unless-stopped +
-    ports: +
-      "1880:1880" +
-    environment: +
-      TZ: "Europe/Berlin" +
-      INFLUXDB_HOST: "influxdb" +
-      INFLUXDB_PORT: "8086" +
-      INFLUXDB_DB: "db" +
-      INFLUXDB_USER: "db" +
-      INFLUXDB_USER_PASSWORD: "db" +
-    volumes: +
-      - node_red_data:/data +
-    depends_on: +
-      - influxdb+
  
-  influxdb: +Edit ''inventory.csv'' so it has a single row for yourself:
-    image: influxdb:1.12.4 +
-    restart: unless-stopped +
-    environment: +
-      INFLUXDB_DB: "db" +
-      INFLUXDB_HTTP_AUTH_ENABLED: "true" +
-      INFLUXDB_ADMIN_USER: "admin" +
-      INFLUXDB_ADMIN_PASSWORD: "admin" +
-      INFLUXDB_USER: "db" +
-      INFLUXDB_USER_PASSWORD: "db" +
-    volumes: +
-      - influxdb_data:/var/lib/influxdb+
  
-  grafana: +<code csv inventory.csv> 
-    image: grafana/grafana:13.0.1 +USER_NAME,USER_PASSWORD,NODE_RED_PORT,NODE_RED_EXTRA_PORT,GRAFANA_PORT 
-    restart: unless-stopped +me,mypassword,17601,1881,17701
-    ports: +
-      - "3000:3000" +
-    environment: +
-      GF_SECURITY_ADMIN_USER: "admin" +
-      GF_SECURITY_ADMIN_PASSWORD: "admin" +
-      GF_USERS_ALLOW_SIGN_UP: "false" +
-    volumes: +
-      - grafana_data:/var/lib/grafana +
-    depends_on: +
-      - influxdb +
- +
-volumes: +
-  node_red_data: +
-  influxdb_data: +
-  grafana_data:+
 </code> </code>
  
-Start it:+Bring it up with the deploy script (**not** raw ''docker compose'' — the script generates the bcrypt password hash Node-RED needs to start):
  
 <code bash> <code bash>
-docker compose up -d+./deploy.sh up
 </code> </code>
  
-And open:+Then open:
  
 ^ Service ^ URL ^ ^ Service ^ URL ^
-| Node-RED | http://localhost:1880 | +| Node-RED | ''http://localhost:17601/me/node-red/''
-| Grafana | http://localhost:3000 (login: ''admin'' / ''admin''+Grafana ''http://localhost:17701/me/grafana/'' |
-InfluxDB | http://localhost:8086 — only used from inside the compose network |+
  
-==== What is different from the workshop version? ====+Log in with the ''USER_NAME'' / ''USER_PASSWORD'' from your CSV. Grafana already has the InfluxDB data source wired in via provisioning, so you can start querying immediately. 
 + 
 +<WRAP center round tip 80%> 
 +The ''/me/node-red/'' and ''/me/grafana/'' sub-paths are still present locally because the containers are configured with those root paths via the generated env file. They work fine on ''localhost'' — you just type the full path. If the prefix annoys you locally, that's the one thing worth changing in ''compose.yml'' (drop ''NODE_RED_HTTP_ADMIN_ROOT'' and the Grafana sub-path vars), but it's not necessary. 
 +</WRAP> 
 + 
 +==== The "extra port": inside vs. outside the container ==== 
 + 
 +A container port and the host port you reach it on are **two different numbers**. Docker //publishes// an internal container port to a host port via the ''host:container'' mapping in ''compose.yml''. For Node-RED's extra port the relevant line is: 
 + 
 +<code yaml> 
 +ports: 
 +  - "${NODE_RED_EXTRA_PORT}:1881" 
 +</code> 
 + 
 +Read this as ''host:container''. So: 
 + 
 +  * **Inside** the container, anything you bind always listens on **1881**. That number never changes — your flows, a broker, an HTTP listener, all use ''1881'' from the container's point of view. 
 +  * **Outside**, you reach it on whatever ''NODE_RED_EXTRA_PORT'' you put in the CSV (''1881'' for the first user, ''1882'' for the second, and so on). The outside number //must// be unique per instance so two users don't fight over the same host port; the inside number stays ''1881'' for everyone because each container has its own isolated network namespace. 
 + 
 +This is exactly why the inventory needs a separate ''NODE_RED_EXTRA_PORT'' column: it's the //external// handle for a //fixed internal// port. When you configure something in Node-RED to listen on a port, use **1881** (the inside number). When you connect to it from your laptop or another machine, use the **outside** number from your CSV. 
 + 
 +==== Hosting your own MQTT broker with Node-RED Aedes ==== 
 + 
 +For testing you often want an MQTT broker without installing one separately. The [[https://flows.nodered.org/node/node-red-contrib-aedes|node-red-contrib-aedes]] node runs a full MQTT broker //inside// Node-RED itself. 
 + 
 +  - In the Node-RED editor, install ''node-red-contrib-aedes'' from the palette manager (//Menu → Manage palette → Install//). 
 +  - Drop an **aedes broker** node onto a flow and set its port to **1881** — the container-internal extra port. 
 +  - Point an **mqtt-broker** config (used by ''mqtt in'' / ''mqtt out'' nodes) at ''localhost:1881'', since to the broker node and the client nodes that all live in the same container, ''localhost:1881'' is the broker. 
 +  - To publish/subscribe from **outside** — e.g. an MQTT client on your laptop or a microcontroller on your network — connect to your host's IP on the **outside** extra port (''1881'', ''1882'', ... whatever you assigned). That's the whole reason the extra port is published. 
 + 
 +This gives every workshop user a private broker with zero extra infrastructure, reachable both internally (flows) and externally (devices). 
 + 
 +==== This setup is not hardened ==== 
 + 
 +<WRAP center round important 80%> 
 +This stack is built for **workshops and local experimentation**, not production. It reuses the same password across Node-RED, Grafana and InfluxDB, runs the end-of-life InfluxDB 1.x line, exposes ports directly, and applies no resource limits or network policies between users. 
 +</WRAP>
  
-In case you want to upgrade your local setup laterhere is what is //missing// compared to the production workshop stack, and why each piece exists there:+If you want to take any of this further than a workshopharden the images before exposing them. Good starting points:
  
-  * **No Node-RED auth.** The workshop stack runs ''adminAuth'' with a bcrypt-hashed password because the editor is reachable over the public internetLocally''localhost'' binds are usually enough+  * **Node-RED** — the official [[https://nodered.org/docs/user-guide/runtime/securing-node-red|Securing Node-RED]] guide covers admin auth, HTTPS, the editor vsruntime endpointsand running behind a proxy properly
-  * **No HTTP root prefix.** Without a reverse proxy you don't need ''/student1/node-red/''; Node-RED happily serves from ''/''+  * **Grafana** — Grafana's [[https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/|security configuration]] docs cover cookie/security settings, disabling the embedded login where SSO is available, and locking down the admin account
-  * **No Grafana sub-path or root URL.** Same reason+  * **InfluxDB** — consider moving off the unmaintained 1.x line to a supported InfluxDB release; review the relevant version's [[https://docs.influxdata.com/|security and authentication]] docs. At minimum, never reuse the user password as the admin password the way the workshop defaults do
-  * **No Grafana datasource provisioning.** You can paste the same ''influxdb.yml'' under ''./grafana/provisioning/datasources/'' and mount it to skip the "create data source" wizard — recommended once you grow tired of clicking through it. +  * **Docker** — apply the general [[https://docs.docker.com/engine/security/|Docker security]] practices and the [[https://github.com/docker/docker-bench-security|Docker Bench for Security]] checks: drop capabilities, set ''read_only'' filesystems where possible, add ''mem_limit'' / ''cpus'', run as a non-root user, and avoid publishing ports you don't actually need on the host
-  * **No bcrypt hashing dance.** No ''deploy.sh''; you run ''docker compose up -d'' directly+  * **Secrets** — replace the plain ''inventory.csv'' passwords with Docker secrets or an external secrets manager, and use unique strong passwords per service rather than one shared value.
-  * **No per-user isolation.** Everyone using your laptop shares the same stack — which is exactly what you want when "everyone" is just you.+
  
 ===== Further reading ===== ===== Further reading =====
  
   * Original lab wiki page this stack is based on: <PLACEHOLDER: link to https://wiki.eolab.de/doku.php?id=user:jan001:nigdocu:aufbau>   * Original lab wiki page this stack is based on: <PLACEHOLDER: link to https://wiki.eolab.de/doku.php?id=user:jan001:nigdocu:aufbau>
-  * Repository: <PLACEHOLDER: link to https://github.com/EOLab-HSRW/nig-workshop-stack>+  * Repository: [[https://github.com/EOLab-HSRW/nig-workshop-stack|github.com/EOLab-HSRW/nig-workshop-stack]]
   * [[https://nodered.org/docs/|Node-RED documentation]]   * [[https://nodered.org/docs/|Node-RED documentation]]
   * [[https://docs.influxdata.com/influxdb/v1/|InfluxDB 1.x documentation]]   * [[https://docs.influxdata.com/influxdb/v1/|InfluxDB 1.x documentation]]
inhabitat/kaunas/day03/details.1779950289.txt.gz · Last modified: 2026/05/28 08:38 by jan.sonntag