【问题标题】:How to store Node.js deployment settings/configuration files?如何存储 Node.js 部署设置/配置文件?
【发布时间】:2011-08-17 16:10:09
【问题描述】:

我一直在开发一些 Node 应用程序,并且一直在寻找一种存储与部署相关的设置的良好模式。在 Django 世界(我来自哪里),通常的做法是拥有一个包含标准设置(时区等)的settings.py 文件,然后是一个用于部署特定设置的local_settings.py,即。与什么数据库通信,什么 memcache 套接字,管理员的电子邮件地址等等。

我一直在寻找 Node.js 的类似模式。只是一个配置文件会很好,所以它不必与app.js 中的其他所有内容混在一起,但我发现有一种方法可以在一个不在源代码控制中的文件中拥有特定于服务器的配置很重要。同一个应用程序很可能部署在具有截然不同的设置的不同服务器上,并且必须处理合并冲突以及所有这些不是我的乐趣。

那么是否有某种框架/工具可以解决这个问题,还是每个人都只是自己拼凑一些东西?

【问题讨论】:

  • 我真的很喜欢mean.js 中的配置方式。基本上,他们将应用相关配置存储在一个单独的模块中,基于每个应用环境(用于生产、开发、测试)的不同设置,并通过应用环境变量传递特定细节,如秘密等。

标签: node.js configuration-files


【解决方案1】:

我为我的包使用package.json,为我的配置使用config.js,如下所示:

var config = {};

config.twitter = {};
config.redis = {};
config.web = {};

config.default_stuff =  ['red','green','blue','apple','yellow','orange','politics'];
config.twitter.user_name = process.env.TWITTER_USER || 'username';
config.twitter.password=  process.env.TWITTER_PASSWORD || 'password';
config.redis.uri = process.env.DUOSTACK_DB_REDIS;
config.redis.host = 'hostname';
config.redis.port = 6379;
config.web.port = process.env.WEB_PORT || 9980;

module.exports = config;

我从我的项目中加载配置:

var config = require('./config');

然后我可以从config.db_hostconfig.db_port 等访问我的东西...如果我不想在源代码管理中存储密码,我可以使用硬编码参数或存储在环境变量中的参数。

我还生成了一个package.json 并插入了一个依赖项部分:

"dependencies": {
  "cradle": "0.5.5",
  "jade": "0.10.4",
  "redis": "0.5.11",
  "socket.io": "0.6.16",
  "twitter-node": "0.0.2",
  "express": "2.2.0"
}

当我将项目克隆到本地计算机时,我运行 npm install 来安装软件包。更多关于here的信息。

项目存储在 GitHub 中,并为我的生产服务器添加了遥控器。

【讨论】:

  • 当您对 dev 和 prod 有不同的配置设置时会发生什么?
  • 我还没有,但这是一种方法。对于每个环境,在 ENV 变量中设置环境名称。然后在这个文件中,它只是 javascript.. 使用 case 或 if 语句来选择性地加载适当的变量。您甚至可以为每个 env 创建一个单独的配置子文件,并在 if 语句中,将此处的子文件重新加载到子配置 var 中,然后将该子配置 var 导出到主配置。我基本上想说的是它只是js,所以你可以有创意
  • 什么 process.env?它在哪里?以及如何设置?
  • 我在想“哇……我已经研究 node.js 几个小时了,我的应用程序已经在工作了……顺便说一句,也许我会分享我来的这段随机代码跟上”
  • 你还不能使用环境变量来存储那些密码吗?这不是这条线的用途吗:config.twitter.password= process.env.TWITTER_PASSWORD || '密码';
【解决方案2】:

很久以后,我发现了一个非常好的用于管理配置的 Node.js 模块:nconf

一个简单的例子:

var nconf = require('nconf');

// First consider commandline arguments and environment variables, respectively.
nconf.argv().env();

// Then load configuration from a designated file.
nconf.file({ file: 'config.json' });

// Provide default values for settings not provided above.
nconf.defaults({
    'http': {
        'port': 1337
    }
});

// Once this is in place, you can just use nconf.get to get your settings.
// So this would configure `myApp` to listen on port 1337 if the port
// has not been overridden by any of the three configuration inputs
// mentioned above.
myApp.listen(nconf.get('http:port'));

它还支持在Redis 中存储设置,编写配置文件,并具有相当可靠的API,并且还得到了更受尊敬的Node.js 商店之一Nodejitsu 的支持,作为@ 的一部分987654324@ 框架倡议,所以它应该是相当面向未来的。

查看nconf at Github

【讨论】:

  • 可能是一个愚蠢的问题,但我还没有看到明确的解释:我在哪里设置节点环境变量?我已经在使用 nconf,但不清楚我将在哪里设置环境变量。它在 nginx/apache 中吗?它是另一个配置文件吗?
  • 我不认为使用 .json 文件作为配置是一个好主意,因为不允许使用 cmets。
  • 这看起来很棒。如果配置文件覆盖命令行选项和环境变量,我想你会让很多 Unixheads 感到惊讶。我们习惯了以下升序:配置文件、环境变量、命令行选项。
  • @sheldonh 等到你发现布尔选项总是设置在 argv 上,因此打破了优先级...:/
  • @DanielC.Sobral 这真是太可惜了。哦,还有 LTNS! :-)
【解决方案3】:

您还可以查看 node-config,它根据 $HOST$NODE_ENV 变量(有点像 RoR)加载配置文件:documentation

这对于不同的部署设置(developmenttestproduction)非​​常有用。

【讨论】:

    【解决方案4】:

    我的解决方案相当简单:

    在 ./config/index.js 中加载环境配置

    var env = process.env.NODE_ENV || 'development'
      , cfg = require('./config.'+env);
    
    module.exports = cfg;
    

    在 ./config/config.global.js 中定义一些默认值

    var config = module.exports = {};
    
    config.env = 'development';
    config.hostname = 'dev.example.com';
    
    //mongo database
    config.mongo = {};
    config.mongo.uri = process.env.MONGO_URI || 'localhost';
    config.mongo.db = 'example_dev';
    

    覆盖 ./config/config.test.js 中的默认值

    var config = require('./config.global');
    
    config.env = 'test';
    config.hostname = 'test.example';
    config.mongo.db = 'example_test';
    
    module.exports = config;
    

    在 ./models/user.js 中使用它:

    var mongoose = require('mongoose')
    , cfg = require('../config')
    , db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
    

    在测试环境中运行您的应用:

    NODE_ENV=test node ./app.js
    

    【讨论】:

    • 我更喜欢这个。正如其他人所提到的,JSON 不是首选的存储结构,这种与全局变量的分层简单而有效
    • 我更喜欢这个而不是 nconf 的唯一原因是因为它允许 .js 格式的配置(开发、测试和产品)文件。允许我们记录每个配置选项,否则 JSON 格式是不可能的。
    • 顺便说一句,NODE_ENV 默认为“开发”。您应该改为检查“生产”。
    • 我不检查开发。我默认了。不知道为什么我会默认生产。
    • 这是最简单的解决方案。如果将节点应用部署到 Azure 应用服务,则可以在应用服务的配置设置中设置进程的环境变量,请参阅docs.microsoft.com/en-us/azure/app-service/configure-common
    【解决方案5】:

    只需用exports 做一个简单的settings.js

    exports.my_password = 'value'
    

    然后,在您的脚本中,执行 require:

    var settings = require('./settings.js');
    

    您的所有设置现在都可以通过settings 变量获得:

    settings.my_password // 'value'
    

    【讨论】:

    • @backdesk 当然,您可以设置一个秘密存储系统,该系统将加密秘密并使用 ip、一些令牌等限制访问。但归根结底,这一切都只是读取一些文件来自磁盘,无论是否加密。
    • @backdesk 例子没有问题。就是这样:一个解释具体事物的例子。
    【解决方案6】:

    您可以要求从 Node v0.5.x (referencing this answer) 开始的 JSON 文件

    config.json:

    {
        "username" : "root",
        "password" : "foot"
    }
    

    app.js:

    var config = require('./config.json');
    log_in(config.username, config.password);
    

    【讨论】:

    • 对该功能印象不深。您可以 require("./config.js") 并且您可以将 cmets 添加到我认为非常重要的配置文件以及其他花里胡哨的地方。如果您的配置只是属性并且没有代码,那么您的 require(config.js) 不会丢失任何内容,而 JSON 以 export.config = 为前缀
    • @teknopaul 你是对的,但是曾经有一个关于使用愚蠢与智能模板系统的“正确性”/可用性的大讨论告诉我:(1)你通常想要一个用于模板/选项的声明性/哑语言 (2) 重构“几乎是 PL”以仅进行模板(或配置)是一个坏主意 - 更好地重用具有已知行为的现有真实 PL。到目前为止+1用于回收JS做用户设置; -1 表示不采用声明性方法。我们已经看到一些非常复杂的配置以声明方式完成;我的直觉告诉我这是要走的路。
    • VScode 中 json 文件中的对象没有智能感知(2017 年底)。对来自 module.exports 的对象进行完全工作的智能感知。
    • @PMO1948 你可以把它放在你项目的任何地方,它只是一个文件。如果它在您的项目中更深,您可以编写整个路径:require('./path/to/config.json')。如果您希望用户编辑它,您应该切换到使用fs.readfs.write 来读取和写入文件。
    • @TinyTimZamboni require 的问题是告诉 webpack 打包它,除非你把它放在一个静态文件夹中。我认为黑客可以访问它。重点是,如果 web pack,打包它,那么您无法根据环境 dev、qa、stage、preprod 等进行自定义。
    【解决方案7】:

    除了this answer中提到的nconf modulethis answer中提到的node-config,还有node-iniparserIniReader,它们看起来是更简单的.ini配置文件解析器。

    【讨论】:

    • 无法返回 win-ini 文件...iniparser 自豪地强调他们知道如何解析配置中的部分...在 2013 年...如果您需要更深入嵌套你说[foo/bar][foo\bar]? bar.baz=42? bar/baz=42? bar\baz=42? bar:baz=42?你怎么知道42 是一个数字?它可能是全数字文本!- 折腾 XML,折腾 YAML,折腾 WIN.INI,拥抱 JSON,烦恼消失了。
    【解决方案8】:

    Convict 是另一个添加验证模式的选项。与 nconf 一样,它支持从环境变量、参数、文件和 json 对象的任意组合加载设置。

    自述文件中的示例:

    var convict = require('convict');
    var conf = convict({
      env: {
        doc: "The applicaton environment.",
        format: ["production", "development", "test"],
        default: "development",
        env: "NODE_ENV"
      },
      ip: {
        doc: "The IP address to bind.",
        format: "ipaddress",
        default: "127.0.0.1",
        env: "IP_ADDRESS",
      },
      port: {
        doc: "The port to bind.",
        format: "port",
        default: 0,
        env: "PORT"
      }
    });
    

    入门文章: Taming Configurations with node-convict

    【讨论】:

      【解决方案9】:

      我玩得有点晚了,但我在这里或其他任何地方都找不到我需要的东西,所以我自己写了一些东西。

      我对配置机制的要求如下:

      1. 支持前端。前端不能使用配置有什么意义?
      2. 支持settings-overrides.js - 看起来相同,但允许覆盖settings.js 的配置。这里的想法是在不更改代码的情况下轻松修改配置。我发现它对 saas 很有用。

      尽管我不太关心支持环境 - 将解释如何轻松地将其添加到我的解决方案中

      var publicConfiguration = {
          "title" : "Hello World"
          "demoAuthToken" : undefined, 
          "demoUserId" : undefined, 
          "errorEmail" : null // if null we will not send emails on errors. 
      
      };
      
      var privateConfiguration = {
          "port":9040,
          "adminAuthToken":undefined,
          "adminUserId":undefined
      }
      
      var meConf = null;
      try{
          meConf = require("../conf/dev/meConf");
      }catch( e ) { console.log("meConf does not exist. ignoring.. ")}
      
      
      
      
      var publicConfigurationInitialized = false;
      var privateConfigurationInitialized = false;
      
      function getPublicConfiguration(){
          if (!publicConfigurationInitialized) {
              publicConfigurationInitialized = true;
              if (meConf != null) {
                  for (var i in publicConfiguration) {
                      if (meConf.hasOwnProperty(i)) {
                          publicConfiguration[i] = meConf[i];
                      }
                  }
              }
          }
          return publicConfiguration;
      }
      
      
      function getPrivateConfiguration(){
          if ( !privateConfigurationInitialized ) {
              privateConfigurationInitialized = true;
      
              var pubConf = getPublicConfiguration();
      
              if ( pubConf != null ){
                  for ( var j in pubConf ){
                      privateConfiguration[j] = pubConf[j];
                  }
              }
              if ( meConf != null ){
                    for ( var i in meConf ){
                        privateConfiguration[i] = meConf[i];
                    }
              }
          }
          return privateConfiguration;
      
      }
      
      
      exports.sendPublicConfiguration = function( req, res ){
          var name = req.param("name") || "conf";
      
          res.send( "window." + name + " = " + JSON.stringify(getPublicConfiguration()) + ";");
      };
      
      
      var prConf = getPrivateConfiguration();
      if ( prConf != null ){
          for ( var i in prConf ){
              if ( prConf[i] === undefined ){
      
                  throw new Error("undefined configuration [" + i + "]");
              }
              exports[i] = prConf[i];
          }
      }
      
      
      return exports;
      

      说明

      • undefined 表示此属性是必需的
      • null 表示可选
      • meConf - 当前代码是针对app 下的文件。 meConf 是针对 conf/dev 的覆盖文件 - 我的 vcs 忽略了它。
      • publicConfiguration - 将从前端和后端可见。
      • privateConfiguration - 仅从后端可见。
      • sendPublicConfiguration - 将公开公共配置并将其分配给全局变量的路由。例如,下面的代码会将公共配置公开为前端的全局变量 myConf。默认情况下,它将使用全局变量名称conf

        app.get("/backend/conf", require("conf").sendPublicConfiguration);

      覆盖逻辑

      • privateConfiguration 与 publicConfiguration 合并,然后与 meConf 合并。
      • publicConfiguration 检查每个键是否有覆盖,并使用该覆盖。这样我们就不会暴露任何隐私。

      添加环境支持

      尽管我没有发现“环境支持”有用,但也许有人会。

      要添加环境支持,您需要将 meConf require 语句更改为类似这样的内容(伪代码)

      如果(环境==“生产”){ meConf = require("../conf/dev/meConf").production; }

      如果(环境==“发展”){ meConf = require("../conf/dev/meConf").development; }

      同样,您可以为每个环境创建一个文件

       meConf.development.js
       meConf.production.js
      

      并导入正确的。 其余逻辑保持不变。

      【讨论】:

      • undefined 真正表示“必需”而null 表示“可选”并不是很明显。所以黄色的垃圾桶是塑料的,蓝色的垃圾桶是废纸的?很好,但在扔垃圾之前必须阅读手册。
      • 您不必使用此约定。我觉得它很有用,我指示我的团队使用它,但您显然可以删除此功能。
      【解决方案10】:

      你们是否使用 npm 来启动脚本(环境等)?

      如果您使用.env 文件,您可以将它们包含在您的package.json 中 并使用 npm 获取/启动它们。

      例子:

      {
        "name": "server",
        "version": "0.0.1",
        "private": true,
        "scripts": {
          "start": "node test.js",
          "start-dev": "source dev.env; node test.js",
          "start-prod": "source prod.env; node test.js"
        },
        "dependencies": {
          "mysql": "*"
        }
      }
      

      然后运行 ​​npm 脚本:

      $ npm start-dev
      

      这里有描述https://gist.github.com/ericelliott/4152984 全部归功于 Eric Elliot

      【讨论】:

      • 你能解释一下什么是“来源”吗?我得到source : not found
      • @JohnnyBizzle source(或简单地说,.)是 Unix shell(Bash 等)中的内置命令,用于从给定文件中读取和执行命令,in当前的外壳。也就是说,这些命令不在子 shell 中执行。在这个例子中的效果是 prod.env 中定义的环境变量被添加到当前的 shell 中,因此,传递给这个 shell 产生的任何子进程。您似乎正在使用 Windows CMD。有关详细信息,请参阅this question
      • 值得注意 - 12 因子应用程序建议创建 dev.envprod.env,但每次部署只有一个 .env 文件。
      【解决方案11】:

      您可以将Konfig 用于特定环境的配置文件。它自动加载 json 或 yaml 配置文件,具有默认值和动态配置功能。

      来自 Konfig 存储库的示例:

      File: config/app.json
      ----------------------------
      {
          "default": {
              "port": 3000,
              "cache_assets": true,
              "secret_key": "7EHDWHD9W9UW9FBFB949394BWYFG8WE78F"
          },
      
          "development": {
              "cache_assets": false
          },
      
          "test": {
              "port": 3001
          },
      
          "staging": {
              "port": #{process.env.PORT},
              "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
          },
      
          "production": {
              "port": #{process.env.PORT},
              "secret_key": "3F8RRJR30UHERGUH8UERHGIUERHG3987GH8"
          }
      }
      

      开发中:

      > config.app.port
      3000
      

      在生产中,假设我们以$ NODE_ENV=production PORT=4567 node app.js 启动应用程序

      > config.app.port
      4567
      

      更多详情:https://github.com/vngrs/konfig

      【讨论】:

        【解决方案12】:

        我最近刚刚发布了一个小模块来加载任何类型的配置文件。 很简单,你可以在https://github.com/flesler/config-node查看它

        【讨论】:

          【解决方案13】:

          您还可以查看遵循twelve-factor app 原则的dotenv

          我曾经使用 node-config,但出于这个原因创建了 dotenv。它完全受到 ruby​​ 的 dotenv 库的启发。

          使用很简单:

          var dotenv = require('dotenv');
          dotenv.load();
          

          然后您只需创建一个 .env 文件并将您的设置放入其中,如下所示:

          S3_BUCKET=YOURS3BUCKET
          SECRET_KEY=YOURSECRETKEYGOESHERE
          OTHER_SECRET_STUFF=my_cats_middle_name
          

          那是 dotenv 对于 nodejs。

          【讨论】:

          • 或者只使用foreman run node xx.js 这也会自动读入你的 .env 文件。
          • 我是否也将这种方法用于生产?
          • @lamar 不,您将它们设置在实际服务器上的环境变量中。那是每次您部署它们时,它们都在那里,但不在源代码中。
          • @Lamar 是的,您实际上可以,作为在服务器上设置环境变量的更便携的替代方案。重要的一点是不要在您的版本控制或部署过程中包含.env 文件。
          【解决方案14】:

          对于那些访问这个旧线程的人来说,这里有一个我觉得很好的包。

          https://www.npmjs.org/package/config

          【讨论】:

            【解决方案15】:

            我刚刚使用了一个替代示例,因为我想要比典型的 .json 文件更灵活,但不希望将它抽象到需要依赖项的库中,就像这样。基本上,导出一个立即调用的函数,该函数返回一个具有我想要设置的值的对象。提供了很大的灵活性。

                 module.exports = function(){
                   switch(node_env){
                     case 'dev':
                       return
                       { var1 = 'development'};
                     }
                }();
            

            这里有一个更好的解释和完整的例子。 Using Config Files in Node.js

            【讨论】:

              【解决方案16】:

              我知道这是一篇很老的帖子。但是我想分享我的用于配置环境变量的模块,我认为这是非常灵活的解决方案。 这是模块json-configurator

              var configJson = {
                'baseUrl': 'http://test.com',
                '$prod_baseUrl': 'https://prod.com',
                'endpoints': {
                  'users': '<%= baseUrl %>/users',
                  'accounts': '<%= baseUrl %>/accounts'
                  },
                foo: 'bar',
                foobar: 'foobar',
                $prod_foo: 'foo in prod',
                $test_foo: 'foo in test',
                deep:{
                  veryDeep: {
                    publicKey: 'abc',
                    secret: 'secret',
                    $prod_secret: 'super secret'
                  }
                }
              };
              
              var config = require('json-configurator')(configJson, 'prod');
              
              console.log(config.deep.veryDeep.secret) 
              // super secret 
              
              console.log(config.endpoints.users)
              // https://prod.com/users 
              

              然后您可以使用process.env.NODE_ENV 获取您环境的所有变量。

              【讨论】:

                【解决方案17】:

                您可以使用 pconf:https://www.npmjs.com/package/pconf

                例子:

                var Config = require("pconf");
                var testConfig = new Config("testConfig");
                testConfig.onload = function(){
                
                  testConfig.setValue("test", 1);
                  testConfig.getValue("test");
                  //testConfig.saveConfig(); Not needed
                
                }
                

                【讨论】:

                  【解决方案18】:

                  在这里,我将把我的帽子扔进戒指,因为这些答案都没有解决几乎任何系统需要的所有关键组件。注意事项:

                  • 公共配置(前端可以看到)与私有配置(mograbi 做对了)。并确保它们分开存放。
                  • 像钥匙一样的秘密
                  • 默认值与特定于环境的覆盖
                  • 前端包

                  以下是我的配置方式:

                  • config.default.private.js - 在版本控制中,这些是默认配置选项,只有您的后端才能看到。
                  • config.default.public.js - 在版本控制中,这些是后端前端
                  • 可以看到的默认配置选项
                  • config.dev.private.js - 如果您需要 dev 的不同私有默认值。
                  • config.dev.public.js - 如果您需要 dev 的不同公共默认值。
                  • config.private.js - 不在版本控制中,这些是覆盖config.default.private.js 的环境特定选项
                  • config.public.js - 不在版本控制中,这些是覆盖 config.default.public.js 的环境特定选项
                  • keys/ - 每个文件存储某种不同秘密的文件夹。这也不受版本控制(密钥不应受版本控制)。

                  我使用普通的 javascript 文件进行配置,因此我拥有 javascript 语言的全部功能(包括 cmets 以及执行诸如在特定于环境的文件中加载默认配置文件以便随后可以覆盖它们的能力) .如果你想使用环境变量,你可以将它们加载到那些配置文件中(虽然我不建议使用 env vars,但出于同样的原因我不建议使用 json 文件 - 你没有编程语言的能力来构建你的配置)。

                  每个密钥位于单独文件中的原因是供安装程序使用。这允许您拥有一个安装程序,可以在机器上创建密钥并将它们存储在密钥文件夹中。如果没有这个,当您加载无法访问密钥的配置文件时,您的安装程序可能会失败。通过这种方式,您可以遍历目录并加载该文件夹中的任何关键文件,而不必担心在任何给定版本的代码中存在什么以及不存在什么。

                  由于您可能在私有配置中加载了密钥,因此您绝对不想在任何前端代码中加载您的私有配置。虽然将前端代码库与后端完全分开可能更理想,但很多时候 PITA 是一个足够大的障碍来阻止人们这样做,因此私有与公共配置。但是我做了两件事来防止在前端加载私有配置:

                  1. 我有一个单元测试,可确保我的前端包不包含我在私有配置中拥有的密钥之一。
                  2. 我的前端代码与后端代码位于不同的文件夹中,并且我有两个名为“config.js”的不同文件 - 每一端一个。对于后端,config.js 加载私有配置,对于前端,它加载公共配置。然后你总是只需要('config')而不用担心它来自哪里。

                  最后一件事:您的配置应该通过一个完全与您的任何其他前端代码分开的文件加载到浏览器中。如果你捆绑你的前端代码,公共配置应该被构建为一个完全独立的包。否则,您的配置不再是真正的配置 - 它只是您代码的一部分。配置需要能够在不同的机器上有所不同。

                  【讨论】:

                  • 我喜欢这个答案,但我仍然没有找到遇到我问题的人。我有一个使用 Google Calendar API 的应用程序,我正在使用 Travis CI,并且测试还需要测试日历的功能。但是,要使用它,我需要在我的项目中有一个credentials.json 文件,这绝对不是 VC。所以我的问题是,如何将这个文件提供给 Travis 的构建过程并让它持续到生产环境中?
                  【解决方案19】:

                  我在这里尝试了一些建议的解决方案,但对它们并不满意,所以我创建了自己的模块。它被称为mikro-config,主要区别在于它尊重配置而不是约定,因此您可以只需要该模块并开始使用它。

                  您将配置存储在纯 js 或 /config 文件夹中的 json 文件中。首先它加载default.js 文件,然后是/config 目录中的所有其他文件,然后它加载基于$NODE_ENV 变量的环境特定配置。

                  它还允许使用local.js 或特定于环境的/config/env/$NODE_ENV.local.js 覆盖此配置以进行本地开发。

                  你可以在这里看看:

                  https://www.npmjs.com/package/mikro-config

                  https://github.com/B4nan/mikro-config

                  【讨论】:

                    【解决方案20】:

                    长期以来,我曾经使用此处解决方案中提到的方法。然而,人们担心明文中的秘密的安全性。您可以在config 之上使用另一个包,以便处理安全位。

                    看看这个:https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault/

                    【讨论】:

                    • 我为什么要订阅 Azure 来为这项服务付费?为什么不使用 ansible-vault?另一件事:我认为没有人会在源存储库上发布带有明文凭据的配置文件。要么使用环境变量,要么将您的秘密数据放在具有只读权限的文件中。
                    • 如果您可以从某个第 3 方位置读取它并对其进行解码并让您的服务使用该绝密数据,那么如果黑客获得您的访问权限,他们就有可能做同样的事情计算机。这是更多的工作(需要更长的时间),但最终它并不能保护你。如果你的服务器被入侵,想象一下你上面的任何东西现在都是公开的。
                    【解决方案21】:

                    我将创建一个文件夹作为配置文件命名为config.js 稍后我将在需要的地方使用该文件,如下所示

                    config.js 示例

                    module.exports = {
                        proxyURL: 'http://url:port',
                        TWITTER: {
                            consumerkey: 'yourconsumerkey',
                            consumerSecrete: 'yourconsumersecrete'
                        },
                        GOOGLE: {
                            consumerkey: 'yourconsumerkey',
                            consumerSecrete: 'yourconsumersecrete'
                        },
                        FACEBOOK: {
                            consumerkey: 'yourconsumerkey',
                            consumerSecrete: 'yourconsumersecrete'
                        }
                    }
                    

                    如果我想在某个地方使用这个配置文件

                    我先导入如下

                    var config = require('./config');

                    我可以访问以下值

                    const oauth = OAuth({
                        consumer: {
                            key: config.TWITTER.consumerkey,
                            secret: config.TWITTER.consumerSecrete
                        },
                        signature_method: 'HMAC-SHA1',
                        hash_function(base_string, key) {
                            return crypto.createHmac('sha1', key).update(base_string).digest('base64');
                        }
                    });
                    

                    【讨论】:

                      【解决方案22】:

                      最好将 'development''production' 配置分开。

                      我使用以下方式: 这是我的 config/index.js 文件:

                      const config = {
                          dev : {
                              ip_address : '0.0.0.0',
                              port : 8080,
                              mongo :{
                                  url : "mongodb://localhost:27017/story_box_dev",
                                  options : ""
                              }
                          },
                          prod : {
                              ip_address : '0.0.0.0',
                              port : 3000,
                              mongo :{
                                  url : "mongodb://localhost:27017/story_box_prod",
                                  options : ""
                              }
                          }
                      } 
                      

                      如果需要配置,请使用以下内容:

                      const config = require('../config')[process.env.NODE_ENV];
                      

                      你可以使用你的配置对象:

                      const ip_address = config.ip_address;
                      const port = config.port;
                      

                      【讨论】:

                      • 您也可以在config/index.js文件末尾使用module.exports = config;
                      【解决方案23】:

                      只需使用npm模块config(超过300000次下载)

                      https://www.npmjs.com/package/config

                      Node-config 为您的应用部署组织分层配置。

                      它允许您定义一组默认参数,并将它们扩展为不同的部署环境(开发、质量保证、暂存、生产等)。

                      $ npm install config
                      $ mkdir config
                      $ vi config/default.json
                      
                      
                      {
                            // Customer module configs
                            "Customer": {
                              "dbConfig": {
                                "host": "localhost",
                                "port": 5984,
                                "dbName": "customers"
                              },
                              "credit": {
                                "initialLimit": 100,
                                // Set low for development
                                "initialDays": 1
                              }
                            }
                      }
                      
                      
                      
                      $ vi config/production.json
                      
                      {
                        "Customer": {
                          "dbConfig": {
                            "host": "prod-db-server"
                          },
                          "credit": {
                            "initialDays": 30
                          }
                        }
                      }
                      
                      
                      
                      $ vi index.js
                      
                      var config = require('config');
                      //...
                      var dbConfig = config.get('Customer.dbConfig');
                      db.connect(dbConfig, ...);
                      
                      if (config.has('optionalFeature.detail')) {
                        var detail = config.get('optionalFeature.detail');
                        //...
                      }
                      
                      
                      $ export NODE_ENV=production
                      $ node index.js
                      

                      【讨论】:

                        【解决方案24】:

                        这是一种受this article 启发的简洁方法。除了无处不在的lodash package,它不需要任何额外的包。此外,它允许您使用特定于环境的覆盖来管理嵌套默认值。

                        首先,在包根路径中创建一个如下所示的配置文件夹

                        package
                          |_config
                              |_ index.js
                              |_ defaults.json
                              |_ development.json
                              |_ test.json
                              |_ production.json
                        

                        这里是 index.js 文件

                        const _ = require("lodash");
                        const defaults = require("./defaults.json");
                        const envConf = require("./" + (process.env.NODE_ENV || "development") + ".json" );
                        module.exports = _.defaultsDeep(envConf, defaults);
                        

                        现在假设我们有一个这样的 defaults.json

                        {
                          "confKey1": "value1",
                          "confKey2": {
                            "confKey3": "value3",
                            "confKey4": "value4"
                          }
                        }
                        

                        和 development.json 一样

                        {
                          "confKey2": {
                            "confKey3": "value10",
                          }
                        }
                        

                        如果你这样做config = require('./config'),你会得到什么

                        {
                          "confKey1": "value1",
                          "confKey2": {
                            "confKey3": "value10",
                            "confKey4": "value4"
                          }
                        }
                        

                        请注意,除了在特定环境文件中定义的值之外,您将获得所有默认值。因此,您可以管理配置层次结构。使用defaultsDeep 确保您甚至可以拥有嵌套的默认值。

                        【讨论】:

                          【解决方案25】:
                          npm i config
                          
                          In config/default.json
                          {
                              "app": {
                                  "port": 3000
                              },
                              "db": {
                                  "port": 27017,
                                  "name": "dev_db_name"
                              }
                          }
                          
                          In config/production.json
                          {
                              "app": {
                                  "port": 4000
                              },
                              "db": {
                                  "port": 27000,
                                  "name": "prod_db_name"
                              }
                          }
                          
                          In index.js
                          
                          const config = require('config');
                          
                          let appPort = config.get('app.port');
                          console.log(`Application port: ${appPort}`);
                          
                          let dbPort = config.get('db.port');
                          console.log(`Database port: ${dbPort}`);
                          
                          let dbName = config.get('db.name');
                          console.log(`Database name: ${dbName}`);
                          
                          console.log('NODE_ENV: ' + config.util.getEnv('NODE_ENV'));
                          
                          $ node index.js
                          Application port: 3000
                          Database port: 27017
                          Database name: dev_db_name
                          NODE_ENV: development
                          
                          For production
                          $ set NODE_ENV=production
                          $ node index.js
                          Application port: 4000
                          Database port: 27000
                          Database name: prod_db_name
                          NODE_ENV: production
                          

                          【讨论】:

                          • 如果我想根据 12factorapp 要求从 ENV_VAR 更改数据库,我该怎么做?
                          • 我的意思是“数据库端口”例如
                          【解决方案26】:

                          我们如何使用 TypeScript。

                          export const loadConfig = () => {
                              const configLoadeded = configLoader.util.toObject() as any
                              Config = configLoadeded
                          }
                          
                          export interface ConfigI {
                              productName: string;
                              productId: string;
                              googleCloudApiKey: string;
                          }
                          

                          【讨论】:

                            【解决方案27】:

                            有点晚了(才 10 年),但我使用了 config.js,其结构如下:

                            const env = process.env.NODE_ENV || 'development';
                            
                            var config_temp = {
                                default:{
                                    port: 3000,
                                    mysql_host: "localhost",
                                    logging_level: 5,
                                    secret_api_key: process.env.SECRET_API_KEY
                                },
                                development: {
                                    logging_level: 10
                                },
                                production: {
                                    port: 3001,
                                    mysql_host: "not-localhost"
                                }
                            };
                            var config = {
                                ...config_temp.default, 
                                ...config_temp[env]
                            }
                            module.exports = config;
                            

                            然后我加载配置:

                            var config = require('./config');
                            var port = config.port;
                            

                            这样:

                            • env 变量的读取包含在 config.js 文件中,因此我可以避免这种丑陋:require('./config')[process.env.NODE_ENV || 'development']
                            • config.js 文件可以上传到代码的 repo 中,因为敏感变量继续使用 process.env 处理。
                            • 如果同一元素同时包含在 default:{custom_env:{ 中,则仅保留第二个。
                            • 没有专用文件夹和多个文件(如config

                            【讨论】:

                            • 在这种方法中,我们每次更改配置或在配置中添加值时都必须重新启动服务器。有没有不需要重启服务器的方法?
                            • @ADITYAKUMAR 保存到数据库,从 api 加载等属性意味着在启动时加载
                            • 那会很慢
                            【解决方案28】:

                            如今,在使用数据库时,最简单的方法是根本不处理配置文件,因为部署环境更容易设置一个单一的环境变量,例如调用它DB_CONNECTION,然后传递它根据需要提供任何其他配置数据。

                            配置数据示例:

                            const config = {
                                userIds: [1, 2, 3],
                                serviceLimit: 100,
                                // etc., configuration data of any complexity    
                            };
                            // or you can read it from a config file
                            

                            创建一个连接字符串,带有数据库驱动程序不关心的额外参数:

                            import {ConnectionString} from 'connection-string';
                            
                            const cs = new ConnectionString('postgres://localhost@dbname', {
                                user: 'user-name',
                                password: 'my-password',
                                params: {
                                    config
                                }  ​
                            });
                            

                            然后我们可以生成生成的字符串以将其存储在环境中:

                            cs.toString();
                            //=>postgres://localhost:my-password@dbname?config=%7B%22userIds%22%3A%5B1%2C2%2C3%5D%2C%22serviceLimit%22%3A100%7D
                            

                            所以你将它存储在你的环境中,比如说DB_CONNECTION,在客户端进程中你可以通过process.env.DB_CONNECTION读取它:

                            const cs = new ConnectionString(process.env.DB_CONNECTION);
                            
                            const config = JSON.parse(cs.params?.config); // parse extra configuration
                            //=> { userIds: [ 1, 2, 3 ], serviceLimit: 100 }
                            

                            这样,您将拥有连接和所需的所有额外配置,都在一个环境变量中,无需弄乱配置文件。

                            【讨论】:

                              【解决方案29】:

                              我使用Dotenv-Flow 进行配置管理。

                              这是按预期工作的。很多时候你有多个 本地、开发、登台和生产等环境。就流这些 创建自己的环境的步骤。

                              1. npm i dotenv-flow.

                              2. 创建像.env | .env.dev | .env.prod 这样的文件。

                              出于测试目的复制此内容

                              .env

                              DATABASE_HOST=global
                              DATABASE_PORT=global
                              DATABASE_USER=global
                              DATABASE_PASS=global
                              DATABASE_NAME=global
                              

                              .env.dev

                              DATABASE_NAME=dev
                              DATABASE_PASS=dev
                              

                              .env.prod

                              DATABASE_NAME=prod
                              DATABASE_PASS=prod
                              

                              现在使用这些环境变量创建一个测试文件。

                              test.js

                              console.log('database host:', process.env.DATABASE_HOST);
                              console.log('database port:', process.env.DATABASE_PORT);
                              console.log('database user:', process.env.DATABASE_USER);
                              console.log('database pass:', process.env.DATABASE_PASS);
                              console.log('database name:', process.env.DATABASE_NAME);
                              

                              现在使用这些命令来运行您的脚本。

                              node -r dotenv-flow/config test.js
                              node -r dotenv-flow/config test.js --node-env=dev
                              node -r dotenv-flow/config test.js --node-env=prod
                              

                              如果您在特定文件夹中创建这些环境变量文件,例如我在 envs 文件夹中创建了这些文件,请使用以下命令。

                              node -r dotenv-flow/config test.js --dotenv-flow-path=./envs
                              node -r dotenv-flow/config test.js --dotenv-flow-path=./envs --node-env=dev
                              node -r dotenv-flow/config test.js --dotenv-flow-path=./envs --node-env=prod
                              

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2020-10-06
                                • 1970-01-01
                                • 2015-09-25
                                • 1970-01-01
                                • 1970-01-01
                                • 2016-12-11
                                • 1970-01-01
                                相关资源
                                最近更新 更多