Automatic Node-Red flow deployment with Github

github-badge nodered-badge

In short

In this example we show how to use Github to deploy a Node-RED flow to a fleet of Raspberry Pis. The flow can then be managed including versioning control. The process starts by pushing the changes of your Node-RED flow to your Github repository. Then, using Github actions, the flow is placed into your file manager with the qbee API. From there on you can distribute and run it on the group of devices you have specified with file distribution.

This is a very simple Node-RED flow used in this example:

        "id": "117f088e.84eb97",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": ""
        "id": "d75ee7b0.0775c8",
        "type": "inject",
        "z": "117f088e.84eb97",
        "name": "weather",
        "props": [
                "p": "payload"
                "p": "topic",
                "vt": "str"
        "repeat": "10",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "weather",
        "payload": "very nice",
        "payloadType": "str",
        "x": 171.5,
        "y": 175,
        "wires": [
        "id": "d1e24e2f.b5a2",
        "type": "function",
        "z": "117f088e.84eb97",
        "name": "weather station",
        "func": "var payload = msg.payload;\n\nmsg.payload=\"The weather is \"+msg.payload;\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 373.5,
        "y": 175,
        "wires": [
        "id": "e7b731c2.2f7f2",
        "type": "debug",
        "z": "117f088e.84eb97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 586.5,
        "y": 174,
        "wires": []

This flows.jsonneeds to automatically be delivered to any remote embedded devices in scope.

This is the automatic workflow:

  • use git as for version control management
  • setup a Github runner (using Github actions) to build our code once a push is triggered
  • copy the new flows.json to the file manager via API calls
  • use the file distribution to upload the new file to a list of devices and to restart Node-RED

How to create a repository on Github

Check out the official documentation on how to create a repository on Github.

Once a repository is set up, we sepcify the Github secrets as shown in the following screenshot. We define the qbee login mail address as QM and the password as QP.

There we specify our username and password, as we do not want them to be exposed.

Once that is done, we create a Github actions which runs our setup script on the runners provided by Github (or you can set up your own runners). Github actions can be created as follows (we use "set up a workflow yourself")

The script we used is the following:

name: Automated Node-RED flow file distribution

    branches: [ main ]
    branches: [ main ]


    runs-on: ubuntu-latest
        FLOWNAME: flows.json  

    - uses: actions/checkout@v2

    - name: install jq
      run: |
        sudo apt-get install jq

    - name: copy to qbee file manager with jwt authentication
      run: |

        while [[ "$auth" != "true" && $i -lt 10 ]]
            echo "try number $((i++))"
            output=$(curl --request POST -sL --url '' \
          --header "Content-Type: application/json" \
          -d "{\"email\":\"${{ secrets.QM }}\",\"password\":\"${{ secrets.QP }}\"}"\
          -w "\n{\"http_code\":%{http_code}}\n")

            http_code=$(echo $output | jq -cs | jq -r '.[1].http_code')
            echo $http_code
            tokenValue=$(echo $output | jq -cs | jq -r '.[0].token')
            echo $tokenValue

            if [ "$http_code" != "$successful_status_code" ]

                echo $tokenValue
            #uncomment next line to do nothing

                apiOutput=$(curl -i --request "DELETE" -d "path=/$FLOWNAME" -H "Content-type: application/x-www-form-urlencoded" \
                   --url ''\
                   --header 'Authorization: Bearer '"$tokenValue")
                echo "API output is:\n$apiOutput"

                apiOutput=$(curl -i --request POST -H "Content-Type:multipart/form-data" -F "path=/" -F "file=@$FLOWNAME" \
                   --url ''\
                   --header 'Authorization: Bearer '"$tokenValue")
                echo "API output is:\n$apiOutput"


Comments on the yaml file

  • this action is triggered on pushes to the main branch
  • the runner is a virtual machine with an ubuntu OS as we specified ubuntu-latest
  • on that virtual machine (freshly created for you on every single run) the code from your repository is checked out using the actions/checkout@v2 option
  • In order to use the JWT authentication jq needs to be installed
  • the output is placed into the root directory of your file manager (c.f. file distribution via API)

Note that your credentials aren't revealed as we use Github secrets to encrypt them as you can see in the action output:

Finally, we distribute our files to the remote devices as usual with the file distribution.

As a "command to run" we use sudo -u pi node-red-restart or whatever command you use to restart Node-RED.

Automatic deployment

Using this workflow, every time you push your Node-RED flow changes to the repository the new flow will be replaced within the file manager. If the flow file differs from the one previously placed in the file manager, then the file distribution is triggered along with the run command that you provided. This distributes the flows to all devices in scope and restarts Node-RED.

Hence, all your edge devices are updated by a simple git push :)