Node-RED Environment Variables Setup¶
Overview¶
Node-RED is now configured to load environment variables for MQTT and other settings from a nodered.env file. Environment variables can come from two sources:
- Systemd Environment File (
/home/pi/.node-red/environment) - Loaded automatically by the systemd service
- Used for production deployments
-
Lower precedence for overrides
-
Dotenv File (
/home/pi/.node-red/nodered.env) - Loaded explicitly by
settings.jsviadotenvpackage - Used for development/testing and overrides
- Higher precedence - overrides systemd variables
Environment Variables¶
MQTT Configuration¶
These variables are used to configure the MQTT client connection for Node-RED flows:
# MQTT Broker Connection
MQTT_BROKER=mqtts.tagai.xyz
MQTT_PORT=8883
MQTT_DEVICE_ID=rpi-staging-1883c404a130
# MQTT mTLS Certificates (paths)
MQTT_CERT_PATH=/home/pi/.node-red/mqtt/client.crt
MQTT_KEY_PATH=/home/pi/.node-red/mqtt/client.key
MQTT_CA_PATH=/home/pi/.node-red/mqtt/ca.crt
Node-RED Configuration¶
# Node-RED Server
NODE_RED_PORT=1880
NODE_RED_ENABLE_PROJECTS=true
NODE_RED_CREDENTIAL_SECRET=tagaitechteam
NODE_RED_USER_DIR=/home/pi/.node-red
# Device Identity
DEVICE_ID=rpi-staging-1883c404a130
TZ=Europe/Vilnius
Optional: Email Configuration¶
# Email Server (for email nodes in flows)
EMAIL_SERVER=smtp.gmail.com
EMAIL_PORT=587
EMAIL_SECURE=false
EMAIL_USER=your-email@example.com
EMAIL_PASSWORD=your-app-password
How It Works¶
1. Loading Order¶
When Node-RED starts:
1. systemd loads EnvironmentFile=/home/pi/.node-red/environment
↓
2. Node-RED process starts with these variables
↓
3. settings.js executes and loads /home/pi/.node-red/nodered.env via dotenv
↓
4. Dotenv variables override any systemd variables with the same name
↓
5. settings.js reads process.env.MQTT_* variables and passes to functionGlobalContext
↓
6. Flows access via: context.global.get('mqtt').broker, etc.
2. Accessing in Flows¶
In Node-RED flows, access the MQTT configuration via function nodes:
// Get MQTT configuration from global context
const mqtt = context.global.get('mqtt');
// Access individual settings
const broker = mqtt.broker; // e.g., "mqtts.tagai.xyz"
const port = mqtt.port; // e.g., 8883
const deviceId = mqtt.deviceId; // e.g., "rpi-staging-1883c404a130"
const certPath = mqtt.certPath; // e.g., "/home/pi/.node-red/mqtt/client.crt"
const keyPath = mqtt.keyPath; // e.g., "/home/pi/.node-red/mqtt/client.key"
const caPath = mqtt.caPath; // e.g., "/home/pi/.node-red/mqtt/ca.crt"
3. systemd Integration¶
The Node-RED systemd service is configured to load the environment file:
[Service]
EnvironmentFile=-/home/pi/.node-red/environment
The - prefix means the file is optional - service starts even if file is missing.
Deployment with Ansible¶
The Ansible playbook automatically:
-
Installs dotenv package
npm install -g dotenv -
Creates systemd environment file from template
nodered-env.j2 - Deployed to:
/home/pi/.node-red/environment -
Variables: MQTT_, NODE_RED_, DEVICE_ID, TZ
-
Creates nodered.env file from template
nodered-dotenv.j2 - Deployed to:
/home/pi/.node-red/nodered.env -
Same variables as environment file
-
Verifies settings.js uses the dotenv loading code
Running Ansible Provisioning¶
# Provision single device
ansible-playbook playbooks/provision-nodered-complete.yml \
-i inventory/production/hosts.yml \
-l rpi-staging-1883c404a130
# Provision multiple devices
ansible-playbook playbooks/provision-nodered-complete.yml \
-i inventory/production/hosts.yml \
-l staging
# Force environment update (without full provisioning)
ansible-playbook playbooks/update-nodered-settings.yml \
-i inventory/production/hosts.yml \
-l rpi-staging-1883c404a130
Manual Testing¶
1. Check Environment Variables Are Loaded¶
# SSH to the Raspberry Pi
ssh pi@rpi-staging-1883c404a130.tagai.uk
# Check systemd environment file
cat ~/.node-red/environment
# Check nodered.env file
cat ~/.node-red/nodered.env
# Check what systemd loaded
systemctl show --environment nodered | grep MQTT
2. Check Node-RED Service Started Correctly¶
# Check service status
systemctl status nodered
# View service logs
journalctl -u nodered -f
# Look for nodered.env loading log message
journalctl -u nodered | grep "Loaded Node-RED env"
3. Verify in Node-RED¶
Via Node-RED function node:
// Test accessing global MQTT config
const mqtt = context.global.get('mqtt');
node.warn(JSON.stringify(mqtt, null, 2));
The debug output should show:
{
"broker": "mqtts.tagai.xyz",
"port": 8883,
"deviceId": "rpi-staging-1883c404a130",
"certPath": "/home/pi/.node-red/mqtt/client.crt",
"keyPath": "/home/pi/.node-red/mqtt/client.key",
"caPath": "/home/pi/.node-red/mqtt/ca.crt"
}
Troubleshooting¶
Environment Variables Not Loaded¶
Problem: MQTT settings not reflecting in Node-RED flows
Check: 1. Is nodered.env file present?
ls -la ~/.node-red/nodered.env
-
Does it have correct permissions?
# Should be readable by pi user ls -la ~/.node-red/nodered.env -
Did Node-RED load it? Check logs:
journalctl -u nodered | grep -i "env\|mqtt"
Solution:
- Restart Node-RED: sudo systemctl restart nodered
- Verify nodered.env file syntax (should be KEY=VALUE format)
- Check Ansible deployed it correctly
Dotenv Module Not Found¶
Error: Cannot find module 'dotenv'
Solution:
# Install globally
sudo npm install -g dotenv
# Or reinstall Node-RED with Ansible
ansible-playbook playbooks/provision-nodered-complete.yml \
-i inventory/production/hosts.yml \
-l <device>
Environment File Not Readable¶
Error: Permission denied when reading .env
Solution:
# Fix permissions
sudo chown pi:pi ~/.node-red/nodered.env
chmod 644 ~/.node-red/nodered.env
Ansible Templates¶
nodered-env.j2 (systemd environment file)¶
Location: ansible/roles/node_red/templates/nodered-env.j2
Used to generate: /home/pi/.node-red/environment
Includes: - MQTT broker and port settings - MQTT client certificate paths - Node-RED configuration - Optional email settings - Device identity and timezone
nodered-dotenv.j2 (dotenv nodered.env file)¶
Location: ansible/roles/node_red/templates/nodered-dotenv.j2
Used to generate: /home/pi/.node-red/nodered.env
Same variables as systemd environment file but in dotenv format.
Variable Reference¶
From group_vars/all/nodered.yml¶
These variables are used in Ansible templates:
node_red_port: 1880
node_red_project_encryption_key: "tagaitechteam"
mqtt_broker: "mqtts.tagai.xyz"
mqtt_broker_port: 8883
node_red_email_enabled: false
# ... other variables
Device-Specific Variables¶
From inventory host_vars:
- inventory_hostname → Device name (e.g., rpi-staging-1883c404a130)
- ansible_user → SSH user (e.g., pi)
Next Steps¶
- Optional: Add custom variables to Ansible templates for your specific needs
- Test locally on a staging device before production rollout
- Update inventory if using different MQTT broker addresses per environment
- Review flows to use
context.global.get('mqtt')instead of hardcoded values