Comment stocker le noeud.paramètres de déploiement js / fichiers de configuration?

j'ai travaillé sur quelques applications nodales, et j'ai été à la recherche d'un bon modèle de stockage des paramètres liés au déploiement. Dans le monde Django (d'où je viens), la pratique courante serait d'avoir un fichier settings.py contenant les réglages standard (fuseau horaire, etc.), puis un fichier local_settings.py pour les réglages spécifiques au déploiement, c'est-à-dire. à quelle base de données parler, à quelle socket memcache, adresse e-mail pour les administrateurs et ainsi de suite.

je cherchais similaire les modèles de Nœud. Juste un fichier de configuration serait bien, donc il n'a pas à être bloqué avec tout le reste dans app.js , mais je trouve qu'il est important d'avoir un moyen d'avoir une configuration spécifique au serveur dans un fichier qui n'est pas sous contrôle source. La même application pourrait bien être déployée sur différents serveurs avec des paramètres très différents, et avoir à faire face à des conflits de fusion et tout ce qui n'est pas mon idée de plaisir.

donc il y a une sorte de cadre/outil pour cela, ou fait tout le monde pirate quelque chose ensemble?

574
demandé sur mikl 2011-05-03 16:09:07

23 réponses

j'utilise un package.json pour mes paquets et un config.js pour ma configuration, qui ressemble à:

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;

je charge la configuration de mon projet:

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

et ensuite je peux accéder à mes affaires à partir de config.db_host , config.db_port , etc... Cela me permet soit d'utiliser des paramètres codés en dur, ou des paramètres stockés dans des variables environnementales si Je ne veux pas stocker les mots de passe dans le contrôle source.

j'ai aussi générez un package.json et insérez une section de dépendances:

"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"
}

quand j'ai cloné le projet sur ma machine locale, j'ai lancé npm install pour installer les paquets. Plus d'informations sur ce ici .

le projet est stocké dans GitHub, avec des télécommandes ajoutées pour mon serveur de production.

707
répondu noli 2017-06-17 12:05:41

vous pouvez demander des fichiers JSON à partir du noeud v0.5.x ( faisant référence à cette réponse )

config.json:

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

app.js:

var config = require('./config.json');
log_in(config.username, config.password);
221
répondu TinyTimZamboni 2017-05-23 12:26:36

beaucoup plus tard, j'ai trouvé un assez bon noeud.module js pour la gestion de la configuration: nconf .

un exemple simple:

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'));

il supporte également le stockage des paramètres dans Redis , l'écriture des fichiers de configuration, et dispose d'une API assez solide, et est également soutenu par l'un des Noeuds les plus respectés.js shops, Nodejitsu , dans le cadre du Flatiron il s'agit d'une initiative-cadre, donc elle devrait être assez résistante à l'avenir.

Check out nconf at github .

188
répondu mikl 2012-01-25 08:48:35

ma solution est assez simple:

Charger l'environnement de config ./config / index.js

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

module.exports = cfg;

définit quelques valeurs par défaut ./config / config.mondial.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';

outrepasse les valeurs par défaut./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);

lancer votre application dans un environnement de test:

NODE_ENV=test node ./app.js

Ceci est expliqué plus en détail ici: http://www.chovy.com/node-js/managing-config-variables-inside-a-node-js-application /

84
répondu chovy 2012-11-26 23:20:00

vous pourriez aussi regarder à dotenv qui suit les principes d'un douze facteurs app .

j'utilisais node-config, mais j'ai créé dotenv pour cette raison. Il a été entièrement inspiré par la bibliothèque dotenv de ruby.

L'Usage est assez facile:

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

alors vous créez juste un .env fichier et de mettre vos paramètres comme:

S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
OTHER_SECRET_STUFF=my_cats_middle_name

C'est dotenv pour nodejs.

30
répondu scottmotte 2014-04-30 00:59:53

vous utilisez npm pour démarrer vos scripts (env etc) ?

si vous utilisez les fichiers .env vous pouvez les inclure dans votre package.json et utiliser npm à la source/start.

exemple:

{
  "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": "*"
  }
}

lancez ensuite les scripts npm:

$ npm start-dev

décrites ici https://gist.github.com/ericelliott/4152984 Tout le crédit à Eric Elliot

29
répondu lxx 2016-01-27 16:28:52

vous pouvez aussi regarder node-config qui charge le fichier de configuration en fonction de $HOST et $NODE_ENV variable (un peu comme RoR): documentation .

cela peut être très utile pour différents réglages de déploiement ( development , test ou production ).

23
répondu ngryman 2012-04-23 17:54:05

il suffit de faire une simple settings.js avec exports :

exports.my_password = 'value'

ensuite, dans votre script, faites un require :

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

tous vos paramètres maintenant seront disponibles via settings variable:

settings.my_password // 'value'
20
répondu Vanuan 2013-01-27 16:47:57

Convict est une autre option qui ajoute un schéma pour la validation. Comme nconf, il prend en charge les paramètres de chargement à partir de n'importe quelle combinaison de variables d'environnement, d'arguments, de fichiers et d'objets json.

exemple tiré du README:

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"
  }
});
Article

pour commencer: configurations de Taming avec noeud-convict

11
répondu hurrymaplelad 2013-08-05 19:00:19

vous pouvez utiliser Konfig pour les fichiers de configuration spécifiques à l'environnement. Il charge automatiquement les fichiers de configuration JSON ou yaml, il a une valeur par défaut et des fonctionnalités de configuration dynamique.

exemple tiré de Konfig repo:

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"
    }
}

en développement:

> config.app.port
3000

dans la production, supposons que nous commençons l'application avec $ NODE_ENV=production PORT=4567 node app.js

> config.app.port
4567

plus de détails: https://github.com/vngrs/konfig

11
répondu Ali Davut 2014-02-03 12:20:32

je vais jeter mon chapeau dans le ring ici parce qu'aucune de ces réponses traitent de tous les composants critiques dont à peu près tous les systèmes ont besoin. Considérations:

  • Public de configuration (qui peut être vu par le frontend) vs privé de configuration (guy mograbi a obtenu ce droit). Et s'assurer que ces sont séparés.
  • Secrets comme les touches
  • par défaut vs dérogations spécifiques à l'environnement
  • Frontend bundles

Voici comment je fais ma configuration:

  • config.default.private.js - dans le contrôle de version, ce sont des options de configuration par défaut qui ne peuvent être vues que par votre arrière-plan.
  • config.default.public.js - dans le contrôle de version, ce sont des options de configuration par défaut qui peuvent être vues par backend et frontend
  • config.dev.private.js - si vous avez besoin de différents paramètres privés par défaut pour dev.
  • config.dev.public.js - si vous avez besoin de différentes valeurs par défaut pour dev.
  • config.private.js - pas dans le contrôle de version, ce sont des options spécifiques à l'environnement qui outrepassent config.default.private.js
  • config.public.js - pas dans le contrôle de version, ce sont des options spécifiques à l'environnement qui outrepassent config.default.public.js
  • keys/ - un dossier où chaque fichier stocke un différent le secret d'une certaine sorte. Ce n'est pas non plus sous contrôle de version (les clés ne devraient jamais être sous contrôle de version).

j'utilise de vieux fichiers javascript pour la configuration afin d'avoir la pleine puissance du langage javascript (y compris les commentaires et la capacité de faire des choses comme charger le fichier de configuration par défaut dans le fichier spécifique à l'environnement afin qu'ils puissent être dépassés). Si vous souhaitez utiliser des variables d'environnement, vous pouvez les charger à l'intérieur de ces fichiers de configuration (quoique je déconseillé d'utiliser envvars pour la même raison que je ne recommande pas d'utiliser les fichiers json - vous n'avez pas la puissance d'un langage de programmation pour construire votre configuration).

la raison pour laquelle chaque clé est dans un fichier séparé est pour l'utilisation par l'installateur. Cela vous permet d'avoir un installateur qui crée les clés sur la machine et les stocke dans le dossier des clés. Sans cela, votre installateur pourrait échouer lorsque vous chargez votre fichier de configuration qui ne peut pas accéder à vos clés. De cette façon, vous pouvez traverser la répertorier et charger les fichiers clés qui sont dans ce dossier sans avoir à se soucier de ce qui existe et ce qui n'existe pas dans une version donnée de votre code.

puisque vous avez probablement des clés chargées dans votre configuration privée, vous certainement ne voulez pas charger votre configuration privée dans un code frontal. Alors que son probablement strictement plus idéal pour séparer complètement votre base de code frontend de votre arrière-plan, beaucoup de fois que PITA est un assez grand barrière pour empêcher les gens de le faire,donc config privée vs publique. Mais il y a deux choses que je fais pour éviter que private config ne soit chargé dans le frontend:

  1. j'ai un test unitaire qui garantit que mes paquets frontend ne contiennent pas une des clés secrètes que j'ai dans la config privée.
  2. j'ai mon code frontend dans un dossier différent de mon code backend, et j'ai deux fichiers différents nommés" config.js" - un pour chaque extrémité. Pour le backend, config.js charge la config privée, pour frontend, il charge la config publique. Ensuite, vous avez toujours besoin de ('config') et ne vous inquiétez pas d'où il vient.

une dernière chose: votre configuration doit être chargée dans le navigateur via un complètement fichier séparé que l'un de vos autres codes frontend. Si vous regroupez votre code frontend, la configuration publique doit être construite comme un ensemble complètement séparé. Sinon, votre config n'est pas vraiment config plus - son juste une partie de votre code. Config doit pouvoir être différent sur différentes machines.

11
répondu B T 2017-03-02 01:59:04

je vais créer un dossier comme config un fichier nommé config.js et plus tard j'utiliserai ce fichier là où requis comme ci-dessous

exemple de configuration.js

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

alors si je veux utiliser ce fichier de configuration quelque part

je vais d'abord importer comme ci-dessous

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

et je peux accéder aux valeurs comme ci-dessous

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');
    }
});
6
répondu Ron 2018-01-25 04:12:46

je suis un peu en retard dans le jeu, mais je ne pouvais pas trouver ce dont j'avais besoin ici - ou ailleurs - donc j'ai écrit quelque chose moi-même.

mes exigences pour un mécanisme de configuration sont les suivantes:

  1. Support frontal. Quel est le but si le front-end ne peut pas utiliser la configuration?
  2. Support settings-overrides.js - qui ressemble au même mais permet des dérogations de configuration à settings.js . L'idée est ici est de modifier la configuration facilement sans changer le code. Je le trouve utile pour saas.

même si je me soucie moins des environnements de soutien - la volonté expliquer comment l'ajouter facilement à ma solution

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;

explication

  • undefined cette propriété est requise."
  • null signifie qu'il est facultatif
  • meConf - actuellement, le code est la cible d'un fichier sous app . meConf est le fichier overrides qui est ciblé sur conf/dev - qui est ignoré par mon vcs.
  • publicConfiguration - sera visible de l'avant et de l'arrière.
  • privateConfiguration - sera visible de l'arrière seulement.
  • sendPublicConfiguration - une route qui exposera la configuration publique et l'assignera à une variable globale. Par exemple, le le code ci-dessous exposera la configuration publique en tant que variable globale myConf dans la partie frontale. Par défaut, il utilisera le nom de la variable globale conf .

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

logique des dérogations

  • privateConfiguration est fusionné avec publicConfiguration et puis meConf.
  • publicConfiguration vérifie chaque clé si elle a une surpassement, et utilise cette surpassement. De cette façon, nous n'exposons rien de privé.

ajout de soutien à l'environnement

même si Je ne trouve pas utile de" support environnemental", peut-être que quelqu'un le fera.

pour ajouter le support d'environnement, vous devez changer l'instruction require meConf en quelque chose comme ceci (pseudo-code)

si ( environnement = production" ) { meConf = require ("../ conf / dev / meConf").production; }

si ( environnement == "développement" ) { meConf = require ("../ conf / dev / meConf").développement; }

de même, vous pouvez avoir un fichier par Environnement

 meConf.development.js
 meConf.production.js

et importer le bon. Le reste de la logique reste la même.

3
répondu guy mograbi 2013-10-01 09:20:21

un exemple alt que je viens d'utiliser parce que je voulais plus de flexibilité qu'un typique .fichier json, mais ne voulais pas qu'il disparaît dans une bibliothèque qui nécessiterait une dépendance est quelque chose comme cela. Essentiellement, exporter une fonction invoquée immédiatement qui renvoie un objet avec des valeurs que je voulais définir. Donne beaucoup de flexibilité.

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

il y a une bien meilleure explication avec un exemple complet ici. utilisant des fichiers de configuration dans Node.js

3
répondu captainavi 2014-10-20 05:22:29

je sais que c'est un très vieux post. Mais je veux partager mon module pour configurer les variables d'environnement, je pense qu'il est solution très flexible. Voici le module JSON-configurateur

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 

, Alors vous pouvez utiliser process.env.NODE_ENV pour obtenir toutes les variables de votre environnement.

3
répondu Christian 2016-01-27 16:30:29

en plus du module nconf mentionné dans cette réponse , et noeud-config mentionné dans cette réponse , Il ya aussi noeud-iniparser et IniReader , qui semblent être plus simples .analyseurs de fichiers de configuration ini.

1
répondu Wingman4l7 2017-05-23 10:31:37

je viens de sortir un petit module pour charger n'importe quel type de fichiers de configuration. C'est assez simple, vous pouvez vérifier à https://github.com/flesler/config-node

1
répondu Ariel Flesler 2014-03-26 19:32:41

vous pouvez utiliser pconf: https://www.npmjs.com/package/pconf

exemple:

var Config = require("pconf");
var testConfig = new Config("testConfig");
testConfig.onload = function(){

  testConfig.setValue("test", 1);
  testConfig.getValue("test");
  //testConfig.saveConfig(); Not needed

}
1
répondu Per Henrik Jakobsson 2017-03-29 14:51:36

il est préférable de séparer 'développement' et 'production' configs.

j'utilise la manière suivante: Voici mon config / index.js fichier:

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 : ""
        }
    }
} 

Pour exiger la config suivante:

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

que vous pouvez utiliser votre objet de configuration:

const ip_address = config.ip_address;
const port = config.port;
1
répondu Aram Manukyan 2018-08-18 10:24:45

pour ceux qui visitent ce vieux fil, voici un paquet que je trouve bon.

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

0
répondu Venkat Kotra 2014-10-14 13:01:52

j'ai essayé quelques-unes des solutions suggérées ici, mais n'a pas été sattisfié avec eux, donc j'ai créé mon propre module. Il est appelé mikro-config et la principale différence est qu'il honore la convention sur la configuration, donc vous pouvez juste exiger le module et commencer à l'utiliser.

vous stockez votre configuration dans des fichiers JS ou json du dossier /config . D'abord il charge le fichier default.js , puis tous les autres fichiers du répertoire /config , puis il charge configuration spécifique à l'environnement basée sur la variable $NODE_ENV .

il permet également de modifier cette configuration pour le développement local avec local.js ou /config/env/$NODE_ENV.local.js spécifique à l'environnement .

, Vous pouvez prendre à la regarder ici:

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

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

0
répondu Martin Adámek 2017-04-17 10:19:02

Pendant longtemps, j'ai utilisé l'approche mentionné dans la solution ici. Toutefois, la sécurité des secrets dans un texte clair suscite des inquiétudes. Vous pouvez utiliser un autre paquet sur le dessus de config de sorte que les bits de sécurité sont prises en charge.

Check this out: https://www.attosol.com/secure-application-secrets-using-masterkey-in-azure-key-vault /

0
répondu Rahul Soni 2017-06-13 10:43:18

il suffit d'utiliser npm module config (plus de 300000 téléchargements)

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

Node-config organise des configurations hiérarchiques pour vos déploiements d'applications.

permet de définir un ensemble de paramètres par défaut, et de les étendre pour différents environnements de déploiement (développement, qa, staging, production, etc.).

$ 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
0
répondu аlex dykyі 2018-08-30 09:27:11