Skip to content

Node-RED Project Deployment Guide

Overview

This guide explains how to deploy Node-RED flows from the separate gaisro-technika-nodered Git repository to your Raspberry Pi fleet using Ansible.

Architecture

The deployment system supports two modes:

  1. Git-based deployment (recommended): Deploys Node-RED project directly from the Git repository
  2. Local file copy (fallback): Copies local Node-RED files from node-red/ directory

Quick Start

Deploy Node-RED Project to All Devices

# Deploy from main branch (default)
cd ansible
ansible-playbook playbooks/deploy-nodered-project.yml

# Deploy specific version/tag
ansible-playbook playbooks/deploy-nodered-project.yml \
  --extra-vars "node_red_project_version=v1.0.0"

# Deploy to specific device
ansible-playbook playbooks/deploy-nodered-project.yml --limit rpi-prod-1883c404a12f

# Deploy to multiple devices
ansible-playbook playbooks/deploy-nodered-project.yml --limit rpi-prod-1883c404a12f,rpi-staging-1883c404a130,rpi-dev-1883c4049f6c
# From project root
task ansible:deploy-nodered-project

# Deploy to specific device
task ansible:deploy-nodered-project LIMIT=rpi-prod-1883c404a12f

# Deploy specific version
task ansible:deploy-nodered-project VERSION=v1.0.0

Configuration

Repository Settings

Configuration is in ansible/group_vars/nodered.yml:

# Enable Git-based deployment
node_red_project_enabled: true

# Repository URL
node_red_project_repo: "https://github.com/mbTagai/gaisro-technika-nodered.git"

# Branch, tag, or commit hash
node_red_project_version: "main"

# Installation path on devices
node_red_project_path: "/home/tagai/.node-red"

Override Per Environment

Create environment-specific configurations:

# ansible/group_vars/production.yml
node_red_project_version: "v1.2.3"  # Use stable release

# ansible/group_vars/staging.yml
node_red_project_version: "develop"  # Use development branch

# ansible/group_vars/development.yml
node_red_project_version: "feature/new-mqtt-nodes"  # Use feature branch

Deployment Process

What Happens During Deployment

  1. Pre-deployment checks
  2. Validates Git repository configuration
  3. Checks device connectivity

  4. Backup existing flows

  5. Creates timestamped backup: flows.json.backup.{timestamp}

  6. Deploy from Git

  7. Clones/updates repository to device
  8. Sets correct file ownership
  9. Installs npm dependencies (if package.json changed)

  10. Restart Node-RED

  11. Gracefully restarts Node-RED service
  12. Waits for health check (up to 60 seconds)

  13. Batch processing

  14. Deploys to devices in batches (default: 10 devices)
  15. Pauses 30 seconds between batches
  16. Stops if >10% of devices fail

Rollback

If deployment fails, restore from backup:

# SSH into device
ssh tagai@rpi-prod-1883c404a12f.tagai.uk

# Stop Node-RED
sudo systemctl stop nodered

# Restore backup (use latest timestamp)
cd ~/.node-red
cp flows.json.backup.1738000000 flows.json

# Restart Node-RED
sudo systemctl start nodered

Repository Structure

Your gaisro-technika-nodered repository should contain:

gaisro-technika-nodered/
├── flows.json           # Node-RED flows
├── flows_cred.json      # Credentials (encrypted)
├── package.json         # Node-RED project metadata & dependencies
├── settings.js          # (optional) Node-RED settings
└── README.md

Important: The flows_cred.json file contains encrypted credentials. Ensure it's properly encrypted by Node-RED before committing.

Working with Versions

Deploy Stable Releases

# Tag a release in gaisro-technika-nodered repo
git tag v1.0.0
git push origin v1.0.0

# Deploy to production
ansible-playbook playbooks/deploy-nodered-project.yml \
  --extra-vars "node_red_project_version=v1.0.0" \
  --limit production

Deploy from Feature Branch

# Deploy feature branch to development devices
ansible-playbook playbooks/deploy-nodered-project.yml \
  --extra-vars "node_red_project_version=feature/mqtt-improvements" \
  --limit rpi-dev-1883c4049f6c,rpi-dev-1883c404a12f

Deploy Specific Commit

# Deploy specific commit hash
ansible-playbook playbooks/deploy-nodered-project.yml \
  --extra-vars "node_red_project_version=a1b2c3d4"

Deployment Strategies

Rolling Deployment (Default)

Deploys to devices in batches with pauses:

ansible-playbook playbooks/deploy-nodered-project.yml
  • Batch size: 10 devices
  • Pause: 30 seconds between batches
  • Max failures: 10%

All-at-Once Deployment

Deploy to all devices simultaneously (use with caution):

ansible-playbook playbooks/deploy-nodered-project.yml \
  --extra-vars "update_batch_size=100"

Canary Deployment

Test on one device first:

# Deploy to canary device
ansible-playbook playbooks/deploy-nodered-project.yml --limit rpi-prod-1883c404a12f

# Verify it works
# Then deploy to rest of fleet
ansible-playbook playbooks/deploy-nodered-project.yml --limit '!rpi-prod-1883c404a12f'

Full Stack Deployment

To deploy entire infrastructure including Node-RED project:

# Deploy everything (prerequisites, cloudflared, node-red with project, mqtt)
ansible-playbook playbooks/site.yml

# Deploy with specific Node-RED version
ansible-playbook playbooks/site.yml \
  --extra-vars "node_red_project_version=v1.0.0"

Troubleshooting

Check Deployment Status

# View Node-RED logs on device
ssh tagai@rpi-prod-1883c404a12f.tagai.uk
sudo journalctl -u nodered -f

# Check Node-RED status
sudo systemctl status nodered

# View Node-RED flows
cat ~/.node-red/flows.json | jq .

Common Issues

Git Clone Fails

Symptom: fatal: could not read Username for 'https://github.com'

Solution: If using private repository, configure Git credentials:

# ansible/group_vars/nodered.yml
node_red_project_repo: "https://{{ github_token }}@github.com/mbTagai/gaisro-technika-nodered.git"

Store github_token in Ansible Vault:

ansible-vault edit group_vars/all.yml
# Add: github_token: "ghp_yourtoken"

NPM Install Fails

Symptom: npm ERR! missing script: install

Solution: Check package.json exists and is valid:

# On device
cd ~/.node-red
cat package.json
npm install --verbose

Node-RED Won't Start

Symptom: Health check timeout

Solution: Check Node-RED logs:

ssh tagai@rpi-prod-1883c404a12f.tagai.uk
sudo journalctl -u nodered -n 50

Common causes: - Syntax error in flows.json - Missing npm dependencies - Port 1880 already in use - Invalid credentials in flows_cred.json

Debug Mode

Run playbook with verbose output:

ansible-playbook playbooks/deploy-nodered-project.yml -vvv

CI/CD Integration

GitHub Actions Example

Create .github/workflows/deploy-nodered.yml in infrastructure repo:

name: Deploy Node-RED to Fleet

on:
  repository_dispatch:
    types: [deploy-nodered]
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to deploy (branch/tag/commit)'
        required: true
        default: 'main'
      environment:
        description: 'Target environment'
        required: true
        type: choice
        options:
          - development
          - staging
          - production

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Ansible
        run: |
          pip install ansible

      - name: Deploy Node-RED Project
        run: |
          cd ansible
          ansible-playbook playbooks/deploy-nodered-project.yml \
            --limit ${{ inputs.environment }} \
            --extra-vars "node_red_project_version=${{ inputs.version }}"
        env:
          ANSIBLE_VAULT_PASSWORD: ${{ secrets.ANSIBLE_VAULT_PASSWORD }}

Trigger from Node-RED Repo

In gaisro-technika-nodered repository:

# .github/workflows/trigger-deployment.yml
name: Trigger Fleet Deployment

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  trigger:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger deployment
        uses: peter-evans/repository-dispatch@v2
        with:
          token: ${{ secrets.DEPLOYMENT_TOKEN }}
          repository: mbTagai/gaisro-technika-infra
          event-type: deploy-nodered
          client-payload: |
            {
              "version": "${{ github.ref_name }}",
              "environment": "production"
            }

Security Considerations

Credentials Management

  • Never commit unencrypted credentials
  • Use Node-RED's built-in credential encryption
  • Store sensitive variables in Ansible Vault
  • Rotate credentials regularly

SSH Access

  • Ansible connects via SSH using credentials in group_vars/all.yml (encrypted)
  • Ensure firewall allows SSH from Ansible controller
  • Consider using SSH keys instead of passwords

Git Authentication

For private repositories: - Use Personal Access Tokens (PAT) with minimal scope - Store in Ansible Vault - Rotate tokens quarterly

Best Practices

  1. Version Control Everything
  2. Tag stable releases in gaisro-technika-nodered
  3. Document breaking changes in CHANGELOG.md

  4. Test Before Production

  5. Deploy to development devices first
  6. Run integration tests
  7. Monitor for 24 hours before wider rollout

  8. Maintain Backups

  9. Automated backups are created during deployment
  10. Keep backups for 30 days minimum
  11. Test restore process quarterly

  12. Monitor Deployments

  13. Check health endpoints after deployment
  14. Monitor MQTT connectivity
  15. Review Node-RED logs for errors

  16. Document Changes

  17. Update README.md in nodered repo
  18. Document new nodes/dependencies
  19. Keep API documentation current

Support

For issues or questions: 1. Check troubleshooting section above 2. Review Node-RED logs on device 3. Check Ansible playbook output with -vvv flag 4. Review closed GitHub issues in both repositories