Description
n8n-uno-q
n8n community nodes for the Arduino UNO Q and for Arduino Cloud, so that workflows in n8n can read sensors, drive GPIO, call I²C devices, react to async events coming from the on-board microcontroller, and — for any Arduino Cloud-connected board, not just the UNO Q — read and write Thing Properties and fire on realtime property updates.
The repo ships three npm packages:
@raasimpact/arduino-uno-q-bridge— a pure Node.js MessagePack-RPC client forarduino-router(the Go service that runs on the Q). Zero external dependencies except@msgpack/msgpack. Useful on its own for anyone writing Node.js code on a UNO Q — Express, Fastify, Bun, raw scripts.n8n-nodes-uno-q— an n8n community package that depends on the bridge and exposes four nodes: Arduino UNO Q Call (action), Arduino UNO Q Trigger (MCU → workflow events), Arduino UNO Q Respond (companion to Trigger’s deferred-response mode), and Arduino UNO Q Method (callable by n8n’s AI Agent, so an LLM can decide when to read a sensor or fire an actuator as part of reasoning).n8n-nodes-arduino-cloud— an n8n community package for the hosted Arduino Cloud story, independent of the UNO Q. Exposes two nodes: Arduino Cloud (action,usableAsTool) with Property Get / Set / GetHistory plus Property Guard + Rate Limit safety rails for AI agents, and Arduino Cloud Trigger (realtime MQTT-over-WSS subscription to property updates). Works with every Arduino Cloud-supported board (Nano 33 IoT, MKR WiFi 1010, Portenta, UNO R4 WiFi, Nano ESP32, …), not just the UNO Q. Built on the two official Arduino JS SDKs — no bespoke wire protocol.
n8n can talk to a Q locally (same host, unix socket) or remotely via one of three relay shapes. A plain socat bridge for trusted LANs (deploy/relay/); a stunnel bridge with mutual TLS for untrusted networks (deploy/relay-mtls/), with a beginner-friendly PKI wrapper under deploy/relay-mtls/pki/; and a reverse-SSH tunnel for Qs behind NAT (deploy/relay-ssh/), where the device dials out to n8n instead of n8n dialing in. The first two share the Arduino UNO Q Router credential and the Transport / Use TLS fields; the reverse-SSH variant uses a separate Arduino UNO Q SSH Relay credential.
For AI-agent workflows touching actuators, read the bridge’s Retry and idempotency section before wiring up a Method node. The idempotent checkbox decides whether the bridge auto-retries a mid-call socket drop (keeps relays from firing twice), the optional Method Guard lets you reject calls at the gate — by parameter value, time of day, or any other predicate — before they reach the MCU, and the optional Rate Limit caps how often the LLM may invoke the tool (minute/hour/day) to protect a constrained device from eager agents.
—
Install n8n on the UNO Q (same-host)
End-user flow, assuming a UNO Q out of the box (Docker preinstalled, arduino-router already running as a systemd service).
1. SSH into the Q from your PC:
ssh arduino@
2. Grab the compose file:
mkdir -p ~/n8n && cd ~/n8n
curl -fsSL -O https://raw.githubusercontent.com/raas-impact/n8n-uno-q/main/deploy/n8n/docker-compose.yml
3. Start n8n:
docker compose up -d
The first run pulls the n8n image — expect several minutes over the Q’s network before the container is up.
4. Open n8n in a browser on your PC: http://. On first launch n8n redirects to /setup — create the owner account (email + password) right there.
> The UNO Q boots n8n slowly — expect the page to throw connection errors for a minute or two after every docker compose up/restart while the container finishes initialising. Just reload.
5. Install the community node from the UI: Settings → Community Nodes → Install a community node → type n8n-nodes-uno-q → Install. n8n pulls the package (and the bridge as a transitive dependency) from npm and persists it in the n8n_data volume.
6. Create an Arduino UNO Q Router credential: Settings → Credentials → New → Arduino UNO Q Router. Leave Transport set to Unix Socket (local) and keep the default /var/run/arduino-router.sock. Test Connection should return Connected — arduino-router .
Done. The Arduino UNO Q Call, Arduino UNO Q Trigger, Arduino UNO Q Respond, and Arduino UNO Q Method nodes are now available in the node picker (search “Arduino” or “UNO Q”). Each node has a Credential field — assign the one you just created.
Updates:
docker compose pull && docker compose up -d on the Q.—
Run n8n on a different machine (remote over TCP)
When n8n runs on your laptop, home server, or any box that isn’t the Q, the arduino-router unix socket isn’t reachable. A relay container on the Q bridges the gap: it mounts the router socket and exposes it as a TCP endpoint n8n can connect to.
Pick one of three flavours depending on the network shape and whether the Q has a public IP:
| Variant | When | Auth + encryption | Direction |
|—|—|—|—|
| A — plain socat | Trusted LAN. Home WiFi behind a router you control. | None — wire-level plaintext. | n8n → Q (TCP) |
| B — reverse SSH | Q behind NAT, no public IP, no port forwarding. The most common home/branch-office shape. | SSH user-cert PKI (two CAs). The Q dials out; n8n’s auth callback verifies the cert before accepting the tunnel. | Q → n8n (outbound only) |
| C — stunnel + mTLS | Q has a routable address but the path between is untrusted (mixed-tenant networks, internet path). | Mutual TLS — the relay only accepts clients presenting a certificate signed by your local CA. | n8n → Q (TCP) |
Each has its own README with install / uninstall commands; quick pointers follow.
Variant A — plain socat (trusted LAN)
Two paths depending on whether you’ve cloned this repo:
Cloned repo (recommended if you’re already developing against it):
./deploy/relay/install.sh --host arduino@
(Or set UNOQ_HOST=arduino@ once in your environment and call ./deploy/relay/install.sh without the flag.)
The installer rsyncs the three files to the Q, runs docker compose up -d, and prints verification commands. See deploy/relay/README.md for env-var overrides and the uninstall.
Zero-clone (just curl the three files):
ssh arduino@
mkdir -p ~/relay && cd ~/relay
curl -fsSL -O https://raw.githubusercontent.com/raas-impact/n8n-uno-q/main/deploy/relay/q/docker-compose.yml
curl -fsSL -O https://raw.githubusercontent.com/raas-impact/n8n-uno-q/main/deploy/relay/q/Dockerfile
curl -fsSL -O https://raw.githubusercontent.com/raas-impact/n8n-uno-q/main/deploy/relay/q/entrypoint.sh
chmod +x entrypoint.sh
docker compose up -d
The relay listens on TCP port 5775 bound to 0.0.0.0 by default. Override via env:
UNOQRELAYBIND=127.0.0.1 — loopback only; consume via an SSH reverse tunnel.UNOQRELAYBIND=192.168.1.42 — bind to a specific NIC.UNOQRELAYPORT=6000 — pick a different port.Variant B — reverse SSH (Q behind NAT)
The Q dials out to your n8n host; n8n reaches the Q through that established channel. No public IP or port-forwarding on the Q’s network — only outbound SSH.
The n8n side is not a separate container — the SSH server runs inside the n8n process itself (singleton on globalThis, same pattern as BridgeManager). You make a TCP port reachable on the n8n host, paste the host bundle into a credential, and you’re done.
One time: create the two CAs (user CA signs device certs, host CA signs the n8n host cert).
./deploy/relay-ssh/pki/pki setupPer n8n endpoint: issue a host cert. The hostname must be reachable from each Q.
./deploy/relay-ssh/pki/pki add n8n laptop --hostname n8n.example.comPer Q: issue a user cert (KeyID = the routing key on the n8n side).
./deploy/relay-ssh/pki/pki add device kitchenDeploy the autossh container + device bundle to the Q.
./deploy/relay-ssh/install.sh --device kitchen --n8n-host n8n.example.com --host arduino@
The Q’s autossh container has no exposed ports — it’s outbound-only. On the n8n host, make TCP 2222 (or whatever Listen port you set in the credential) reachable from wherever the Qs sit, then paste the contents of deploy/relay-ssh/pki/out/n8n/laptop/{sshhosted25519key,sshhosted25519key-cert.pub,user_ca.pub} into the n8n credential and set Device nickname to kitchen.
The relay-ssh README and n8n-server notes walk through reachability options and the credential paste flow. The PKI README covers cert renewal and the revoked_serials flow.
Variant C — stunnel + mTLS (untrusted network)
mTLS-authenticated; every client presents a certificate the relay checks against your CA. Requires the repo cloned locally for the PKI wrapper.
One time: create a home CA.
./deploy/relay-mtls/pki/pki setupPer Q: issue a server cert.
./deploy/relay-mtls/pki/pki add device kitchenPer n8n instance: issue a client cert.
./deploy/relay-mtls/pki/pki add n8n laptopDeploy the relay + device cert to the Q.
./deploy/relay-mtls/install.sh --device kitchen --host arduino@
The PKI README walks through every step, including hostname/IP options, troubleshooting, and when to consider step-ca for larger fleets. The relay-mtls README covers install/uninstall details and common failure modes.
In n8n
For Variants A and C, create an Arduino UNO Q Router credential with Transport = TCP, Host = the Q’s hostname or IP, Port = 5775.
deploy/relay-mtls/pki/out/n8n//ca.pem , client.pem, client.key into the three PEM fields. Test Connection runs the full TLS handshake plus $/version.For Variant B (reverse SSH), create an Arduino UNO Q SSH Relay credential instead. Set Device nickname = (matching ./pki add device ), Listen port = 2222, then paste sshhosted25519key, sshhosted25519key-cert.pub, and user_ca.pub from deploy/relay-ssh/pki/out/n8n/. Test Connection looks up the device in the in-process registry and calls $/version through the tunnel.
From then on the nodes behave exactly like in the same-host setup — just assign the credential.
—
Multiple Qs
Define one credential per Q (Kitchen Q, Garage Q, …) and assign a different one to each node in a workflow. A workflow that reads a temperature sensor on the kitchen Q and fires a fan relay on the garage Q is two nodes, one credential each — no other coordination needed.
Credentials can mix freely: one unix-socket credential for a local Q and several TCP credentials for remote Qs in the same workflow.
—
Advertised host for AI Chat and webhooks
The sample compose file defaults N8NHOST / WEBHOOKURL to linucs.local, the hostname used during development of this package. If your Q answers on a different hostname or an IP, override it before bringing n8n up — otherwise the built-in AI Chat panel (and any Webhook/Chat Trigger node) will advertise an unreachable URL to the browser and fail with “Failed to receive response” without running any nodes.
Option A — shell env, one-off
N8NHOST=myq.local WEBHOOKURL=http://myq.local:5678/ docker compose up -dOption B — persist via .env next to docker-compose.yml
cat > .env <
The hostname you set must be the one your browser uses to reach n8n — not the container's internal name.
---
Development
For contributors and anyone modifying the packages. Requires Node ≥ 20 on your dev machine and a UNO Q reachable over SSH.
First-time setup
git clone https://github.com/raas-impact/n8n-uno-q.git
cd n8n-uno-q
npm install
npm run build
Dev loop
deploy/sync.sh builds, rsyncs packages/*/dist into ~/n8n/custom/packages/ on the Q, and reloads n8n with a dev-only compose override that bind-mounts that folder. No image rebuild, no npm publish needed.
./deploy/sync.sh
Override the target via env vars (defaults shown):
UNOQHOST=arduino@linucs.local UNOQBASE=/home/arduino ./deploy/sync.sh
Unit tests
npm run test # everything
npm run test -w packages/bridge
npx vitest run packages/bridge/test/bridge.test.ts
Integration tests (require the real UNO Q)
The bridge's integration suite runs once per transport configured via env vars; any combination of UNOQSOCKET, UNOQTCPHOST+UNOQTCPPORT, and UNOQTLS_* can be set in one command to exercise all three in one run. The suite is skipped when none are set. Node never runs on the Q itself — tunnel from your PC.
Unix-socket path — in a separate terminal, leave the tunnel running:
rm -f /tmp/arduino-router.sock
ssh -N -L /tmp/arduino-router.sock:/var/run/arduino-router.sock arduino@
Then in your working terminal:
UNOQ_SOCKET=/tmp/arduino-router.sock npm run test:integration -w packages/bridge
TCP path (Variant A relay running on the Q) — forward the TCP port instead:
ssh -N -L 5775:localhost:5775 arduino@
Then:
UNOQTCPHOST=127.0.0.1 UNOQTCPPORT=5775 npm run test:integration -w packages/bridge
TLS path (Variant C relay running on the Q) — no tunnel, n8n connects directly. UNOQTLSHOST must match what the server cert was issued for (usually ; loopback won't work unless the cert's SAN covers 127.0.0.1):
UNOQTLSHOST=.local UNOQTLSPORT=5775
UNOQTLSCA=deploy/relay-mtls/pki/out/n8n//ca.pem
UNOQTLSCERT=deploy/relay-mtls/pki/out/n8n//client.pem
UNOQTLSKEY=deploy/relay-mtls/pki/out/n8n//client.key
npm run test:integration -w packages/bridge
Some tests in packages/bridge/test/integration.test.ts additionally require the sketches/integration-test.ino firmware flashed on the board. The sketch depends on these Arduino libraries — install them via the IDE's Library Manager before flashing:
Arduino_RouterBridge (by Arduino) — MsgPack-RPC bridge to arduino-router.ArduinoLEDMatrix (by Arduino) — drives the on-board 8×13 LED matrix.ArduinoJson (by Benoît Blanchon) — used by printBridgeReply() to render any RPC return type as JSON. Note: this is not the similarly named Arduino_JSON library.---
Repo layout
packages/bridge → @raasimpact/arduino-uno-q-bridge (Node ↔ arduino-router)
packages/n8n-nodes → n8n-nodes-uno-q (UNO Q community nodes)
packages/n8n-nodes-arduino-cloud → n8n-nodes-arduino-cloud (Arduino Cloud community nodes)
deploy/n8n/ → docker-compose (prod base + dev override) for n8n on the Q
deploy/relay/ → Variant A: plain socat TCP-to-unix-socket relay
q/ → container assets shipped to the Q (Dockerfile, compose, entrypoint)
deploy/relay-mtls/ → Variant C: stunnel + mTLS relay
q/ → container assets shipped to the Q (Dockerfile, compose, stunnel.conf, certs/)
pki/ → openssl wrapper that issues the mTLS certs (PC-only)
deploy/relay-ssh/ → Variant B: reverse-SSH relay (Q dials out to n8n)
q/ → container assets shipped to the Q (Dockerfile, compose, autossh entrypoint, certs/)
pki/ → ssh-keygen wrapper that issues user/host certs (two-CA, PC-only)
n8n-server/ → notes for the n8n side (listen-port reachability, credential paste flow)
deploy/lib/ → shared install-script helpers (SSH multiplexing)
deploy/sync.sh → build + rsync + reload helper for the n8n custom-nodes bundle
experiments/ → raw-socket smoke tests against a real Q
sketches/ → MCU firmware used by integration tests
---
License
MIT.