Skip to content

Multi-node RTL-Config.json gets overwritten when updating application settings #217

@CosimoRicciardi

Description

@CosimoRicciardi

RTL issue: multi-node configuration gets overwritten when updating application settings

Environment

  • RTL latest master

  • Node.js v22

  • Multi-node setup:

    • LND node
    • CLN node using rune authentication
  • RTL running via systemd on Linux

Problem

In a multi-node configuration, RTL overwrites RTL-Config.json and silently removes nodes when application settings are updated from the UI.

Example:

Initial config:

"nodes": [
  {
    "index": 1,
    "lnNode": "[alias-lnd]",
    "lnImplementation": "LND"
  },
  {
    "index": 2,
    "lnNode": "[alias-cln]",
    "lnImplementation": "CLN"
  }
]

After opening Settings or changing application settings, the config gets rewritten containing only the currently selected node.

Depending on which node is active, the other node disappears from the config and from the UI.

This makes RTL unstable for mixed LND + CLN environments because the configuration file becomes progressively corrupted during normal UI usage.


Root cause

The issue appears to originate from updateApplicationSettings() inside:

/backend/controllers/shared/RTLConf.js

RTL rebuilds the configuration object from the frontend payload:

const config = common.addSecureData(req.body);
common.appConfig = JSON.parse(JSON.stringify(config));

The frontend payload only contains the currently selected node, so all other nodes are discarded when the config is rewritten.

Later:

fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');

persists the truncated configuration to disk.


Patch applied

1. Preserve existing node list

Patched updateApplicationSettings() to merge the incoming config with the previous config instead of replacing it completely.

Added:

const oldConfig = JSON.parse(fs.readFileSync(RTLConfFile, 'utf-8'));
const config = common.addSecureData(req.body);

if (oldConfig.nodes && oldConfig.nodes.length > 0 && config.nodes && config.nodes.length > 0) {
    oldConfig.nodes.forEach((oldNode) => {
        if (!config.nodes.find((newNode) => newNode.index === oldNode.index)) {
            config.nodes.push(oldNode);
        }
    });
}

Then replaced:

common.appConfig = JSON.parse(JSON.stringify(config));

with:

const mergedConfig = JSON.parse(JSON.stringify(oldConfig));

Object.keys(config).forEach((key) => {
    if (key !== 'nodes') {
        mergedConfig[key] = config[key];
    }
});

mergedConfig.nodes = oldConfig.nodes;

common.appConfig = JSON.parse(JSON.stringify(mergedConfig));

And replaced:

fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8');

with:

fs.writeFileSync(RTLConfFile, JSON.stringify(mergedConfig, null, 2), 'utf-8');

2. Preserve node settings during updates

Inside updateNodeSettings():

Original:

node.settings = req.body.settings;

Patched:

node.settings = { ...node.settings, ...req.body.settings };

This prevents partial frontend payloads from wiping existing settings fields.


Result after patches

  • Both LND and CLN nodes persist correctly
  • Node switching works
  • Application settings no longer overwrite RTL-Config.json
  • Multi-node setup remains stable across UI operations

Logs now correctly show both nodes loaded simultaneously:

"nodes":[
  {"index":1,"lnNode":"[alias-lnd]","lnImplementation":"LND"},
  {"index":2,"lnNode":"[alias-cln]","lnImplementation":"CLN"}
]

I have identified the root cause and prepared a local fix. I will open a PR shortly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions