# Node RED v4 : Single File Executable

**URL:** <https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323>\
**Category:** Share Your Projects\
**Tags:** pkg, single-file-executable, executable, sfe\
**Created:** [6 July 2024 16:26 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323 "2024-07-06T16:26:08Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![ziga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ziga/32/98138_2.png) [@ziga](https://discourse.nodered.org/u/ziga)\
**Post date:** [23 January 2025 17:28 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/41 "2025-01-23T17:28:40Z")

</div>

Reading the github readme I was under the impression that flow can't be modified (even at runtime)

> You're tasked by your client to design a dashboard that takes input from a user, and it gets processed with your magic sauce/IP. There will be some level of code (or all of it), that you don't want to reveal or be messed with.

Perhaps this can be altered in some way, I'm not that familiar with core node-red procedures, otherwise maybe mention this in readme, so someone would not be under the same impressions and want to deploy this somewhere thinking no one can alter the flow.

Putting this aside, very cool project!

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 January 2025 17:31 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/42 "2025-01-23T17:31:13Z")

</div>

it does note it...

> If a flow is not embedded, the SFE will create a directory called `NRUserDir` on startup if it's not already been created. This allows you to deploy the executable with a modifiable flow (but note: this also allows you to view the flow code)

but yes - I should make it more clear - thanks for the feedback 👍

---

<div class="post-metadata">

**Author:** ![ziga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ziga/32/98138_2.png) [@ziga](https://discourse.nodered.org/u/ziga)\
**Post date:** [23 January 2025 17:47 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/43 "2025-01-23T17:47:28Z")

</div>

> **If a flow is not embedded** , the SFE will create a directory called `NRUserDir` on startup if it's not already been created. This allows you to deploy the executable with a modifiable flow (but note: this also allows you to view the flow code)

But I did embed the flow.

> The final executable will contain an embedded file system, which is read only. Therefore, if you do not block access to the Editor (`disableEditor` ) and try to deploy (or install Nodes) after, it will fail.

It's true I can't seem to install new nodes, but I can deploy the changes and also disabling the panel does not prevent me to add new ones or add flows - all that can be done through UI or action panel which is available.

I'm not criticizing, just seems that readme is a bit confusing.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 January 2025 17:52 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/44 "2025-01-23T17:52:39Z")

</div>

Don't worry - im all ears 😃

I guess it should re-worded as.

* * *

Providing you embed a flow, and disable the editor : `disableEditor: true` - the flow becomes _difficult_ to reverse engineer - given its embedded and the editor is fully disabled

* * *

I'm happy for a PR for any read me changes 🙂

---

<div class="post-metadata">

**Author:** ![ziga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ziga/32/98138_2.png) [@ziga](https://discourse.nodered.org/u/ziga)\
**Post date:** [23 January 2025 18:01 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/45 "2025-01-23T18:01:23Z")

</div>

> [@marcus-j-davies](#):
>
> Providing you embed a flow, and disable the editor : `disableEditor: true`

Yea I didn't set this: `disableEditor: true` - now this is the flow I was expecting!

And because I never disabled editor before in node-red I thought this was on by default, seeing those disabled panels and deploy button (that don't do anything btw except confuse people like me 😃 )

All good and confusion resolved.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 January 2025 18:05 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/46 "2025-01-23T18:05:51Z")

</div>

The recommended approach is highlighted

* * *

 ![Screenshot 2025-01-23 at 18.04.41](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/4/043d0a43f04fa57622ffee8409e5983f6720e41d.png)

* * *

But yes, I agree - should emphasise this more

---

<div class="post-metadata">

**Author:** ![KarolisL](https://avatars.discourse-cdn.com/v4/letter/k/a4c791/32.png) [@KarolisL](https://discourse.nodered.org/u/KarolisL)\
**Post date:** [23 January 2025 18:21 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/47 "2025-01-23T18:21:01Z")

</div>

Thats is completely out of my skill set, but I've tried to run this application via .bat file and then startup dashboard.

`START node-red-sfe.exe`

doesn't work. there are no installed nodes available:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/0/609138a309e826a37cc4f437550aa8b58671f63b.png)  
but when I run it by double clicking it is fine:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/e/fec01264f62a230de7a6e6d5106d5bb1d7d133ae.png)

any ideas how to run it by .bat file?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 January 2025 18:26 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/48 "2025-01-23T18:26:13Z")

</div>

I'm not a windows user...  
But I think you need to set the working directory in the bat file

Try this..

```auto
cd /d %~dp0
node-red-sfe.exe

```

I think by default, windows doesn't run the bat file, from the current directory it resides (or something like that)

---

<div class="post-metadata">

**Author:** ![ziga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ziga/32/98138_2.png) [@ziga](https://discourse.nodered.org/u/ziga)\
**Post date:** [23 January 2025 19:32 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/49 "2025-01-23T19:32:32Z")

</div>

I created a PR of what @KarolisL requested, to open browser automatically on NR-SFE start if editor is not disabled.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 January 2025 19:38 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/50 "2025-01-23T19:38:40Z")

</div>

Amazing!

I'll get it merged soon.

I want to bump `yao-pkg` also (where the magic happens) - as I think it has some fixes with later node versions under windows.

> **[GitHub - yao-pkg/pkg: Package your Node.js project into an executable](https://github.com/yao-pkg/pkg)**
>
> Package your Node.js project into an executable

---

<div class="post-metadata">

**Author:** ![ziga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ziga/32/98138_2.png) [@ziga](https://discourse.nodered.org/u/ziga)\
**Post date:** [23 January 2025 19:41 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/51 "2025-01-23T19:41:19Z")

</div>

Sure, and feel free to put it in build configuration if you think it should be optional. I didn't want to put in in `settings.js` as that is nr specific.

---

<div class="post-metadata">

**Author:** ![KarolisL](https://avatars.discourse-cdn.com/v4/letter/k/a4c791/32.png) [@KarolisL](https://discourse.nodered.org/u/KarolisL)\
**Post date:** [23 January 2025 20:09 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/52 "2025-01-23T20:09:07Z")

</div>

Hello, my initial request was to add parameter to settings.js file:

```auto
	/* Change me */
	credentialSecret: '#########################',

	/* This should be set to true, JUST BEFORE compiling to an SFE */
	/* But it will be ignored (forcibly set to false) during the development stage */
	disableEditor: false,
    autostartDashboard: false, <- new parameter to autostart dashboard

```

but your PR changes seems to be easy to modify for my needs:

```auto
 const url = `http://127.0.0.1:${nrSettings.uiPort}/dashboard`; 

```

am I right?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [23 January 2025 20:42 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/53 "2025-01-23T20:42:26Z")

</div>

I’ll get this merged tomorrow,

And will look to add the ability to auto start (along with a custom URL)

I want to try and do it without using settings.js (as that is for Node RED only)

I’ll have a think

One thought I had - if a file of “AUTOSTART” is found, it will launch the URL inside of that file

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [24 January 2025 19:35 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/54 "2025-01-24T19:35:00Z")

</div>

Ok @KarolisL

Using the contribution from @ziga.  
I have now merged some changes, with the following effect.

- if a file named `AUTOLOAD` (no file extension) is found in the same location as the executable, it will load up the URL inside of it. (regardless of `disableEditor`, or mode)
  - if begins with `/` - will append the URL to the admin endpoint (example : `/dashboard`)
  - If has an absolute URL (`http://...`) - will load up that URL.

See the table below

| Mode | disableEditor | AUTOLOAD Found | Auto Loaded URL | Editor Possible |
| --- | --- | --- | --- | --- |
| Design Time | N/A | N/A | Editor | YES |
| Run Time | TRUE/FALSE | YES | From File | IF ALLOWED |
| Run Time | TRUE/FALSE | NO | ————— | IF ALLOWED |

Have also bumped a few dependencies

Please do let me know how this gets on - I have done minimal testing.

---

<div class="post-metadata">

**Author:** ![KarolisL](https://avatars.discourse-cdn.com/v4/letter/k/a4c791/32.png) [@KarolisL](https://discourse.nodered.org/u/KarolisL)\
**Post date:** [25 January 2025 09:36 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/55 "2025-01-25T09:36:46Z")

</div>

Looks awesome,

works exactly as expected!

---

<div class="post-metadata">

**Author:** ![KarolisL](https://avatars.discourse-cdn.com/v4/letter/k/a4c791/32.png) [@KarolisL](https://discourse.nodered.org/u/KarolisL)\
**Post date:** [5 February 2025 11:44 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/56 "2025-02-05T11:44:56Z")

</div>

One more request:  
in the same manner that you have done AUTOLOAD,  
would it be possible to copy/paste external file folder that are in "Node-RED-SFE-main" directory?

If directory "files" (or whatever) exists copy it with all contents to build/dist?

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/c/7c1168c24870255df9e28678eaf33cae10fa3558.png)

=\>

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/3/93a5007bf416f074561956503ce6520022a6552f.png)

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [5 February 2025 13:16 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/57 "2025-02-05T13:16:54Z")

</div>

Hi @KarolisL

What’s the use case?  
I ask - as you can already set HTTP Static for this type of setup.

See the last point here : [GitHub - marcus-j-davies/Node-RED-SFE: A Single File Executable framework for Node-RED](https://github.com/marcus-j-davies/Node-RED-SFE?tab=readme-ov-file#current-limitations-to-do)

 ![IMG_1030](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/3/63998d6bc548c786c5bdf4c6cd194d0b2a7a24b0.png)

You can just modify the build script if you wanted to move files to the output.

---

<div class="post-metadata">

**Author:** ![KarolisL](https://avatars.discourse-cdn.com/v4/letter/k/a4c791/32.png) [@KarolisL](https://discourse.nodered.org/u/KarolisL)\
**Post date:** [5 February 2025 13:45 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/58 "2025-02-05T13:45:49Z")

</div>

Thanks for a reply, my use case is that I plan to distribute SFE with external files which engineer has to modify to his use case. These files are basically templates... I just use local filesystem

Every time I create a new build - dist folder is cleared. "files" folder is removed so I just have to copy/paste from develop environment

honestly, didn't work with httpStatic before, I though it was a way to store your images and etc, for dashboard purposes

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [5 February 2025 14:10 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/59 "2025-02-05T14:10:39Z")

</div>

Ok got it.

I’ll add the ability to move a folder called `ExternalFiles` to the dist folder?

---

<div class="post-metadata">

**Author:** ![KarolisL](https://avatars.discourse-cdn.com/v4/letter/k/a4c791/32.png) [@KarolisL](https://discourse.nodered.org/u/KarolisL)\
**Post date:** [5 February 2025 15:37 UTC](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323/60 "2025-02-05T15:37:05Z")

</div>

Looks good to me,  
I (DeepSeek) wrote a shell script

```auto
# Check if settings.js exists
if (-Not (Test-Path -Path "./settings.js")) {
    Write-Host "Run script in Node-RED-SFE-main folder"
    pause
    exit
}

# Check if node_modules folder exists
if (-Not (Test-Path -Path "./node_modules")) {
    $installNPM = Read-Host "node_modules folder not found. Can I run 'npm install'? (yes/no)"
    if ($installNPM -eq "yes") {
        npm install
    } else {
        exit
    }
}

# Provide menu options
function Show-Menu {
    Write-Host "1. npm run-script develop"
    Write-Host "2. npm run-script package"
    Write-Host "3. Exit"
}

do {
    Show-Menu
    $choice = Read-Host "Choose an option (1-3)"
    switch ($choice) {
        1 {
            npm run-script develop
        }
        2 {
            npm run-script build
            npm run-script package

            # Check if "files" folder exists and copy it to ./build/dist
            if (Test-Path -Path "./files") {
                $destination = "./build/dist"
                if (-Not (Test-Path -Path $destination)) {
                    New-Item -ItemType Directory -Path $destination | Out-Null
                }
                Copy-Item -Path "./files" -Destination $destination -Recurse -Force
                Write-Host "'files' folder copied to $destination"
            } else {
                Write-Host "'files' folder not found, skipping copy."
            }
        }
        3 {
            exit
        }
        default {
            Write-Host "Invalid choice, please select a valid option."
        }
    }
} while ($true)

```

which helps to automate things a bit. Maybe it will be useful for somebody in the future

[Previous page](https://discourse.nodered.org/t/node-red-v4-single-file-executable/89323.md?page=2)
