Deploy new flows to a remote machine

Hi, I'd like to deploy flows (.json file) to a remote machine using curl. I don't want any manual intervention to import or deploy flows on the remote machine. Could you please guide me achieve this task. Thanks in advance.

1 Like

curl uses a webaddress as input, so the .json needs to be available on a webserver, you could achieve this by creating a symbolic link to the .json.

why not use rsync instead ?

You can use the admin http api to do an HTTP Post of your flow json file to a remote Node-RED instance: https://nodered.org/docs/api/admin/methods/post/flows/

For example:

curl -vX POST http://my-remote-node-red-server.com -d @flows.json --header "Content-Type: application/json"

should do it.

One slight complication is if your flow includes any credentials stored in your flows_creds.json file. There's not quick and easy way to send that via the admin http api.

1 Like

I tried this approach, but this pops up a merge option and enables the deploy button for me to manually deploy.

Yes, that is what it is meant to do if someone is currently also editing the remote machine flows directly. But the flows are still already deployed and running in the runtime.

We also would like to (force) deploy a flow to an instance of Node-Red without triggering the manual merge. Is there any chance of putting this into the to-do-list?
Thanks,
David

We would also like to force deployment of a set of nodes to a runtime - in our case, a headless one.

Also, what happens to a running flow if a new set of flows is deployed? Am I correct in assuming that the engine is stopped and the state of an in-flight flow is indeterminate?

Thanks,
Andy

@acoulson2000 if you want to deploy flows to a headless runtime then you can do what I described in my original reply in this topic - Deploy new flows to a remote machine - #3 by knolleary

The default deployment type will stop everything and any inflight messages will be lost.

As with the editor, you can also use the modified-nodes and modified-flows deployment types that will only stop/restart the things that have changed and any unmodified flows will be left alone. All the details are in the API docs I link to in my previous reply.

When one merges only modified flows to a headless back-end, are there any merge complications? As @rnavanee pointed out, in "normal" mode, this results in a merge pop-up. Is this essentially something that is occurring in the browser client of the user who receives the merge notification - so if you are performing a merge that is something that is occurring in the front-end client, not on the back-end? And is therefore not an issue for a headless instance?

Correct.

A POST to /flows replaces the entire current flow configuration - no merging or anything like that to worry about.

It is only when there is an editor connected to the runtime where the editor needs to figure out how to merge the changes made in the runtime to any changes the user may be in the middle of making in the current editor. But all of that is done in the editor.

1 Like

As with the editor, you can also use the modified-nodes and modified-flows deployment types that will only stop/restart the things that have changed and any unmodified flows will be left alone

This does not seem to be the behavior I am seeing. I make a change to one node in one flow in the editor, make sure that the deploy widget is set to Modified Flows, and click deploy...I seee every flow stopped:

13 Feb 17:37:12 - [debug] saved flow revision: 41d63693decdf98174eab03fc6f20d45
13 Feb 17:37:12 - [info] Stopping modified flows
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : global
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : 95db39a1.5dffe8
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : 79ce107e.733c3
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : a6b92166.9ae76
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : 7a098550.0731dc
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : 85c2c10a.df7ee
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : 94fdaf7f.d981
13 Feb 17:37:12 - [debug] red/nodes/flows.stop : stopping flow : 139df320.2de23d
13 Feb 17:37:12 - [info] Stopped modified flows
13 Feb 17:37:12 - [info] Starting modified flows
13 Feb 17:37:12 - [info] Started modified flows

If you set the log level to trace, you'll see which nodes it's actually stopping in each of those flows.

What I'm saying is; Using the "Modified Flows" options, if I change just a single node in just one of 3 flows, I still see all the flows (and every node) being stopped and restarted, not just modified flows. This doesn't sound like the intended behavior.

17 Feb 11:42:21 - [debug] saved flow revision: f3d4d9c8eed1c20dcd2e206b61f2abd2
17 Feb 11:42:21 - [info] Stopping modified flows
17 Feb 11:42:21 - [debug] red/nodes/flows.stop : stopping flow : global
17 Feb 11:42:21 - [trace] [flow:global] stop flow
17 Feb 11:42:21 - [debug] red/nodes/flows.stop : stopping flow : 36d6dbef.36e2d4
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4] stop flow
17 Feb 11:42:21 - [debug] red/nodes/flows.stop : stopping flow : ba0c3047.754bb
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb] stop flow
17 Feb 11:42:21 - [debug] red/nodes/flows.stop : stopping flow : b7f7e3e6.44c13
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13] stop flow
17 Feb 11:42:21 - [info] Stopped modified flows
17 Feb 11:42:21 - [info] Starting modified flows
17 Feb 11:42:21 - [trace] [flow:global] start flow
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4] start flow
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4]  id               | type         | alias
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4]  759c6589.35cf1c  | inject       |
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4]  dfb7b8f0.770518  | debug        |
17 Feb 11:42:21 - [trace] [flow:36d6dbef.36e2d4] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb] start flow
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb]  id               | type         | alias
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb]  17990f89.ad233   | inject       |
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb]  ffa9d503.903188  | debug        |
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb]  9c492db7.9d667   | change       |
17 Feb 11:42:21 - [trace] [flow:ba0c3047.754bb] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13] start flow
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13]  id               | type         | alias
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13]  6b0f812d.43e6f   | inject       |
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13]  b1ec70da.770c7   | debug        |
17 Feb 11:42:21 - [trace] [flow:b7f7e3e6.44c13] ------------------|--------------|-----------------
17 Feb 11:42:21 - [trace] runtime event: {"id":"runtime-state","retain":true}
17 Feb 11:42:21 - [info] Started modified flows

The POST request is definitely specifying "flows" in the deployment type header:

Request URL: http://localhost:11882/flows
Request Method: POST
...
Headers:
Node-RED-API-Version: v2
Node-RED-Deployment-Type: flows

Are you basing your comments on the trace output or observed behaviour of the flows themselves?

That trace shows no nodes were stopped. Compare it with the trace output when you do a full deploy.

Sure enough, I see it now. Thanks!

Not sure if I should open new thread or hijack this one? I am trying to use the curl POST method, and hit an odd issue I think, I get a connection refused trying to post flows file to remote device.

From Linux CLI...

# curl -X POST http://pizero5.[redacted] -d @/home/pi/.node-red/flows.json --header "Content-Type: application/json"
curl: (7) Failed to connect to pizero5.[redacted] port 80: Connection refused

From test flow...

7/8/2020, 8:04:52 AMnode: Message
msg : Object
object
_msgid: "eed9711d.e6cda"
payload: "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current↵                                 Dload  Upload   Total   Spent    Left  Speed↵
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (7) Failed to connect to pizero5.dachshund-digital.org port 80: Connection refused↵"
rc: object
code: 7
message: "Command failed: curl -X POST http://pizero5.dachshund-digital.org -d @/home/pi/.node-red/flows.json --header "Content-Type: application/json"↵  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current↵                                 Dload  Upload   Total   Spent    Left  Speed↵
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (7) Failed to connect to pizero5.[redacted] port 80: Connection refused↵"

Should this not be using port 1880 to talk to the node red device correctly? Admin API off the same port number?

So when I explicitly set the port in the curl command, I no longer get an error but after restarting node red on the remote device, I don't see the new flows I believe I just pushed out?

In an exec node...

curl -X POST http://pizero5.[redacted]:1880 -d @/home/pi/.node-red/flows.json --header "Content-Type: application/json"type or paste code here

Results...

7/8/2020, 9:22:50 AMnode: Messagemsg : Object
object
_msgid: "111a69.fd90d597"
payload: string

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>

rc: object
7/8/2020, 9:22:50 AMnode: Messagemsg : Object
object
_msgid: "111a69.fd90d597"
payload: "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current↵                                 Dload  Upload   Total   Spent    Left  Speed↵
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0  173k    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  173k  100   140  100  173k    152   189k --:--:-- --:--:-- --:--:--  189k↵"
rc: object
code: 0
7/8/2020, 9:22:50 AMnode: Messagemsg : Object
object
_msgid: "111a69.fd90d597"
payload: object
code: 0

Seems the curl result was 0, but the post actually failed?

Got it figured out... but my POST looks a lot different than the original example...

curl -v -X POST http://192.168.1.135:1880/flows -H "Content-Type: application/json"  --data "@/home/pi/.node-red/flows.json"

Not sure why but I had to explicitly qualify the port, and the path to file to be pushed, the example in the thread above did not qualify these specifics. The original example below.

curl -vX POST http://my-remote-node-red-server.com -d @flows.json --header "Content-Type: application/json
1 Like