# Annotated settings.js

**URL:** <https://discourse.nodered.org/t/annotated-settings-js/37928>\
**Category:** Share Your Projects\
**Created:** [23 December 2020 16:06 UTC](https://discourse.nodered.org/t/annotated-settings-js/37928 "2020-12-23T16:06:16Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 December 2020 16:06 UTC](https://discourse.nodered.org/t/annotated-settings-js/37928/1 "2020-12-23T16:06:16Z")

</div>

Been meaning to share this for a while. This is a sanitised version of my settings.js file.

There are a few potential advantages over the stock version - use or abuse as you like 😃

- Annotated - using JSDoc comments rather than the originals where possible - this greatly improves readability, especially when using a decent code editor such as VScode.
- Some annotation regions also included - supporting code editors will let you collapse these regions which can make working on the file a lot easier.
- Captures the Node-RED PID and makes it available as a file and as a global variable (commented out) - useful if you want to kill or restart Node-RED from a flow.
- Increases the number of environment variables available. Really useful if you want/need to start multiple instances of Node-RED.
- Replaces references to @knolleary's home drive with generic references that should work on any platform. 😃
- Replaces all hard-coded filing system paths with cross-platform versions.
- Provides example Node and Admin middleware functions with some settings that improve security.
- Adds some global variables that may be useful - all are commented out to ensure maxumum security, add/remove/change as needed
  - PID - as mentioned above
  - All environment variables - this is convenient but might be a security issue in some environments
  - The user id and user home folder for the user that runs Node-RED - again, this might be a security issue with some environments but is otherwise quite handy.
  - The `require` function - this lets you do `const require = global.get('require')` at the top of a function node so that you can require any other installed npm modules. **WARNING** this is definitely a security issue! Don't do this if your instance of Node-RED is available across the Internet or if multiple people use it.

- The global context keys are also exposed so that you can use `global.keys()`. Again, don't do this if you are trying to secure your instance.
- Context storage is configured with the default to memory and `file` for the filing system

I will try to update this when new settings appear in Node-RED as they do from time-to-time. I do a comparison between my and the default settings.js when a new version of Node-RED is produced.

```javascript
/**
 * JK Version of Node-RED Settings file
 * @see ..\node_modules\node-red\settings.js
 * @version Node-RED v1.2.6
 **/

const path = require('path') // Node core library. path library for cross-platform file system specs
const fs = require('fs') // The `https` setting requires the `fs` module.
//const _ = require('lodash'); // lodash (improved underscore) for JS utility fns

/** Save a PID file so that Node-RED can be easily restarted even when run manually */
const pid = process.pid
console.info('PID: ', pid)
process.env.node_red_pid = pid+''
fs.readdir('.', (err, files)=>{
    if (err) throw err

    for (var i = 0, len = files.length; i < len; i++) {
        var match = files[i].match(/.*\.pid/)
        if(match !== null) fs.unlink(match[0], (err) => {
            if (err) throw err
        })
    }

    fs.writeFile(`${pid}.pid`, `${pid}`, (err) => {
        if (err) throw err
    })
})

/** Optionally display the Node.js/v8 engine heap size on startup */
// const v8 = require('v8')
// console.info(`V8 Total Heap Size: ${(v8.getHeapStatistics().total_available_size / 1024 / 1024).toFixed(2)} MB`)

module.exports = {
    /** the tcp port that the Node-RED web server is listening on */
    uiPort: process.env.PORT || 1880,

    /** By default, the Node-RED UI accepts connections on all IPv4 interfaces.
     * To listen on all IPv6 addresses, set uiHost to "::",
     * The following property can be used to listen on a specific interface. For
     * example, the following would only allow connections from the local machine.
     * This can be useful security when putting NR behind a reverse proxy on the same device.
     */
    //uiHost: process.env.HOST || '127.0.0.1',

    /** Retry time in milliseconds for MQTT connections */
    mqttReconnectTime: 15000,

    /** Retry time in milliseconds for Serial port connections */
    serialReconnectTime: 15000,

    /** Retry time in milliseconds for TCP socket connections */
    //socketReconnectTime: 10000,

    /** Timeout in milliseconds for TCP server socket connections, defaults to no timeout */
    //socketTimeout: 120000,

    /** Maximum number of messages to wait in queue while attempting to connect to TCP socket, defaults to 1000 */
    //tcpMsgQueueSize: 2000,

    /** Timeout in milliseconds for HTTP request connections - defaults to 120 seconds */
    //httpRequestTimeout: 120000,

    /** The maximum length, in characters, of any message sent to the debug sidebar tab */
    debugMaxLength: 1000,

    /** The maximum number of messages nodes will buffer internally as part of their
     * operation. This applies across a range of nodes that operate on message sequences.
     * defaults to no limit. A value of 0 also means no limit is applied.
     */
    //nodeMessageBufferMaxLength: 0,

    /** To disable the option for using local files for storing keys and certificates 
     * in the TLS configuration node, set this to true
     */
    //tlsConfigDisableLocalFiles: true,

    /** Colourise the console output of the debug node */
    debugUseColors: true,

    /** The file containing the flows. If not set, it defaults to flows_<hostname>.json */
    //flowFile: 'nrmain_flows.json',

    /** To enabled pretty-printing of the flow within the flow file, set the following
     * property to true:
     */
    flowFilePretty: true,

    /** By default, credentials are encrypted in storage using a generated key. To
     * specify your own secret, set the following property.
     * If you want to disable encryption of credentials, set this property to false.
     * Note: once you set this property, do not change it - doing so will prevent
     * node-red from being able to decrypt your existing credentials and they will be
     * lost.
     */
    credentialSecret: 'Replace me with something more random',

    /** By default, all user data is stored in a directory called `.node-red` under
     * the user's home directory. To use a different location, the following
     * property can be used
     * JK: Setting via startup command
     */
    //userDir: path.join(os.homedir(), '.node-red')',

    /** Node-RED scans the `nodes` directory in the userDir to find local node files.
     * The following property can be used to specify an additional directory to scan.
     */
    //nodesDir: path.join(os.homedir(), '.node-red', 'nodes')',

    /** By default, the Node-RED UI is available at http://localhost:1880/
     * The following property can be used to specify a different root path.
     * If set to false, this is disabled.
     * WARNING: If left unset or set to a path that user paths sit beneath,
     * any admin middleware such as the httpAdminMiddleware function
     * will also run for those user paths.
     * This can have unintended consequences.
     */
    httpAdminRoot: process.env.httpAdminRoot || '/red',

    /** Some nodes, such as HTTP In, can be used to listen for incoming http requests.
     * By default, these are served relative to '/'. The following property
     * can be used to specifiy a different root path. If set to false, this is
     * disabled.
     */
    httpNodeRoot: process.env.httpNodeRoot || '/',

    /** The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot',
     * to apply the same root to both parts. Defaults to '/'.
     */
    //httpRoot: process.env.httpRoot || '/',

    /** When httpAdminRoot is used to move the UI to a different root path, the
     * following property can be used to identify a directory of static content
     * that should be served at http://localhost:1880/.
     */
    //httpStatic: process.env.httpStatic || path.join('.', 'public'),

    /** The maximum size of HTTP request that will be accepted by the runtime api. Default: 5mb */
    //apiMaxLength: '5mb',

    /** If you installed the optional node-red-dashboard you can set it's path relative to httpRoot */
    //ui: { path: 'ui' },

    //#region ------ Securing Node-RED ------ //

    /** To password protect the Node-RED editor and admin API, the following
     * property can be used. See http://nodered.org/docs/security.html for details.
     */
    // adminAuth: {
        // type: "credentials",
        // // sessionExpiryTime: 604800, // in secs, default 7d=604800
        // default: {
        // permissions: "*"
        // },
        // users: [
        // {
        // username: "admin",
        // password: "$2a$08$wmsrXbrhacO5v15.vr/jWOk54pRcbqWdOljStdMycrnFbYF.kTctu",
        // permissions: "*"
        // },{
        // username: "reader",
        // password: "$2a$08$wmsrXbrhacO5v15.vr/jWOk54pRcbqWdOljStdMycrnFbYF.kTctu",
        // permissions: "read"
        // },
        // ],
    // },

    /** To password protect the node-defined HTTP endpoints (httpNodeRoot), or
     * the static content (httpStatic), the following properties can be used.
     * The pass field is a bcrypt hash of the password.
     * See http://nodered.org/docs/security.html#generating-the-password-hash
     */
    //httpNodeAuth: {user:'user',pass:'$2a$08$XPzmmEYTvmUI75ajrc.mheyvRKSoZAUwQYDgdmlYLUp3eP6JQrz1m'},
    //httpStaticAuth: {user:'user',pass:'$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.'},

    /** The following property can be used to enable HTTPS
     * See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener
     * for details on its contents.
     * See the comment at the top of this file on how to load the `fs` module used by
     * this setting.
     */
    //https: {
        //key: fs.readFileSync( path.join(os.homedir(), '.acme.sh', '<domain folder>', '<keyname>.key') ),
        //cert: fs.readFileSync( path.join(os.homedir(), '.acme.sh', '<domain folder>', 'fullchain.cer') )
    //},
    /** Alternatively:
        https: function() {
            return {
                key: fs.readFileSync('privkey.pem'),
                cert: fs.readFileSync('cert.pem'),
            }
        },
        OR https asynchronous function:
        https: function() {
            return Promise.resolve({
                key: fs.readFileSync('privkey.pem'),
                cert: fs.readFileSync('cert.pem'),
            })
        },
     */

    /** The following property can be used to refresh the https settings at a
     * regular time interval in hours.
     * This requires:
     * - the `https` setting to be a function that can be called to get the refreshed settings.
     * - Node.js 11 or later.
     */
    //httpsRefreshInterval : 12,

    /** The following property can be used to cause insecure HTTP connections to
     * be redirected to HTTPS.
     */
    //requireHttps: true,

    /** The following property can be used to disable the editor. The admin API
     * is not affected by this option. To disable both the editor and the admin
     * API, use either the httpRoot or httpAdminRoot properties
     */
    //disableEditor: false,

    /** The following property can be used to configure cross-origin resource sharing
     * in the HTTP nodes.
     * See https://github.com/troygoode/node-cors#configuration-options for
     * details on its contents. The following is a basic permissive set of options:
     */
    //httpNodeCors: {
        //origin: "*",
        //methods: "GET,PUT,POST,DELETE"
    //},

    /** If you need to set an http proxy please set an environment variable
     * called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system.
     * For example - http_proxy=http://myproxy.com:8080
     * (Setting it here will have no effect)
     * You may also specify no_proxy (or NO_PROXY) to supply a comma separated
     * list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk
     */

    /** The following property can be used to add a custom middleware function
     * in front of all http in nodes. This allows custom authentication to be
     * applied to all http in nodes, or any other sort of common request processing.
     * 
     * @param {Object} req The ExpressJS request object
     * @param {Object} res The ExpressJS result object
     * @param {Function} next Function that MUST be called at the end of this function so that further ExpressJS middleware functions will be chained
     */
    httpNodeMiddleware: function(req,res,next) {
        // Handle/reject the request, or pass it on to the http in node by calling next();
        // Optionally skip our rawBodyParser by setting this to true;
        //req.skipRawBodyParser = true;

        res.setHeader('x-powered-by','')

        // Help reduce risk of XSS and other attacks
        res.setHeader('X-XSS-Protection','1;mode=block')
        res.setHeader('X-Content-Type-Options','nosniff')
        //res.setHeader('X-Frame-Options','SAMEORIGIN')
        //res.setHeader('Content-Security-Policy',"script-src 'self'")
       
        next()
    },

    /** The following property can be used to add a custom middleware function
     * in front of all admin http routes. For example, to set custom http headers
     * 
     * @param {Object} req The ExpressJS request object
     * @param {Object} res The ExpressJS result object
     * @param {Function} next Function that MUST be called at the end of this function so that further ExpressJS middleware functions will be chained
     */ 
    httpAdminMiddleware: function(req,res,next) {
        // Help reduce risk of XSS and other attacks
        res.setHeader('X-XSS-Protection','1;mode=block')
        res.setHeader('X-Content-Type-Options','nosniff')
        
        // Set the X-Frame-Options header to limit where the editor can be embedded
        res.set('X-Frame-Options', 'sameorigin')

        next()
    },

    /** The following property can be used to pass custom options to the Express.js
     * server used by Node-RED. For a full list of available options, refer
     * to http://expressjs.com/en/api.html#app.settings.table
     */
    httpServerOptions: {
        // http://expressjs.com/en/api.html#trust.proxy.options.table
        // 'trust proxy': true, // t/f or subnet to trust or function, default false
        'x-powered-by': false,
    },

    /** Optional callback for webSocketNodeVerifyClient
     * @callback wsVerifyCallback
     * @param {boolean} result whether to accept the connection or not
     * @param {number} code if result is false, the HTTP error status to return
     * @param {string} reason if result is false, the HTTP reason string to return
     */
    /** The following property can be used to verify websocket connection attempts.
     * This allows, for example, the HTTP request headers to be checked to ensure
     * they include valid authentication information.
     * 
     * WARNING: Verify only works on initial socket connection. 
     * This is a weakness of websockets not Node-RED
     * 
     * @param {Object} info
     * @param {string} info.origin the value in the Origin header
     * @param {Object} info.req the HTTP request
     * @param {boolean} info.secure true if req.connection.authorized or req.connection.encrypted is set
     * @param {wsVerifyCallback} [callback] Optional. Verify the client asynchronously
     * 
     * @return {boolean} The function should return true if the connection should be accepted, false otherwise.
     */
    // webSocketNodeVerifyClient: function(info) {
    // console.log('WEBSOKCETNODEVERIFYCLIENT: ', info)
    // return true
    // },
    
    //#endregion ----- Securing Node-RED ----- //

    /** The following property can be used to seed Global Context with predefined
     * values. This allows extra node modules to be made available with the
     * Function node.
     * For example,
     * functionGlobalContext: { os:require('os') }
     * can be accessed in a function block as:
     * global.get("os")
     */
    functionGlobalContext: {
        //_pid: process.pid,
        //_env: process.env, // Pass environment vars to Node-RED
        //userid: process.env.user || process.env.username || process.env.USER,
        //userHome: process.env.home || process.env.userhome || process.env.HOME,
        //require: require, // DANGER Will Robinson!
        //_: require('lodash'),
        //wiser: require('node-drayton-wiser')(),
    },

    /** `global.keys()` returns a list of all properties set in global context.
     * This allows them to be displayed in the Context Sidebar within the editor.
     * In some circumstances it is not desirable to expose them to the editor. The
     * following property can be used to hide any property set in `functionGlobalContext`
     * from being list by `global.keys()`.
     * By default, the property is set to false to avoid accidental exposure of
     * their values. Setting this to true will cause the keys to be listed.
     */
    exportGlobalContextKeys: true,

    /** Context Storage
     * The following property can be used to enable context storage. The configuration
     * provided here will enable file-based context that flushes to disk every 30 seconds.
     * Refer to the documentation for further options: https://nodered.org/docs/api/context/
     * 
     * Default is to use 'memory' only.
     * 'memory' and 'localfilesystem' are both synchronous.
     */
    contextStorage: {
        default: {
            module:'memory',
        },
        file: {
            module: 'localfilesystem',
            // config: {
            // flushInterval: '10', // default is 30s
            // },
        },
    },

    /** The following property can be used to order the categories in the editor
     * palette. If a node's category is not in the list, the category will get
     * added to the end of the palette.
     * If not set, the following default order is used:
     */
    //paletteCategories: ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'],

    /** Configure the logging output */
    logging: {
        /** Only console logging is currently supported */
        console: {
            /** Level of logging to be recorded. Options are:
             * fatal - only those errors which make the application unusable should be recorded.
             * error - record errors which are deemed fatal for a particular request + fatal errors.
             * warn - record problems which are non fatal + errors + fatal errors.
             * info - record information about the general running of the application + warn + error + fatal errors.
             * debug - record information which is more verbose than info + info + warn + error + fatal errors.
             * trace - record very detailed logging + debug + info + warn + error + fatal errors.
             * off - turn off all logging (doesn't affect metrics or audit).
             */
            level: 'info',
            /** Whether or not to include metric events in the log output */
            metrics: false,
            /** Whether or not to include audit events in the log output */
            audit: false,
        }
    },

    /** Customising the editor
     * favicon, page title, header text, header icon, deploy button, hide user menu, customise main menu, custom css, login logo
     * @see https://github.com/node-red/node-red/wiki/Design:-Editor-Themes
     */
    editorTheme: {
        projects: {
            /** To enable the Projects feature, set this value to true */
            enabled: false,
        },
        //header: {
            //title: 'HOME',
            //image: "/absolute/path/to/header/image", // or null to remove image
            //url: 'https://localhost' // optional url to make the header text/image a link to this url
        //},
    },
}

// EOF

```

* * *

## Updates

### 2020-12-23 18:46

Amended comments and default for httpAdminRoot to reflect the comments from @kevinGodell.

---

_[View the full topic](https://discourse.nodered.org/t/annotated-settings-js/37928)._
