diff --git a/Cargo.lock b/Cargo.lock
index 830975527667b31fd90287ee15e9d4c6fd4b96f9..e020f1ce320b872d0662a9e4f69daef31ddb9fbd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -998,8 +998,11 @@ dependencies = [
  "dup-crypto 0.7.0",
  "durs-common-tools 0.2.0",
  "durs-module 0.3.0-dev",
+ "envy 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rpassword 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1335,6 +1338,14 @@ dependencies = [
  "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "envy"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "failure"
 version = "0.1.6"
@@ -1988,6 +1999,11 @@ name = "numtoa"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "once_cell"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "opaque-debug"
 version = "0.2.3"
@@ -3132,6 +3148,7 @@ dependencies = [
 "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
 "checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28"
 "checksum enum-as-inner 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "900a6c7fbe523f4c2884eaf26b57b81bb69b6810a01a236390a7ac021d09492e"
+"checksum envy 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f938a4abd5b75fe3737902dbc2e79ca142cc1526827a9e40b829a086758531a9"
 "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
 "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
@@ -3207,6 +3224,7 @@ dependencies = [
 "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
 "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72"
 "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
+"checksum once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
 "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
 "checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585"
 "checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f"
diff --git a/lib/core/conf/Cargo.toml b/lib/core/conf/Cargo.toml
index f66ac63f787a820f41dc73d50e46d62340272b55..3449896a0905ff483cd7c22b87b47654a6845709 100644
--- a/lib/core/conf/Cargo.toml
+++ b/lib/core/conf/Cargo.toml
@@ -16,6 +16,7 @@ dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
 durs-module = { path = "../module" }
 durs-common-tools = { path = "../../tools/common-tools" }
+envy = "0.4.1"
 failure = "0.1.5"
 log = "0.4.*"
 rpassword = "4.0.3"
@@ -24,4 +25,8 @@ serde_derive = "1.0.*"
 serde_json = "1.0.*"
 unwrap = "1.2.1"
 
+[dev-dependencies]
+maplit = "1.0.2"
+once_cell = "1.3.1"
+
 [features]
diff --git a/lib/core/conf/src/constants.rs b/lib/core/conf/src/constants.rs
index 7f0179cdd5d4b8ae1f2fceb927655197e313a24d..d2d323b553d29addcf1114f5ac5650d4d989e1a2 100644
--- a/lib/core/conf/src/constants.rs
+++ b/lib/core/conf/src/constants.rs
@@ -15,20 +15,26 @@
 
 //! Dunitrust configuration constants
 
-/// User datas folder
+/// User datas folder.
 pub static USER_DATAS_FOLDER: &str = "durs-dev";
 
-/// Configuration filename
+/// Configuration filename.
 pub static CONF_FILENAME: &str = "conf.json";
 
-/// Keypairs filename
+/// Keypairs filename.
 pub static KEYPAIRS_FILENAME: &str = "keypairs.json";
 
-/// If no currency is specified by the user, is the currency will be chosen by default
+/// If no currency is specified by the user, is the currency will be chosen by default.
 pub static DEFAULT_CURRENCY: &str = "g1";
 
-/// Default value for `default_sync_module` conf field
+/// Default value for `default_sync_module` conf field.
 pub static DEFAULT_DEFAULT_SYNC_MODULE: &str = "ws2p";
 
-/// Modules datas folder
+/// Modules datas folder.
 pub static MODULES_DATAS_FOLDER: &str = "datas";
+
+/// Prefix for dunitrust environment variables.
+pub static DURS_ENV_PREFIX: &str = "DURS_";
+
+/// Name of the environment variable that indicates the version of the configuration.
+pub static DURS_CONF_VERSION: &str = "DURS_CONF_VERSION";
diff --git a/lib/core/conf/src/env.rs b/lib/core/conf/src/env.rs
new file mode 100644
index 0000000000000000000000000000000000000000..27c2e099be4a710592c75754f05fcdc20fdbe51d
--- /dev/null
+++ b/lib/core/conf/src/env.rs
@@ -0,0 +1,126 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust configuration from environment variables
+
+use crate::constants;
+use crate::errors::DursConfEnvError;
+use crate::global_conf::v2::DuRsGlobalUserConfV2;
+use crate::global_conf::DuRsGlobalUserConf;
+
+/// Load global user configuration from environment variables
+pub fn load_env_global_user_conf() -> Result<DuRsGlobalUserConf, DursConfEnvError> {
+    if let Ok(conf_version) = std::env::var(constants::DURS_CONF_VERSION) {
+        match conf_version
+            .parse::<usize>()
+            .map_err(DursConfEnvError::ConfVersionParseErr)?
+        {
+            2 => Ok(DuRsGlobalUserConf::V2(
+                envy::prefixed(constants::DURS_ENV_PREFIX)
+                    .from_env::<DuRsGlobalUserConfV2>()
+                    .map_err(DursConfEnvError::EnvyErr)?,
+            )),
+            v => Err(DursConfEnvError::UnsupportedVersion {
+                expected: vec![2],
+                found: v,
+            }),
+        }
+    } else {
+        Ok(DuRsGlobalUserConf::V2(DuRsGlobalUserConfV2::default()))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use dubp_currency_params::CurrencyName;
+    use durs_module::ModuleName;
+    use maplit::hashset;
+    use once_cell::sync::Lazy;
+    use std::sync::Mutex;
+
+    // Empty mutex used to ensure that only one test runs at a time
+    static MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
+
+    #[test]
+    fn test_env_conf_without_env_vars() -> Result<(), DursConfEnvError> {
+        let _lock = MUTEX.lock().expect("MUTEX poisoned");
+
+        std::env::remove_var(constants::DURS_CONF_VERSION);
+
+        assert_eq!(
+            DuRsGlobalUserConf::V2(DuRsGlobalUserConfV2::default()),
+            load_env_global_user_conf()?,
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_env_conf_with_unsupported_conf_version_var() -> Result<(), DursConfEnvError> {
+        let _lock = MUTEX.lock().expect("MUTEX poisoned");
+
+        std::env::set_var(constants::DURS_CONF_VERSION, "3");
+
+        if let Err(DursConfEnvError::UnsupportedVersion { .. }) = load_env_global_user_conf() {
+            Ok(())
+        } else {
+            panic!("load_env_global_user_conf() must return an error DursConfEnvError::UnsupportedVersion.");
+        }
+    }
+
+    #[test]
+    fn test_env_conf_with_some_valid_env_vars() -> Result<(), DursConfEnvError> {
+        let _lock = MUTEX.lock().expect("MUTEX poisoned");
+
+        std::env::set_var(constants::DURS_CONF_VERSION, "2");
+        std::env::set_var(&format!("{}CURRENCY", constants::DURS_ENV_PREFIX), "g1");
+        std::env::set_var(
+            &format!("{}DISABLED", constants::DURS_ENV_PREFIX),
+            "tui,gva",
+        );
+
+        assert_eq!(
+            DuRsGlobalUserConf::V2(DuRsGlobalUserConfV2 {
+                currency: Some(CurrencyName(String::from("g1"))),
+                my_node_id: None,
+                default_sync_module: None,
+                ressources_usage: None,
+                disabled: Some(hashset![
+                    ModuleName("tui".to_owned()),
+                    ModuleName("gva".to_owned())
+                ]),
+                enabled: None,
+            }),
+            load_env_global_user_conf()?,
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_env_conf_with_invalid_conf_version_var() -> Result<(), DursConfEnvError> {
+        let _lock = MUTEX.lock().expect("MUTEX poisoned");
+
+        std::env::set_var(constants::DURS_CONF_VERSION, "str");
+
+        if let Err(DursConfEnvError::ConfVersionParseErr(_)) = load_env_global_user_conf() {
+            Ok(())
+        } else {
+            panic!("load_env_global_user_conf() must return an error DursConfEnvError::ConfVersionParseErr.");
+        }
+    }
+}
diff --git a/lib/core/conf/src/errors.rs b/lib/core/conf/src/errors.rs
new file mode 100644
index 0000000000000000000000000000000000000000..18884dc073aed1b27784a4e0aab83565bf2dc4cf
--- /dev/null
+++ b/lib/core/conf/src/errors.rs
@@ -0,0 +1,65 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust configuration errors
+
+use failure::Fail;
+
+/// Error with configuration file
+#[derive(Debug, Fail)]
+pub enum DursConfError {
+    /// Env var error
+    #[fail(display = "fail to parse configuration file: {}", _0)]
+    EnvVarErr(DursConfEnvError),
+    /// File error
+    #[fail(display = "{}", _0)]
+    FileErr(DursConfFileError),
+}
+
+/// Error with configuration file
+#[derive(Debug, Fail)]
+pub enum DursConfEnvError {
+    /// Fail to parse conf version
+    #[fail(display = "Fail to parse conf version : {}.", _0)]
+    ConfVersionParseErr(std::num::ParseIntError),
+    /// Envy error
+    #[fail(display = "{}", _0)]
+    EnvyErr(envy::Error),
+    /// Unsupported version
+    #[fail(
+        display = "Version {} not supported. List of supported versions : {:?}.",
+        found, expected
+    )]
+    UnsupportedVersion {
+        /// List of supported versions
+        expected: Vec<usize>,
+        /// Version found
+        found: usize,
+    },
+}
+
+/// Error with configuration file
+#[derive(Debug, Fail)]
+pub enum DursConfFileError {
+    /// Read error
+    #[fail(display = "fail to read configuration file: {}", _0)]
+    ReadError(std::io::Error),
+    /// Parse error
+    #[fail(display = "fail to parse configuration file: {}", _0)]
+    ParseError(serde_json::Error),
+    /// Write error
+    #[fail(display = "fail to write configuration file: {}", _0)]
+    WriteError(std::io::Error),
+}
diff --git a/lib/core/conf/src/file.rs b/lib/core/conf/src/file.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bbdab08a8c51b8c729efc66244f2622868ab2383
--- /dev/null
+++ b/lib/core/conf/src/file.rs
@@ -0,0 +1,172 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust configuration file
+
+use crate::constants;
+use crate::errors::DursConfFileError;
+use crate::DuRsConf;
+use durs_module::DursConfTrait;
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::{Path, PathBuf};
+
+#[inline]
+/// Return path to configuration file
+pub fn get_conf_path(profile_path: &PathBuf) -> PathBuf {
+    let mut conf_path = profile_path.clone();
+    conf_path.push(constants::CONF_FILENAME);
+    conf_path
+}
+
+/// Load configuration from file
+pub fn load_conf_from_file(mut conf_file_path: PathBuf) -> Result<DuRsConf, DursConfFileError> {
+    // Open conf file
+    conf_file_path.push(constants::CONF_FILENAME);
+    if conf_file_path.as_path().exists() {
+        match File::open(conf_file_path.as_path()) {
+            Ok(mut f) => {
+                let mut contents = String::new();
+                f.read_to_string(&mut contents)
+                    .map_err(DursConfFileError::ReadError)?;
+                // Parse conf file
+                let conf: DuRsConf =
+                    serde_json::from_str(&contents).map_err(DursConfFileError::ParseError)?;
+                // Upgrade conf to latest version
+                let (conf, upgraded) = conf.upgrade();
+                // If conf is upgraded, rewrite conf file
+                if upgraded {
+                    write_conf_file(conf_file_path.as_path(), &conf)
+                        .map_err(DursConfFileError::WriteError)?;
+                }
+                Ok(conf)
+            }
+            Err(e) => Err(DursConfFileError::ReadError(e)),
+        }
+    } else {
+        // Create conf file with default conf
+        let conf = DuRsConf::default();
+        write_conf_file(conf_file_path.as_path(), &conf)
+            .unwrap_or_else(|_| panic!(dbg!("Fatal error : fail to write default conf file!")));
+        Ok(conf)
+    }
+}
+
+/// Save configuration in profile folder
+pub fn write_conf_file<DC: DursConfTrait>(
+    conf_path: &Path,
+    conf: &DC,
+) -> Result<(), std::io::Error> {
+    let mut f = File::create(conf_path)?;
+    f.write_all(
+        serde_json::to_string_pretty(conf)
+            .expect("Fatal error : fail to write default conf file !")
+            .as_bytes(),
+    )?;
+    f.sync_all()?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use serde_json::json;
+
+    #[inline]
+    fn save_old_conf(profile_path: PathBuf) -> std::io::Result<()> {
+        let mut conf_path = profile_path.clone();
+        conf_path.push(constants::CONF_FILENAME);
+        let mut conf_sav_path = profile_path;
+        conf_sav_path.push("conf-sav.json");
+        std::fs::copy(conf_path.as_path(), conf_sav_path.as_path())?;
+        Ok(())
+    }
+
+    fn restore_old_conf_and_save_upgraded_conf(profile_path: PathBuf) -> std::io::Result<()> {
+        let mut conf_path = profile_path.clone();
+        conf_path.push(constants::CONF_FILENAME);
+        let mut conf_sav_path = profile_path.clone();
+        conf_sav_path.push("conf-sav.json");
+        let mut conf_upgraded_path = profile_path;
+        conf_upgraded_path.push("conf-upgraded.json");
+        std::fs::copy(conf_path.as_path(), &conf_upgraded_path.as_path())?;
+        std::fs::copy(conf_sav_path.as_path(), &conf_path.as_path())?;
+        std::fs::remove_file(conf_sav_path.as_path())?;
+        Ok(())
+    }
+
+    #[test]
+    fn load_conf_file_v1() -> Result<(), DursConfFileError> {
+        let profile_path = PathBuf::from("./test/v1/");
+        save_old_conf(PathBuf::from(profile_path.clone()))
+            .map_err(DursConfFileError::WriteError)?;
+        let conf = load_conf_from_file(profile_path.clone())?;
+        assert_eq!(
+            conf.modules()
+                .get("ws2p")
+                .expect("Not found ws2p conf")
+                .clone(),
+            json!({
+                "sync_endpoints": [
+                {
+                    "endpoint": "WS2P c1c39a0a i3.ifee.fr 80 /ws2p",
+                    "pubkey": "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx"
+                },
+                {
+                    "endpoint": "WS2P 15af24db g1.ifee.fr 80 /ws2p",
+                    "pubkey": "BoZP6aqtErHjiKLosLrQxBafi4ATciyDZQ6XRQkNefqG"
+                },
+                {
+                    "endpoint": "WS2P b48824f0 g1.monnaielibreoccitanie.org 80 /ws2p",
+                    "pubkey": "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef"
+                }
+                ]
+            })
+        );
+        restore_old_conf_and_save_upgraded_conf(profile_path)
+            .map_err(DursConfFileError::WriteError)?;
+
+        Ok(())
+    }
+
+    #[test]
+    fn load_conf_file_v2() -> Result<(), DursConfFileError> {
+        let profile_path = PathBuf::from("./test/v2/");
+        let conf = load_conf_from_file(profile_path)?;
+        assert_eq!(
+            conf.modules()
+                .get("ws2p")
+                .expect("Not found ws2p conf")
+                .clone(),
+            json!({
+                "sync_endpoints": [
+                {
+                    "endpoint": "WS2P c1c39a0a i3.ifee.fr 80 /ws2p",
+                    "pubkey": "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx"
+                },
+                {
+                    "endpoint": "WS2P 15af24db g1.ifee.fr 80 /ws2p",
+                    "pubkey": "BoZP6aqtErHjiKLosLrQxBafi4ATciyDZQ6XRQkNefqG"
+                },
+                {
+                    "endpoint": "WS2P b48824f0 g1.monnaielibreoccitanie.org 80 /ws2p",
+                    "pubkey": "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef"
+                }
+                ]
+            })
+        );
+        Ok(())
+    }
+}
diff --git a/lib/core/conf/src/global_conf.rs b/lib/core/conf/src/global_conf.rs
new file mode 100644
index 0000000000000000000000000000000000000000..07b03afe743d715398ed4d357e3b678cb217cc99
--- /dev/null
+++ b/lib/core/conf/src/global_conf.rs
@@ -0,0 +1,56 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust global configuration
+
+pub mod v2;
+
+use durs_common_tools::fatal_error;
+use durs_module::{DursGlobalConfTrait, ModuleName};
+
+#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+/// Dunitrust global configuration (without modules configuration)
+pub enum DuRsGlobalConf {
+    /// Dunitrust global configuration v1
+    V1(crate::v1::DuRsConfV1),
+    /// Dunitrust global configuration v2
+    V2(v2::DuRsGlobalConfV2),
+}
+
+#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+/// Dunitrust global configuration (without modules configuration)
+pub enum DuRsGlobalUserConf {
+    /// Dunitrust global user configuration v2
+    V2(v2::DuRsGlobalUserConfV2),
+}
+
+impl DursGlobalConfTrait for DuRsGlobalConf {
+    type GlobalUserConf = DuRsGlobalUserConf;
+
+    fn my_node_id(&self) -> u32 {
+        match *self {
+            DuRsGlobalConf::V1(ref conf_v1) => conf_v1.my_node_id,
+            DuRsGlobalConf::V2(ref conf_v2) => conf_v2.my_node_id,
+        }
+    }
+    fn default_sync_module(&self) -> ModuleName {
+        match *self {
+            DuRsGlobalConf::V1(_) => {
+                fatal_error!("Feature default_sync_module not exist in durs conf v1 !")
+            }
+            DuRsGlobalConf::V2(ref conf_v2) => conf_v2.default_sync_module.clone(),
+        }
+    }
+}
diff --git a/lib/core/conf/src/global_conf/v2.rs b/lib/core/conf/src/global_conf/v2.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c4c7dd9b52e8ce76fe100a55e40fa009497e544e
--- /dev/null
+++ b/lib/core/conf/src/global_conf/v2.rs
@@ -0,0 +1,107 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust global configuration V2
+
+use crate::constants;
+use crate::resources::ResourcesUsage;
+use crate::v1::DuRsConfV1;
+use dubp_currency_params::CurrencyName;
+use durs_module::ModuleName;
+use std::collections::HashSet;
+
+#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
+/// Dunitrust configuration v2
+pub struct DuRsGlobalUserConfV2 {
+    /// Currency name
+    pub currency: Option<CurrencyName>,
+    /// Node unique identifier
+    pub my_node_id: Option<u32>,
+    /// Name of the module used by default for synchronization
+    pub default_sync_module: Option<ModuleName>,
+    /// Ressources usage
+    pub ressources_usage: Option<ResourcesUsage>,
+    /// Disabled modules
+    pub disabled: Option<HashSet<ModuleName>>,
+    /// Enabled modules
+    pub enabled: Option<HashSet<ModuleName>>,
+}
+
+#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
+/// Dunitrust configuration v2
+pub struct DuRsGlobalConfV2 {
+    /// Currency name
+    pub currency: CurrencyName,
+    /// Duniter node unique identifier
+    pub my_node_id: u32,
+    /// Name of the module used by default for synchronization
+    pub default_sync_module: ModuleName,
+    /// Ressources usage
+    pub ressources_usage: ResourcesUsage,
+    /// Disabled modules
+    pub disabled: HashSet<ModuleName>,
+    /// Enabled modules
+    pub enabled: HashSet<ModuleName>,
+}
+
+impl Default for DuRsGlobalConfV2 {
+    fn default() -> Self {
+        DuRsGlobalConfV2 {
+            currency: CurrencyName(String::from(constants::DEFAULT_CURRENCY)),
+            my_node_id: crate::generate_random_node_id(),
+            default_sync_module: ModuleName(String::from(constants::DEFAULT_DEFAULT_SYNC_MODULE)),
+            ressources_usage: ResourcesUsage::default(),
+            disabled: HashSet::with_capacity(0),
+            enabled: HashSet::with_capacity(0),
+        }
+    }
+}
+
+impl From<DuRsConfV1> for DuRsGlobalConfV2 {
+    fn from(conf_v1: DuRsConfV1) -> Self {
+        DuRsGlobalConfV2 {
+            currency: conf_v1.currency,
+            my_node_id: conf_v1.my_node_id,
+            default_sync_module: ModuleName(String::from(constants::DEFAULT_DEFAULT_SYNC_MODULE)),
+            ressources_usage: ResourcesUsage::default(),
+            disabled: conf_v1.disabled,
+            enabled: conf_v1.enabled,
+        }
+    }
+}
+
+impl DuRsGlobalConfV2 {
+    /// Override configuration with user configuration
+    pub fn r#override(self, global_user_conf: DuRsGlobalUserConfV2) -> Self {
+        DuRsGlobalConfV2 {
+            currency: global_user_conf.currency.unwrap_or(self.currency),
+            my_node_id: global_user_conf.my_node_id.unwrap_or(self.my_node_id),
+            default_sync_module: global_user_conf
+                .default_sync_module
+                .unwrap_or(self.default_sync_module),
+            ressources_usage: global_user_conf
+                .ressources_usage
+                .unwrap_or(self.ressources_usage),
+            disabled: global_user_conf.disabled.unwrap_or(self.disabled),
+            enabled: global_user_conf.enabled.unwrap_or(self.enabled),
+        }
+    }
+}
+
+impl From<DuRsGlobalUserConfV2> for DuRsGlobalConfV2 {
+    fn from(global_user_conf: DuRsGlobalUserConfV2) -> Self {
+        Self::default().r#override(global_user_conf)
+    }
+}
diff --git a/lib/core/conf/src/keypairs.rs b/lib/core/conf/src/keypairs.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6c6f2efbad135581030e3ee0a7cdf4b197008578
--- /dev/null
+++ b/lib/core/conf/src/keypairs.rs
@@ -0,0 +1,213 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust keypairs
+
+pub mod cli;
+
+use crate::constants;
+use crate::errors::DursConfError;
+use dup_crypto::keys::*;
+use durs_module::{RequiredKeys, RequiredKeysContent};
+use serde::ser::{Serialize, SerializeStruct, Serializer};
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::PathBuf;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+/// Keypairs filled in by the user (via a file or by direct entry in the terminal).
+pub struct DuniterKeyPairs {
+    /// Keypair used by the node to sign its communications with other nodes. This keypair is mandatory, if it's not filled in, a random keypair is generated.
+    pub network_keypair: KeyPairEnum,
+    /// Keypair used to sign the blocks forged by this node. If this keypair is'nt filled in, the node will not calculate blocks.
+    pub member_keypair: Option<KeyPairEnum>,
+}
+
+impl Serialize for DuniterKeyPairs {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        let member_seed = if let Some(ref member_keypair) = self.member_keypair {
+            member_keypair.seed().to_string()
+        } else {
+            String::from("")
+        };
+        let member_pub = if let Some(ref member_keypair) = self.member_keypair {
+            member_keypair.public_key().to_string()
+        } else {
+            String::from("")
+        };
+        let mut state = serializer.serialize_struct("DuniterKeyPairs", 4)?;
+        state.serialize_field(
+            "network_seed",
+            &self.network_keypair.seed().to_string().as_str(),
+        )?;
+        state.serialize_field(
+            "network_pub",
+            &self.network_keypair.public_key().to_string().as_str(),
+        )?;
+        state.serialize_field("member_seed", member_seed.as_str())?;
+        state.serialize_field("member_pub", member_pub.as_str())?;
+        state.end()
+    }
+}
+
+impl DuniterKeyPairs {
+    /// Returns only the keys indicated as required
+    pub fn get_required_keys_content(
+        required_keys: RequiredKeys,
+        keypairs: DuniterKeyPairs,
+    ) -> RequiredKeysContent {
+        match required_keys {
+            RequiredKeys::MemberKeyPair() => {
+                RequiredKeysContent::MemberKeyPair(keypairs.member_keypair)
+            }
+            RequiredKeys::MemberPublicKey() => {
+                RequiredKeysContent::MemberPublicKey(if let Some(keys) = keypairs.member_keypair {
+                    Some(keys.public_key())
+                } else {
+                    None
+                })
+            }
+            RequiredKeys::NetworkKeyPair() => {
+                RequiredKeysContent::NetworkKeyPair(keypairs.network_keypair)
+            }
+            RequiredKeys::NetworkPublicKey() => {
+                RequiredKeysContent::NetworkPublicKey(keypairs.network_keypair.public_key())
+            }
+            RequiredKeys::None() => RequiredKeysContent::None(),
+        }
+    }
+}
+
+/// Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
+fn generate_random_keypair(algo: KeysAlgo) -> KeyPairEnum {
+    match algo {
+        KeysAlgo::Ed25519 => KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair::generate_random()),
+        KeysAlgo::Schnorr => panic!("Schnorr algo not yet supported !"),
+    }
+}
+
+/// Save keypairs in profile folder
+// Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
+pub fn write_keypairs_file(
+    file_path: &PathBuf,
+    keypairs: &DuniterKeyPairs,
+) -> Result<(), std::io::Error> {
+    let mut f = File::create(file_path.as_path())?;
+    f.write_all(
+        serde_json::to_string_pretty(keypairs)
+            .unwrap_or_else(|_| panic!(dbg!("Fatal error : fail to deserialize keypairs !")))
+            .as_bytes(),
+    )?;
+    f.sync_all()?;
+    Ok(())
+}
+
+/// Load keypairs from file
+pub fn load_keypairs_from_file(
+    profile_path: &PathBuf,
+    keypairs_file_path: &Option<PathBuf>,
+) -> Result<DuniterKeyPairs, DursConfError> {
+    // Get KeyPairs
+    let keypairs_path = if let Some(ref keypairs_file_path) = keypairs_file_path {
+        keypairs_file_path.clone()
+    } else {
+        let mut keypairs_path = profile_path.clone();
+        keypairs_path.push(constants::KEYPAIRS_FILENAME);
+        keypairs_path
+    };
+    if keypairs_path.as_path().exists() {
+        if let Ok(mut f) = File::open(keypairs_path.as_path()) {
+            let mut contents = String::new();
+            if f.read_to_string(&mut contents).is_ok() {
+                let json_conf: serde_json::Value =
+                    serde_json::from_str(&contents).expect("Conf: Fail to parse keypairs file !");
+
+                if let Some(network_seed) = json_conf.get("network_seed") {
+                    if let Some(network_pub) = json_conf.get("network_pub") {
+                        let network_seed = network_seed
+                            .as_str()
+                            .expect("Conf: Fail to parse keypairs file !");
+                        let network_pub = network_pub
+                            .as_str()
+                            .expect("Conf: Fail to parse keypairs file !");
+                        let network_keypair = KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
+                            seed: Seed32::from_base58(network_seed)
+                                .expect("conf : keypairs file : fail to parse network_seed !"),
+                            pubkey: ed25519::PublicKey::from_base58(network_pub)
+                                .expect("conf : keypairs file : fail to parse network_pub !"),
+                        });
+
+                        let member_keypair = if let Some(member_seed) = json_conf.get("member_seed")
+                        {
+                            if let Some(member_pub) = json_conf.get("member_pub") {
+                                let member_seed = member_seed
+                                    .as_str()
+                                    .expect("Conf: Fail to parse keypairs file !");
+                                let member_pub = member_pub
+                                    .as_str()
+                                    .expect("Conf: Fail to parse keypairs file !");
+                                if member_seed.is_empty() || member_pub.is_empty() {
+                                    None
+                                } else {
+                                    Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
+                                        seed: Seed32::from_base58(member_seed).expect(
+                                            "conf : keypairs file : fail to parse member_seed !",
+                                        ),
+                                        pubkey: ed25519::PublicKey::from_base58(member_pub).expect(
+                                            "conf : keypairs file : fail to parse member_pub !",
+                                        ),
+                                    }))
+                                }
+                            } else {
+                                panic!("Fatal error : keypairs file wrong format : no field member_pub !")
+                            }
+                        } else {
+                            panic!(
+                                "Fatal error : keypairs file wrong format : no field member_seed !"
+                            )
+                        };
+
+                        // Return keypairs
+                        Ok(DuniterKeyPairs {
+                            network_keypair,
+                            member_keypair,
+                        })
+                    } else {
+                        panic!("Fatal error : keypairs file wrong format : no field salt !")
+                    }
+                } else {
+                    panic!("Fatal error : keypairs file wrong format : no field password !")
+                }
+            } else {
+                panic!("Fail to read keypairs file !");
+            }
+        } else {
+            panic!("Fail to open keypairs file !");
+        }
+    } else {
+        // Create keypairs file with random keypair
+        let keypairs = DuniterKeyPairs {
+            network_keypair: generate_random_keypair(KeysAlgo::Ed25519),
+            member_keypair: None,
+        };
+        write_keypairs_file(&keypairs_path, &keypairs).unwrap_or_else(|_| {
+            panic!(dbg!("Fatal error : fail to write default keypairs file !"))
+        });
+        Ok(keypairs)
+    }
+}
diff --git a/lib/core/conf/src/keys.rs b/lib/core/conf/src/keypairs/cli.rs
similarity index 94%
rename from lib/core/conf/src/keys.rs
rename to lib/core/conf/src/keypairs/cli.rs
index 86a3b1109ac26b1499db503fa47d56735e21a269..22b5c245c48711dee53f09ef0d47be6553095fc3 100644
--- a/lib/core/conf/src/keys.rs
+++ b/lib/core/conf/src/keypairs/cli.rs
@@ -13,7 +13,7 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-//! Dunitrust keys configuration module
+//! Dunitrust keypairs cli commands
 
 #![deny(
     missing_docs,
@@ -75,23 +75,21 @@ pub fn modify_member_keys(
 pub fn clear_keys(network: bool, member: bool, key_pairs: DuniterKeyPairs) -> DuniterKeyPairs {
     inner_clear_keys(
         if network {
-            match question_prompt("Clear your network keypair?", &["y", "n"]) {
-                Ok(answer) if answer == "y" => {
-                    println!("Generating a new network keypair!");
-                    true
-                }
-                _ => false,
+            if let Ok("y") = question_prompt("Clear your network keypair?", &["y", "n"]) {
+                println!("Generating a new network keypair!");
+                true
+            } else {
+                false
             }
         } else {
             false
         },
         if member {
-            match question_prompt("Clear your member keypair?", &["y", "n"]) {
-                Ok(answer) if answer == "y" => {
-                    println!("Deleting member keypair!");
-                    true
-                }
-                _ => false,
+            if let Ok("y") = question_prompt("Clear your member keypair?", &["y", "n"]) {
+                println!("Deleting member keypair!");
+                true
+            } else {
+                false
             }
         } else {
             false
@@ -107,7 +105,7 @@ fn inner_clear_keys(
     mut key_pairs: DuniterKeyPairs,
 ) -> DuniterKeyPairs {
     if network {
-        key_pairs.network_keypair = generate_random_keypair(KeysAlgo::Ed25519);
+        key_pairs.network_keypair = super::generate_random_keypair(KeysAlgo::Ed25519);
     }
     if member {
         key_pairs.member_keypair = None
@@ -137,7 +135,7 @@ pub fn save_keypairs(
         conf_keys_path.push(crate::constants::KEYPAIRS_FILENAME);
         conf_keys_path
     };
-    write_keypairs_file(&conf_keys_path, &key_pairs)?;
+    super::write_keypairs_file(&conf_keys_path, &key_pairs)?;
     Ok(())
 }
 
diff --git a/lib/core/conf/src/lib.rs b/lib/core/conf/src/lib.rs
index d6fbc76eb953c025b15d905f2070fd214ba16103..0cf9a602bc1834ebeec5e2f4a6f544df22bfb75c 100644
--- a/lib/core/conf/src/lib.rs
+++ b/lib/core/conf/src/lib.rs
@@ -13,7 +13,7 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-//! Dunitrust configuration files properties module
+//! Dunitrust configuration module
 
 #![deny(
     clippy::option_unwrap_used,
@@ -35,23 +35,30 @@ extern crate log;
 extern crate serde_derive;
 
 pub mod constants;
-pub mod keys;
+mod env;
+pub mod errors;
+pub mod file;
+mod global_conf;
+pub mod keypairs;
+mod modules_conf;
+mod resources;
+mod v1;
+
+pub use crate::errors::DursConfError;
+pub use crate::keypairs::DuniterKeyPairs;
 
 use crate::constants::MODULES_DATAS_FOLDER;
+use crate::global_conf::v2::DuRsGlobalConfV2;
+use crate::global_conf::{DuRsGlobalConf, DuRsGlobalUserConf};
+use crate::modules_conf::ModulesConf;
 use dubp_currency_params::CurrencyName;
 use dup_crypto::keys::*;
 use dup_crypto::rand;
 use durs_common_tools::fatal_error;
-use durs_module::{
-    DursConfTrait, DursGlobalConfTrait, ModuleName, RequiredKeys, RequiredKeysContent,
-};
-use failure::Fail;
-use serde::ser::{Serialize, SerializeStruct, Serializer};
+use durs_module::{DursConfTrait, DursGlobalConfTrait, ModuleName};
 use std::collections::HashSet;
 use std::fs;
-use std::fs::File;
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 
 #[derive(Debug, Clone)]
 /// User request on global conf
@@ -66,185 +73,25 @@ pub enum ChangeGlobalConf {
     None(),
 }
 
-#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
-/// Modules conf
-pub struct ModulesConf(pub serde_json::Value);
-
-impl Default for ModulesConf {
-    #[inline]
-    fn default() -> Self {
-        ModulesConf(serde_json::Value::Null)
-    }
-}
-
-impl ModulesConf {
-    /// Change module conf
-    pub fn set_module_conf(&mut self, module_name: ModuleName, new_module_conf: serde_json::Value) {
-        if self.0.is_null() {
-            let mut new_modules_conf = serde_json::Map::with_capacity(1);
-            new_modules_conf.insert(module_name.0, new_module_conf);
-            self.0 = serde_json::value::to_value(new_modules_conf)
-                .expect("Fail to create map of new modules conf !");
-        } else {
-            self.0
-                .as_object_mut()
-                .expect("Conf file currupted !")
-                .insert(module_name.0, new_module_conf);
-        }
-    }
-}
-
-#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
-/// Duniter configuration v1
-pub struct DuRsConfV1 {
-    /// Currency name
-    pub currency: CurrencyName,
-    /// Duniter node unique identifier
-    pub my_node_id: u32,
-    /// Configuration of modules in json format (obtained from the conf.json file)
-    pub modules: ModulesConf,
-    /// Disabled modules
-    pub disabled: HashSet<ModuleName>,
-    /// Enabled modules
-    pub enabled: HashSet<ModuleName>,
-}
-
-impl Default for DuRsConfV1 {
-    fn default() -> Self {
-        DuRsConfV1 {
-            currency: CurrencyName(String::from(constants::DEFAULT_CURRENCY)),
-            my_node_id: generate_random_node_id(),
-            modules: ModulesConf::default(),
-            disabled: HashSet::with_capacity(0),
-            enabled: HashSet::with_capacity(0),
-        }
-    }
-}
-
-#[derive(Debug, Copy, Clone, Deserialize, PartialEq, Serialize)]
-/// Ressource usage
-pub enum ResourceUsage {
-    /// Minimal use of the resource, to the detriment of performance
-    Minimal,
-    /// Trade-off between resource use and performance
-    Medium,
-    /// A performance-oriented trade-off, the use of the resource is slightly limited
-    Large,
-    /// No restrictions on the use of the resource, maximizes performance
-    Infinite,
-}
-#[derive(Debug, Copy, Clone, Deserialize, PartialEq, Serialize)]
-/// Ressources usage
-pub struct ResourcesUsage {
-    /// Cpu usage
-    pub cpu_usage: ResourceUsage,
-    /// Network usage
-    pub network_usage: ResourceUsage,
-    /// Memory usage
-    pub memory_usage: ResourceUsage,
-    /// Disk space usage
-    pub disk_space_usage: ResourceUsage,
-}
-
-impl Default for ResourcesUsage {
-    fn default() -> Self {
-        ResourcesUsage {
-            cpu_usage: ResourceUsage::Large,
-            network_usage: ResourceUsage::Large,
-            memory_usage: ResourceUsage::Large,
-            disk_space_usage: ResourceUsage::Large,
-        }
-    }
-}
-
-#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
-/// Duniter configuration v2
-pub struct DuRsConfV2 {
-    /// Currency name
-    pub currency: CurrencyName,
-    /// Duniter node unique identifier
-    pub my_node_id: u32,
-    /// Name of the module used by default for synchronization
-    pub default_sync_module: ModuleName,
-    /// Ressources usage
-    pub ressources_usage: ResourcesUsage,
-    /// Disabled modules
-    pub disabled: HashSet<ModuleName>,
-    /// Enabled modules
-    pub enabled: HashSet<ModuleName>,
-}
-
-impl Default for DuRsConfV2 {
-    fn default() -> Self {
-        DuRsConfV2 {
-            currency: CurrencyName(String::from(constants::DEFAULT_CURRENCY)),
-            my_node_id: generate_random_node_id(),
-            default_sync_module: ModuleName(String::from(constants::DEFAULT_DEFAULT_SYNC_MODULE)),
-            ressources_usage: ResourcesUsage::default(),
-            disabled: HashSet::with_capacity(0),
-            enabled: HashSet::with_capacity(0),
-        }
-    }
-}
-
-impl From<DuRsConfV1> for DuRsConfV2 {
-    fn from(conf_v1: DuRsConfV1) -> Self {
-        DuRsConfV2 {
-            currency: conf_v1.currency,
-            my_node_id: conf_v1.my_node_id,
-            default_sync_module: ModuleName(String::from(constants::DEFAULT_DEFAULT_SYNC_MODULE)),
-            ressources_usage: ResourcesUsage::default(),
-            disabled: conf_v1.disabled,
-            enabled: conf_v1.enabled,
-        }
-    }
-}
-
 #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
 /// Dunitrust node configuration
 pub enum DuRsConf {
     /// Dunitrust node configuration v1
-    V1(DuRsConfV1),
+    V1(v1::DuRsConfV1),
     /// Dunitrust node configuration v2
     V2 {
         /// Global configuration
-        global_conf: DuRsConfV2,
+        global_conf: DuRsGlobalConfV2,
         /// Modules configuration
         modules_conf: ModulesConf,
     },
 }
 
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-/// Dunitrust global configuration (without modules configuration)
-pub enum DuRsGlobalConf {
-    /// Dunitrust global configuration v1
-    V1(DuRsConfV1),
-    /// Dunitrust global configuration v2
-    V2(DuRsConfV2),
-}
-
-impl DursGlobalConfTrait for DuRsGlobalConf {
-    fn my_node_id(&self) -> u32 {
-        match *self {
-            DuRsGlobalConf::V1(ref conf_v1) => conf_v1.my_node_id,
-            DuRsGlobalConf::V2(ref conf_v2) => conf_v2.my_node_id,
-        }
-    }
-    fn default_sync_module(&self) -> ModuleName {
-        match *self {
-            DuRsGlobalConf::V1(_) => {
-                fatal_error!("Feature default_sync_module not exist in durs conf v1 !")
-            }
-            DuRsGlobalConf::V2(ref conf_v2) => conf_v2.default_sync_module.clone(),
-        }
-    }
-}
-
 impl Default for DuRsConf {
     #[inline]
     fn default() -> Self {
         DuRsConf::V2 {
-            global_conf: DuRsConfV2::default(),
+            global_conf: DuRsGlobalConfV2::default(),
             modules_conf: ModulesConf::default(),
         }
     }
@@ -261,12 +108,30 @@ impl DursConfTrait for DuRsConf {
             } => DuRsGlobalConf::V2(global_conf.clone()),
         }
     }
+    fn override_global_conf(
+        self,
+        global_user_conf: <Self::GlobalConf as DursGlobalConfTrait>::GlobalUserConf,
+    ) -> Self {
+        match self {
+            DuRsConf::V1(conf_v1) => DuRsConf::V1(conf_v1),
+            DuRsConf::V2 {
+                global_conf,
+                modules_conf,
+            } => {
+                let DuRsGlobalUserConf::V2(global_user_conf_v2) = global_user_conf;
+                DuRsConf::V2 {
+                    global_conf: global_conf.r#override(global_user_conf_v2),
+                    modules_conf,
+                }
+            }
+        }
+    }
     fn upgrade(self) -> (Self, bool) {
         if let DuRsConf::V1(conf_v1) = self {
             let modules_conf = conf_v1.modules.clone();
             (
                 DuRsConf::V2 {
-                    global_conf: DuRsConfV2::from(conf_v1),
+                    global_conf: DuRsGlobalConfV2::from(conf_v1),
                     modules_conf,
                 },
                 true,
@@ -365,81 +230,6 @@ impl DursConfTrait for DuRsConf {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq)]
-/// Keypairs filled in by the user (via a file or by direct entry in the terminal).
-pub struct DuniterKeyPairs {
-    /// Keypair used by the node to sign its communications with other nodes. This keypair is mandatory, if it's not filled in, a random keypair is generated.
-    pub network_keypair: KeyPairEnum,
-    /// Keypair used to sign the blocks forged by this node. If this keypair is'nt filled in, the node will not calculate blocks.
-    pub member_keypair: Option<KeyPairEnum>,
-}
-
-impl Serialize for DuniterKeyPairs {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let member_seed = if let Some(ref member_keypair) = self.member_keypair {
-            member_keypair.seed().to_string()
-        } else {
-            String::from("")
-        };
-        let member_pub = if let Some(ref member_keypair) = self.member_keypair {
-            member_keypair.public_key().to_string()
-        } else {
-            String::from("")
-        };
-        let mut state = serializer.serialize_struct("DuniterKeyPairs", 4)?;
-        state.serialize_field(
-            "network_seed",
-            &self.network_keypair.seed().to_string().as_str(),
-        )?;
-        state.serialize_field(
-            "network_pub",
-            &self.network_keypair.public_key().to_string().as_str(),
-        )?;
-        state.serialize_field("member_seed", member_seed.as_str())?;
-        state.serialize_field("member_pub", member_pub.as_str())?;
-        state.end()
-    }
-}
-
-impl DuniterKeyPairs {
-    /// Returns only the keys indicated as required
-    pub fn get_required_keys_content(
-        required_keys: RequiredKeys,
-        keypairs: DuniterKeyPairs,
-    ) -> RequiredKeysContent {
-        match required_keys {
-            RequiredKeys::MemberKeyPair() => {
-                RequiredKeysContent::MemberKeyPair(keypairs.member_keypair)
-            }
-            RequiredKeys::MemberPublicKey() => {
-                RequiredKeysContent::MemberPublicKey(if let Some(keys) = keypairs.member_keypair {
-                    Some(keys.public_key())
-                } else {
-                    None
-                })
-            }
-            RequiredKeys::NetworkKeyPair() => {
-                RequiredKeysContent::NetworkKeyPair(keypairs.network_keypair)
-            }
-            RequiredKeys::NetworkPublicKey() => {
-                RequiredKeysContent::NetworkPublicKey(keypairs.network_keypair.public_key())
-            }
-            RequiredKeys::None() => RequiredKeysContent::None(),
-        }
-    }
-}
-
-// Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
-fn generate_random_keypair(algo: KeysAlgo) -> KeyPairEnum {
-    match algo {
-        KeysAlgo::Ed25519 => KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair::generate_random()),
-        KeysAlgo::Schnorr => panic!("Schnorr algo not yet supported !"),
-    }
-}
-
 #[inline]
 fn generate_random_node_id() -> u32 {
     rand::gen_u32()
@@ -465,14 +255,6 @@ pub fn get_datas_path(profile_path: PathBuf) -> PathBuf {
     datas_path
 }
 
-#[inline]
-/// Return path to configuration file
-pub fn get_conf_path(profile_path: &PathBuf) -> PathBuf {
-    let mut conf_path = profile_path.clone();
-    conf_path.push(constants::CONF_FILENAME);
-    conf_path
-}
-
 /// Returns the path to the folder containing the user data of the running profile
 // Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
 pub fn get_profile_path(profiles_path: &Option<PathBuf>, profile_name: &str) -> PathBuf {
@@ -503,184 +285,27 @@ pub fn get_profile_path(profiles_path: &Option<PathBuf>, profile_name: &str) ->
     profile_path
 }
 
-/// Get keypairs file path
-pub fn keypairs_filepath(profiles_path: &Option<PathBuf>, profile: &str) -> PathBuf {
-    let profile_path = get_profile_path(profiles_path, profile);
-    let mut conf_keys_path = profile_path;
-    conf_keys_path.push(constants::KEYPAIRS_FILENAME);
-    conf_keys_path
-}
-
 /// Load configuration.
 pub fn load_conf(
     profile_path: PathBuf,
     keypairs_file_path: &Option<PathBuf>,
-) -> Result<(DuRsConf, DuniterKeyPairs), DursConfFileError> {
-    // Load conf
-    let (conf, keypairs) = load_conf_at_path(profile_path, keypairs_file_path)?;
+) -> Result<(DuRsConf, DuniterKeyPairs), DursConfError> {
+    let keypairs = crate::keypairs::load_keypairs_from_file(&profile_path, keypairs_file_path)?;
 
-    // Return conf and keypairs
-    Ok((conf, keypairs))
-}
-
-/// Error with configuration file
-#[derive(Debug, Fail)]
-pub enum DursConfFileError {
-    /// Read error
-    #[fail(display = "fail to read configuration file: {}", _0)]
-    ReadError(std::io::Error),
-    /// Parse error
-    #[fail(display = "fail to parse configuration file: {}", _0)]
-    ParseError(serde_json::Error),
-    /// Write error
-    #[fail(display = "fail to write configuration file: {}", _0)]
-    WriteError(std::io::Error),
-}
-
-/// Load configuration. at specified path
-// Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
-pub fn load_conf_at_path(
-    profile_path: PathBuf,
-    keypairs_file_path: &Option<PathBuf>,
-) -> Result<(DuRsConf, DuniterKeyPairs), DursConfFileError> {
-    // Get KeyPairs
-    let keypairs_path = if let Some(ref keypairs_file_path) = keypairs_file_path {
-        keypairs_file_path.clone()
-    } else {
-        let mut keypairs_path = profile_path.clone();
-        keypairs_path.push(constants::KEYPAIRS_FILENAME);
-        keypairs_path
-    };
-    let keypairs = if keypairs_path.as_path().exists() {
-        if let Ok(mut f) = File::open(keypairs_path.as_path()) {
-            let mut contents = String::new();
-            if f.read_to_string(&mut contents).is_ok() {
-                let json_conf: serde_json::Value =
-                    serde_json::from_str(&contents).expect("Conf: Fail to parse keypairs file !");
-
-                if let Some(network_seed) = json_conf.get("network_seed") {
-                    if let Some(network_pub) = json_conf.get("network_pub") {
-                        let network_seed = network_seed
-                            .as_str()
-                            .expect("Conf: Fail to parse keypairs file !");
-                        let network_pub = network_pub
-                            .as_str()
-                            .expect("Conf: Fail to parse keypairs file !");
-                        let network_keypair = KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
-                            seed: Seed32::from_base58(network_seed)
-                                .expect("conf : keypairs file : fail to parse network_seed !"),
-                            pubkey: ed25519::PublicKey::from_base58(network_pub)
-                                .expect("conf : keypairs file : fail to parse network_pub !"),
-                        });
-
-                        let member_keypair = if let Some(member_seed) = json_conf.get("member_seed")
-                        {
-                            if let Some(member_pub) = json_conf.get("member_pub") {
-                                let member_seed = member_seed
-                                    .as_str()
-                                    .expect("Conf: Fail to parse keypairs file !");
-                                let member_pub = member_pub
-                                    .as_str()
-                                    .expect("Conf: Fail to parse keypairs file !");
-                                if member_seed.is_empty() || member_pub.is_empty() {
-                                    None
-                                } else {
-                                    Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
-                                        seed: Seed32::from_base58(member_seed).expect(
-                                            "conf : keypairs file : fail to parse member_seed !",
-                                        ),
-                                        pubkey: ed25519::PublicKey::from_base58(member_pub).expect(
-                                            "conf : keypairs file : fail to parse member_pub !",
-                                        ),
-                                    }))
-                                }
-                            } else {
-                                panic!("Fatal error : keypairs file wrong format : no field salt !")
-                            }
-                        } else {
-                            panic!("Fatal error : keypairs file wrong format : no field password !")
-                        };
+    // Load conf from file
+    let conf_from_file =
+        crate::file::load_conf_from_file(profile_path).map_err(DursConfError::FileErr)?;
 
-                        // Create keypairs file with random keypair
-                        DuniterKeyPairs {
-                            network_keypair,
-                            member_keypair,
-                        }
-                    } else {
-                        panic!("Fatal error : keypairs file wrong format : no field salt !")
-                    }
-                } else {
-                    panic!("Fatal error : keypairs file wrong format : no field password !")
-                }
-            } else {
-                panic!("Fail to read keypairs file !");
-            }
-        } else {
-            panic!("Fail to open keypairs file !");
-        }
-    } else {
-        // Create keypairs file with random keypair
-        let keypairs = DuniterKeyPairs {
-            network_keypair: generate_random_keypair(KeysAlgo::Ed25519),
-            member_keypair: None,
-        };
-        write_keypairs_file(&keypairs_path, &keypairs).unwrap_or_else(|_| {
-            panic!(dbg!("Fatal error : fail to write default keypairs file !"))
-        });
-        keypairs
-    };
+    // Try to load global user conf from env vars
+    let env_global_user_conf =
+        env::load_env_global_user_conf().map_err(DursConfError::EnvVarErr)?;
 
-    // Open conf file
-    let mut conf_path = profile_path;
-    conf_path.push(constants::CONF_FILENAME);
-    let conf = if conf_path.as_path().exists() {
-        match File::open(conf_path.as_path()) {
-            Ok(mut f) => {
-                let mut contents = String::new();
-                f.read_to_string(&mut contents)
-                    .map_err(DursConfFileError::ReadError)?;
-                // Parse conf file
-                let conf: DuRsConf =
-                    serde_json::from_str(&contents).map_err(DursConfFileError::ParseError)?;
-                // Upgrade conf to latest version
-                let (conf, upgraded) = conf.upgrade();
-                // If conf is upgraded, rewrite conf file
-                if upgraded {
-                    write_conf_file(conf_path.as_path(), &conf)
-                        .map_err(DursConfFileError::WriteError)?;
-                }
-                conf
-            }
-            Err(e) => return Err(DursConfFileError::ReadError(e)),
-        }
-    } else {
-        // Create conf file with default conf
-        let conf = DuRsConf::default();
-        write_conf_file(conf_path.as_path(), &conf)
-            .unwrap_or_else(|_| panic!(dbg!("Fatal error : fail to write default conf file!")));
-        conf
-    };
+    // Override global conf with env global user conf
+    let conf = conf_from_file.override_global_conf(env_global_user_conf);
 
-    // Return conf and keypairs
     Ok((conf, keypairs))
 }
 
-/// Save keypairs in profile folder
-// Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
-pub fn write_keypairs_file(
-    file_path: &PathBuf,
-    keypairs: &DuniterKeyPairs,
-) -> Result<(), std::io::Error> {
-    let mut f = File::create(file_path.as_path())?;
-    f.write_all(
-        serde_json::to_string_pretty(keypairs)
-            .unwrap_or_else(|_| panic!(dbg!("Fatal error : fail to deserialize keypairs !")))
-            .as_bytes(),
-    )?;
-    f.sync_all()?;
-    Ok(())
-}
-
 /// Write new module conf
 pub fn write_new_module_conf<DC: DursConfTrait>(
     conf: &mut DC,
@@ -691,22 +316,8 @@ pub fn write_new_module_conf<DC: DursConfTrait>(
     conf.set_module_conf(module_name, new_module_conf);
     let mut conf_path = profile_path;
     conf_path.push(crate::constants::CONF_FILENAME);
-    write_conf_file(conf_path.as_path(), conf).expect("Fail to write new conf file ! ");
-}
-
-/// Save configuration in profile folder
-pub fn write_conf_file<DC: DursConfTrait>(
-    conf_path: &Path,
-    conf: &DC,
-) -> Result<(), std::io::Error> {
-    let mut f = File::create(conf_path)?;
-    f.write_all(
-        serde_json::to_string_pretty(conf)
-            .expect("Fatal error : fail to write default conf file !")
-            .as_bytes(),
-    )?;
-    f.sync_all()?;
-    Ok(())
+    crate::file::write_conf_file(conf_path.as_path(), conf)
+        .expect("Fail to write new conf file ! ");
 }
 
 /// Returns the path to the database containing the blockchain
@@ -722,95 +333,3 @@ pub fn get_blockchain_db_path(profile_path: PathBuf) -> PathBuf {
     }
     db_path
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use serde_json::json;
-
-    #[inline]
-    fn save_old_conf(profile_path: PathBuf) -> std::io::Result<()> {
-        let mut conf_path = profile_path.clone();
-        conf_path.push(constants::CONF_FILENAME);
-        let mut conf_sav_path = profile_path;
-        conf_sav_path.push("conf-sav.json");
-        std::fs::copy(conf_path.as_path(), conf_sav_path.as_path())?;
-        Ok(())
-    }
-
-    fn restore_old_conf_and_save_upgraded_conf(profile_path: PathBuf) -> std::io::Result<()> {
-        let mut conf_path = profile_path.clone();
-        conf_path.push(constants::CONF_FILENAME);
-        let mut conf_sav_path = profile_path.clone();
-        conf_sav_path.push("conf-sav.json");
-        let mut conf_upgraded_path = profile_path;
-        conf_upgraded_path.push("conf-upgraded.json");
-        std::fs::copy(conf_path.as_path(), &conf_upgraded_path.as_path())?;
-        std::fs::copy(conf_sav_path.as_path(), &conf_path.as_path())?;
-        std::fs::remove_file(conf_sav_path.as_path())?;
-        Ok(())
-    }
-
-    #[test]
-    fn load_conf_file_v1() -> Result<(), DursConfFileError> {
-        let profile_path = PathBuf::from("./test/v1/");
-        save_old_conf(PathBuf::from(profile_path.clone()))
-            .map_err(DursConfFileError::WriteError)?;
-        let (conf, _keys) = load_conf_at_path(profile_path.clone(), &None)?;
-        assert_eq!(
-            conf.modules()
-                .get("ws2p")
-                .expect("Not found ws2p conf")
-                .clone(),
-            json!({
-                "sync_endpoints": [
-                {
-                    "endpoint": "WS2P c1c39a0a i3.ifee.fr 80 /ws2p",
-                    "pubkey": "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx"
-                },
-                {
-                    "endpoint": "WS2P 15af24db g1.ifee.fr 80 /ws2p",
-                    "pubkey": "BoZP6aqtErHjiKLosLrQxBafi4ATciyDZQ6XRQkNefqG"
-                },
-                {
-                    "endpoint": "WS2P b48824f0 g1.monnaielibreoccitanie.org 80 /ws2p",
-                    "pubkey": "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef"
-                }
-                ]
-            })
-        );
-        restore_old_conf_and_save_upgraded_conf(profile_path)
-            .map_err(DursConfFileError::WriteError)?;
-
-        Ok(())
-    }
-
-    #[test]
-    fn load_conf_file_v2() -> Result<(), DursConfFileError> {
-        let profile_path = PathBuf::from("./test/v2/");
-        let (conf, _keys) = load_conf_at_path(profile_path, &None)?;
-        assert_eq!(
-            conf.modules()
-                .get("ws2p")
-                .expect("Not found ws2p conf")
-                .clone(),
-            json!({
-                "sync_endpoints": [
-                {
-                    "endpoint": "WS2P c1c39a0a i3.ifee.fr 80 /ws2p",
-                    "pubkey": "D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx"
-                },
-                {
-                    "endpoint": "WS2P 15af24db g1.ifee.fr 80 /ws2p",
-                    "pubkey": "BoZP6aqtErHjiKLosLrQxBafi4ATciyDZQ6XRQkNefqG"
-                },
-                {
-                    "endpoint": "WS2P b48824f0 g1.monnaielibreoccitanie.org 80 /ws2p",
-                    "pubkey": "7v2J4badvfWQ6qwRdCwhhJfAsmKwoxRUNpJHiJHj7zef"
-                }
-                ]
-            })
-        );
-        Ok(())
-    }
-}
diff --git a/lib/core/conf/src/modules_conf.rs b/lib/core/conf/src/modules_conf.rs
new file mode 100644
index 0000000000000000000000000000000000000000..38e975b0c38a189261b732d86635d365ce64e66c
--- /dev/null
+++ b/lib/core/conf/src/modules_conf.rs
@@ -0,0 +1,46 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust modules configuration
+
+use durs_module::ModuleName;
+
+#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
+/// Modules conf
+pub struct ModulesConf(pub serde_json::Value);
+
+impl Default for ModulesConf {
+    #[inline]
+    fn default() -> Self {
+        ModulesConf(serde_json::Value::Null)
+    }
+}
+
+impl ModulesConf {
+    /// Change module conf
+    pub fn set_module_conf(&mut self, module_name: ModuleName, new_module_conf: serde_json::Value) {
+        if self.0.is_null() {
+            let mut new_modules_conf = serde_json::Map::with_capacity(1);
+            new_modules_conf.insert(module_name.0, new_module_conf);
+            self.0 = serde_json::value::to_value(new_modules_conf)
+                .expect("Fail to create map of new modules conf !");
+        } else {
+            self.0
+                .as_object_mut()
+                .expect("Conf file currupted !")
+                .insert(module_name.0, new_module_conf);
+        }
+    }
+}
diff --git a/lib/core/conf/src/resources.rs b/lib/core/conf/src/resources.rs
new file mode 100644
index 0000000000000000000000000000000000000000..75a1e84cee32af4a5e3bdc8cb04a00fe6d79db35
--- /dev/null
+++ b/lib/core/conf/src/resources.rs
@@ -0,0 +1,53 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust resources usage configuration
+
+#[derive(Debug, Copy, Clone, Deserialize, PartialEq, Serialize)]
+/// Ressource usage
+pub enum ResourceUsage {
+    /// Minimal use of the resource, to the detriment of performance
+    Minimal,
+    /// Trade-off between resource use and performance
+    Medium,
+    /// A performance-oriented trade-off, the use of the resource is slightly limited
+    Large,
+    /// No restrictions on the use of the resource, maximizes performance
+    Infinite,
+}
+
+#[derive(Debug, Copy, Clone, Deserialize, PartialEq, Serialize)]
+/// Ressources usage
+pub struct ResourcesUsage {
+    /// Cpu usage
+    pub cpu_usage: ResourceUsage,
+    /// Network usage
+    pub network_usage: ResourceUsage,
+    /// Memory usage
+    pub memory_usage: ResourceUsage,
+    /// Disk space usage
+    pub disk_space_usage: ResourceUsage,
+}
+
+impl Default for ResourcesUsage {
+    fn default() -> Self {
+        ResourcesUsage {
+            cpu_usage: ResourceUsage::Large,
+            network_usage: ResourceUsage::Large,
+            memory_usage: ResourceUsage::Large,
+            disk_space_usage: ResourceUsage::Large,
+        }
+    }
+}
diff --git a/lib/core/conf/src/v1.rs b/lib/core/conf/src/v1.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b68367763e0772047f8c23a3db6e84ac5eed1c53
--- /dev/null
+++ b/lib/core/conf/src/v1.rs
@@ -0,0 +1,48 @@
+//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Dunitrust configuration v1
+
+use crate::modules_conf::ModulesConf;
+use dubp_currency_params::CurrencyName;
+use durs_module::ModuleName;
+use std::collections::HashSet;
+
+#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
+/// Duniter configuration v1
+pub struct DuRsConfV1 {
+    /// Currency name
+    pub currency: CurrencyName,
+    /// Duniter node unique identifier
+    pub my_node_id: u32,
+    /// Configuration of modules in json format (obtained from the conf.json file)
+    pub modules: ModulesConf,
+    /// Disabled modules
+    pub disabled: HashSet<ModuleName>,
+    /// Enabled modules
+    pub enabled: HashSet<ModuleName>,
+}
+
+impl Default for DuRsConfV1 {
+    fn default() -> Self {
+        DuRsConfV1 {
+            currency: CurrencyName(String::from(crate::constants::DEFAULT_CURRENCY)),
+            my_node_id: crate::generate_random_node_id(),
+            modules: ModulesConf::default(),
+            disabled: HashSet::with_capacity(0),
+            enabled: HashSet::with_capacity(0),
+        }
+    }
+}
diff --git a/lib/core/core/src/change_conf.rs b/lib/core/core/src/change_conf.rs
index 9e6c9d644b06cd5ae018a8416ddfe9e352ed4539..cd12fc0c9adad53b79e7a41e00ca037c86613fc8 100644
--- a/lib/core/core/src/change_conf.rs
+++ b/lib/core/core/src/change_conf.rs
@@ -34,6 +34,6 @@ pub fn change_global_conf<DC: DursConfTrait>(
     }
 
     // Write new conf
-    durs_conf::write_conf_file(&durs_conf::get_conf_path(profile_path), conf)
+    durs_conf::file::write_conf_file(&durs_conf::file::get_conf_path(profile_path), conf)
         .map_err(DursCoreError::FailUpdateConf)
 }
diff --git a/lib/core/core/src/commands/keys.rs b/lib/core/core/src/commands/keys.rs
index 8bf320f9a0182d0df4581467fb4823bd22a2d020..61736c8978c51c4ea9a310b8aae210964007cb51 100644
--- a/lib/core/core/src/commands/keys.rs
+++ b/lib/core/core/src/commands/keys.rs
@@ -20,7 +20,7 @@ use crate::errors::DursCoreError;
 use crate::DursCore;
 use clap::arg_enum;
 use clear_on_drop::clear::Clear;
-use durs_conf::keys::*;
+use durs_conf::keypairs::cli::*;
 use durs_conf::DuRsConf;
 
 #[derive(StructOpt, Debug, Clone)]
diff --git a/lib/core/core/src/errors.rs b/lib/core/core/src/errors.rs
index 9021d4c14fedf24a91b4748fb91a2033f4b47859..9e40dd0e69e61eca4a37143fad08569106380441 100644
--- a/lib/core/core/src/errors.rs
+++ b/lib/core/core/src/errors.rs
@@ -17,16 +17,13 @@
 
 use crate::logger::InitLoggerError;
 use dubp_currency_params::db::CurrencyParamsDbError;
-use durs_conf::keys::WizardError;
+use durs_conf::keypairs::cli::WizardError;
 use durs_module::{ModuleStaticName, PlugModuleError};
 use failure::{Error, Fail};
 
 #[derive(Debug, Fail)]
 /// Dunitrust server error
 pub enum DursCoreError {
-    /// Error with configuration file
-    #[fail(display = "Error with configuration file: {}", _0)]
-    ConfFileError(durs_conf::DursConfFileError),
     /// Generic error that impl Fail
     #[fail(display = "{}", _0)]
     Error(Error),
@@ -54,6 +51,9 @@ pub enum DursCoreError {
     /// Error on initialization of the logger
     #[fail(display = "Error on initialization of the logger: {}", _0)]
     InitLoggerError(InitLoggerError),
+    /// Error at configuration loading
+    #[fail(display = "Error at configuration loading: {}", _0)]
+    LoadConfError(durs_conf::DursConfError),
     /// Plug module error
     #[fail(display = "Error on loading module '{}': {}", module_name, error)]
     PlugModuleError {
diff --git a/lib/core/core/src/lib.rs b/lib/core/core/src/lib.rs
index 74b4779c264b88faa0320d71a0dd40a103311d58..edb2da353912e56011a09dee70550890752c20b8 100644
--- a/lib/core/core/src/lib.rs
+++ b/lib/core/core/src/lib.rs
@@ -45,7 +45,7 @@ use dubp_currency_params::CurrencyName;
 use durs_bc::{dbex::DbExQuery, BlockchainModule};
 use durs_common_tools::fatal_error;
 pub use durs_conf::{
-    constants::KEYPAIRS_FILENAME, keys::*, ChangeGlobalConf, DuRsConf, DuniterKeyPairs,
+    constants::KEYPAIRS_FILENAME, keypairs::cli::*, ChangeGlobalConf, DuRsConf, DuniterKeyPairs,
 };
 use durs_message::*;
 use durs_module::*;
@@ -246,7 +246,7 @@ impl DursCore<DuRsConf> {
         // Load global conf
         let (conf, keypairs) =
             durs_conf::load_conf(profile_path.clone(), &durs_core_opts.keypairs_file)
-                .map_err(DursCoreError::ConfFileError)?;
+                .map_err(DursCoreError::LoadConfError)?;
         info!("Success to load global conf.");
 
         // Get currency name
diff --git a/lib/core/core/src/router.rs b/lib/core/core/src/router.rs
index 1baf6ad2a09db9fc803a22a7e460ed868535b418..db662040f00fe538ff8c07fd9261a195426450fb 100644
--- a/lib/core/core/src/router.rs
+++ b/lib/core/core/src/router.rs
@@ -238,13 +238,13 @@ fn start_conf_thread(
     mut conf: DuRsConf,
     receiver: &mpsc::Receiver<DursMsg>,
 ) {
-    let conf_path = durs_conf::get_conf_path(&profile_path);
+    let conf_path = durs_conf::file::get_conf_path(&profile_path);
     loop {
         match receiver.recv() {
             Ok(msg) => {
                 if let DursMsg::SaveNewModuleConf(module_static_name, new_json_conf) = msg {
                     conf.set_module_conf(ModuleName(module_static_name.to_string()), new_json_conf);
-                    durs_conf::write_conf_file(&conf_path, &conf)
+                    durs_conf::file::write_conf_file(&conf_path, &conf)
                         .expect("Fail to write new module conf in conf file ! ");
                 }
             }
diff --git a/lib/core/module/src/lib.rs b/lib/core/module/src/lib.rs
index b1d6c07ea927837cd42fdd1efdcf705571c0af6a..23360f7c441eb173e16a9626cef7b7c1a7f21182 100644
--- a/lib/core/module/src/lib.rs
+++ b/lib/core/module/src/lib.rs
@@ -109,6 +109,9 @@ impl ToString for ModuleReqFullId {
 pub trait DursGlobalConfTrait:
     Clone + Debug + PartialEq + Serialize + DeserializeOwned + Send + ToOwned
 {
+    /// Global user configuration
+    type GlobalUserConf;
+
     /// Get node id
     fn my_node_id(&self) -> u32;
     /// Get default sync module
@@ -130,16 +133,21 @@ pub trait DursConfTrait:
     fn enable(&mut self, module: ModuleName);
     /// Get enabled modules
     fn enabled_modules(&self) -> HashSet<ModuleName>;
+    /// Get currency name
+    fn get_currency(&self) -> CurrencyName;
     /// Get global conf
     fn get_global_conf(&self) -> Self::GlobalConf;
+    /// Override global configuration
+    fn override_global_conf(
+        self,
+        global_user_conf: <Self::GlobalConf as DursGlobalConfTrait>::GlobalUserConf,
+    ) -> Self;
     /// Get modules conf
     fn modules(&self) -> serde_json::Value;
     /// Get node id
     fn my_node_id(&self) -> u32 {
         self.get_global_conf().my_node_id()
     }
-    /// Get currency name
-    fn get_currency(&self) -> CurrencyName;
     /// Set currency
     fn set_currency(&mut self, new_currency: CurrencyName);
     /// Change module conf
diff --git a/lib/modules/blockchain/blockchain/src/sync/mod.rs b/lib/modules/blockchain/blockchain/src/sync/mod.rs
index 75d12308b0a540784406f0845c7f7003e7f5c3a2..77f4deed445a2988563b9b6c4a6b741d81bb77c8 100644
--- a/lib/modules/blockchain/blockchain/src/sync/mod.rs
+++ b/lib/modules/blockchain/blockchain/src/sync/mod.rs
@@ -180,7 +180,7 @@ pub fn local_sync<DC: DursConfTrait>(
     // Write new conf
     let mut conf_path = profile_path.clone();
     conf_path.push(durs_conf::constants::CONF_FILENAME);
-    durs_conf::write_conf_file(conf_path.as_path(), &conf).expect("Fail to write new conf !");
+    durs_conf::file::write_conf_file(conf_path.as_path(), &conf).expect("Fail to write new conf !");
 
     // Open database
     let db = open_db(&db_path.as_path()).map_err(|_| LocalSyncError::FailToOpenDB)?;