diff --git a/etc/spack/defaults/config.yaml b/etc/spack/defaults/config.yaml
index 6a749b5f6d75212f6123b1c8a8de583ee27b5545..85019ede6120b7c27fffba071e170a0c2c8b850a 100644
--- a/etc/spack/defaults/config.yaml
+++ b/etc/spack/defaults/config.yaml
@@ -14,17 +14,18 @@
 #   ~/.spack/config.yaml
 # -------------------------------------------------------------------------
 config:
-
-  # Precedence of configuration scopes, high to low.
-  # The user can override this paradoxically.
-  # scopes: [user, spack, default]
-
-
   # This is the path to the root of the Spack install tree.
   # You can use $spack here to refer to the root of the spack instance.
   install_tree: $spack/opt/spack
 
 
+  # Locations where different types of modules should be installed.
+  module_roots:
+    tcl:    $spack/share/spack/modules
+    lmod:   $spack/share/spack/lmod
+    dotkit: $spack/share/spack/dotkit
+
+
   # Temporary locations Spack can try to use for builds.
   #
   # Spack will use the first one it finds that exists and is writable.
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
index c6fa84109e4eb1ebb733491ea85e8d6e60ceebdb..d7abe0fa871ece117e0a4bde616ddfd3d625f686 100644
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -210,7 +210,8 @@ def refresh(mtype, specs, args):
     cls = module_types[mtype]
 
     # Detect name clashes
-    writers = [cls(spec) for spec in specs]
+    writers = [cls(spec) for spec in specs
+               if spack.repo.exists(spec.name)]  # skip unknown packages.
     file2writer = collections.defaultdict(list)
     for item in writers:
         file2writer[item.file_name].append(item)
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index cf67ca905d9676e7b9a714f31c07b848da579dc5..2c2804aea10d32c4399c2defb2b01d977f4aa6e0 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -48,10 +48,12 @@
 import textwrap
 
 import llnl.util.tty as tty
+from llnl.util.filesystem import join_path, mkdirp
+
 import spack
 import spack.compilers  # Needed by LmodModules
 import spack.config
-from llnl.util.filesystem import join_path, mkdirp
+from spack.util.path import canonicalize_path
 from spack.build_environment import parent_class_modules
 from spack.build_environment import set_module_variables_for_package
 from spack.environment import *
@@ -62,7 +64,11 @@
    metaclass."""
 module_types = {}
 
-CONFIGURATION = spack.config.get_config('modules')
+"""Module install roots are in config.yaml."""
+_roots = spack.config.get_config('config').get('module_roots', {})
+
+"""Specifics about modules are in modules.yaml"""
+_module_config = spack.config.get_config('modules')
 
 
 def print_help():
@@ -92,7 +98,7 @@ def inspect_path(prefix):
     """
     env = EnvironmentModifications()
     # Inspect the prefix to check for the existence of common directories
-    prefix_inspections = CONFIGURATION.get('prefix_inspections', {})
+    prefix_inspections = _module_config.get('prefix_inspections', {})
     for relative_path, variables in prefix_inspections.items():
         expected = join_path(prefix, relative_path)
         if os.path.isdir(expected):
@@ -168,7 +174,7 @@ def parse_config_options(module_generator):
         module file
     """
     # Get the configuration for this kind of generator
-    module_configuration = copy.deepcopy(CONFIGURATION.get(
+    module_configuration = copy.deepcopy(_module_config.get(
         module_generator.name, {}))
 
     #####
@@ -248,7 +254,7 @@ class __metaclass__(type):
 
         def __init__(cls, name, bases, dict):
             type.__init__(cls, name, bases, dict)
-            if cls.name != 'env_module' and cls.name in CONFIGURATION[
+            if cls.name != 'env_module' and cls.name in _module_config[
                     'enable']:
                 module_types[cls.name] = cls
 
@@ -271,7 +277,7 @@ def __init__(self, spec=None):
     @property
     def naming_scheme(self):
         try:
-            naming_scheme = CONFIGURATION[self.name]['naming_scheme']
+            naming_scheme = _module_config[self.name]['naming_scheme']
         except KeyError:
             naming_scheme = self.default_naming_format
         return naming_scheme
@@ -314,7 +320,7 @@ def category(self):
 
     @property
     def blacklisted(self):
-        configuration = CONFIGURATION.get(self.name, {})
+        configuration = _module_config.get(self.name, {})
         whitelist_matches = [x
                              for x in configuration.get('whitelist', [])
                              if self.spec.satisfies(x)]
@@ -473,7 +479,9 @@ def remove(self):
 
 class Dotkit(EnvModule):
     name = 'dotkit'
-    path = join_path(spack.share_path, 'dotkit')
+    path = canonicalize_path(
+        _roots.get(name, join_path(spack.share_path, name)))
+
     environment_modifications_formats = {
         PrependPath: 'dk_alter {name} {value}\n',
         RemovePath: 'dk_unalter {name} {value}\n',
@@ -516,7 +524,8 @@ def prerequisite(self, spec):
 
 class TclModule(EnvModule):
     name = 'tcl'
-    path = join_path(spack.share_path, "modules")
+    path = canonicalize_path(
+        _roots.get(name, join_path(spack.share_path, 'modules')))
 
     autoload_format = ('if ![ is-loaded {module_file} ] {{\n'
                        '    puts stderr "Autoloading {module_file}"\n'
@@ -635,7 +644,8 @@ def module_specific_content(self, configuration):
 
 class LmodModule(EnvModule):
     name = 'lmod'
-    path = join_path(spack.share_path, "lmod")
+    path = canonicalize_path(
+        _roots.get(name, join_path(spack.share_path, name)))
 
     environment_modifications_formats = {
         PrependPath: 'prepend_path("{name}", "{value}")\n',
@@ -656,6 +666,12 @@ class LmodModule(EnvModule):
 
     path_part_without_hash = join_path('{token.name}', '{token.version}')
 
+    # TODO : Check that extra tokens specified in configuration file
+    # TODO : are actually virtual dependencies
+    configuration = _module_config.get('lmod', {})
+    hierarchy_tokens = configuration.get('hierarchical_scheme', [])
+    hierarchy_tokens = hierarchy_tokens + ['mpi', 'compiler']
+
     def __init__(self, spec=None):
         super(LmodModule, self).__init__(spec)
 
diff --git a/lib/spack/spack/schema/config.py b/lib/spack/spack/schema/config.py
index 7ae3b75c3e763df2748e3177fd976f5fa21f543f..a8057f303c056d3954306e11b5f61f9ae46e7fcc 100644
--- a/lib/spack/spack/schema/config.py
+++ b/lib/spack/spack/schema/config.py
@@ -42,6 +42,16 @@
                         {'type': 'array',
                          'items': {'type': 'string'}}],
                 },
+                'module_roots': {
+                    'type': 'object',
+                    'default': {},
+                    'additionalProperties': False,
+                    'properties': {
+                        'tcl': {'type': 'string'},
+                        'lmod': {'type': 'string'},
+                        'dotkit': {'type': 'string'},
+                    },
+                },
                 'source_cache': {'type': 'string'},
                 'misc_cache': {'type': 'string'},
                 'verify_ssl': {
diff --git a/lib/spack/spack/test/modules.py b/lib/spack/spack/test/modules.py
index cdaeef33391ec3ecf883f09b3e13489dfd8ec3a8..cb3a26e62b72b3934c8763f07ca57a157c8e3983 100644
--- a/lib/spack/spack/test/modules.py
+++ b/lib/spack/spack/test/modules.py
@@ -102,18 +102,18 @@ class ModuleFileGeneratorTests(MockPackagesTest):
 
     def setUp(self):
         super(ModuleFileGeneratorTests, self).setUp()
-        self.configuration_instance = spack.modules.CONFIGURATION
+        self.configuration_instance = spack.modules._module_config
         self.module_types_instance = spack.modules.module_types
         spack.modules.open = mock_open
         spack.modules.mkdirp = lambda x: None
         # Make sure that a non-mocked configuration will trigger an error
-        spack.modules.CONFIGURATION = None
+        spack.modules._module_config = None
         spack.modules.module_types = {self.factory.name: self.factory}
 
     def tearDown(self):
         del spack.modules.open
         spack.modules.module_types = self.module_types_instance
-        spack.modules.CONFIGURATION = self.configuration_instance
+        spack.modules._module_config = self.configuration_instance
         spack.modules.mkdirp = llnl.util.filesystem.mkdirp
         super(ModuleFileGeneratorTests, self).tearDown()
 
@@ -231,7 +231,7 @@ class TclTests(ModuleFileGeneratorTests):
     }
 
     def test_simple_case(self):
-        spack.modules.CONFIGURATION = self.configuration_autoload_direct
+        spack.modules._module_config = self.configuration_autoload_direct
         spec = spack.spec.Spec(mpich_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertTrue('module-whatis "mpich @3.0.4"' in content)
@@ -239,13 +239,13 @@ def test_simple_case(self):
                           spec, 'non-existing-tag')
 
     def test_autoload(self):
-        spack.modules.CONFIGURATION = self.configuration_autoload_direct
+        spack.modules._module_config = self.configuration_autoload_direct
         spec = spack.spec.Spec(mpileaks_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'is-loaded' in x]), 2)
         self.assertEqual(len([x for x in content if 'module load ' in x]), 2)
 
-        spack.modules.CONFIGURATION = self.configuration_autoload_all
+        spack.modules._module_config = self.configuration_autoload_all
         spec = spack.spec.Spec(mpileaks_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'is-loaded' in x]), 5)
@@ -256,7 +256,7 @@ def test_autoload(self):
         # - 1 ('build','link') dependency
         # - 1 ('build',) dependency
         # Just make sure the 'build' dependency is not there
-        spack.modules.CONFIGURATION = self.configuration_autoload_direct
+        spack.modules._module_config = self.configuration_autoload_direct
         spec = spack.spec.Spec('dtbuild1')
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'is-loaded' in x]), 2)
@@ -267,25 +267,25 @@ def test_autoload(self):
         # - 1 ('build','link') dependency
         # - 1 ('build',) dependency
         # Just make sure the 'build' dependency is not there
-        spack.modules.CONFIGURATION = self.configuration_autoload_all
+        spack.modules._module_config = self.configuration_autoload_all
         spec = spack.spec.Spec('dtbuild1')
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'is-loaded' in x]), 2)
         self.assertEqual(len([x for x in content if 'module load ' in x]), 2)
 
     def test_prerequisites(self):
-        spack.modules.CONFIGURATION = self.configuration_prerequisites_direct
+        spack.modules._module_config = self.configuration_prerequisites_direct
         spec = spack.spec.Spec('mpileaks arch=x86-linux')
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'prereq' in x]), 2)
 
-        spack.modules.CONFIGURATION = self.configuration_prerequisites_all
+        spack.modules._module_config = self.configuration_prerequisites_all
         spec = spack.spec.Spec('mpileaks arch=x86-linux')
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'prereq' in x]), 5)
 
     def test_alter_environment(self):
-        spack.modules.CONFIGURATION = self.configuration_alter_environment
+        spack.modules._module_config = self.configuration_alter_environment
         spec = spack.spec.Spec('mpileaks platform=test target=x86_64')
         content = self.get_modulefile_content(spec)
         self.assertEqual(
@@ -315,7 +315,7 @@ def test_alter_environment(self):
             len([x for x in content if 'setenv LIBDWARF_ROOT' in x]), 1)
 
     def test_blacklist(self):
-        spack.modules.CONFIGURATION = self.configuration_blacklist
+        spack.modules._module_config = self.configuration_blacklist
         spec = spack.spec.Spec('mpileaks ^zmpi')
         content = self.get_modulefile_content(spec)
         self.assertEqual(len([x for x in content if 'is-loaded' in x]), 1)
@@ -329,7 +329,7 @@ def test_blacklist(self):
         self.assertEqual(len([x for x in content if 'module load ' in x]), 1)
 
     def test_conflicts(self):
-        spack.modules.CONFIGURATION = self.configuration_conflicts
+        spack.modules._module_config = self.configuration_conflicts
         spec = spack.spec.Spec('mpileaks')
         content = self.get_modulefile_content(spec)
         self.assertEqual(
@@ -339,11 +339,11 @@ def test_conflicts(self):
         self.assertEqual(
             len([x for x in content if x == 'conflict intel/14.0.1']), 1)
 
-        spack.modules.CONFIGURATION = self.configuration_wrong_conflicts
+        spack.modules._module_config = self.configuration_wrong_conflicts
         self.assertRaises(SystemExit, self.get_modulefile_content, spec)
 
     def test_suffixes(self):
-        spack.modules.CONFIGURATION = self.configuration_suffix
+        spack.modules._module_config = self.configuration_suffix
         spec = spack.spec.Spec('mpileaks+debug arch=x86-linux')
         spec.concretize()
         generator = spack.modules.TclModule(spec)
@@ -412,7 +412,7 @@ class LmodTests(ModuleFileGeneratorTests):
     }
 
     def test_simple_case(self):
-        spack.modules.CONFIGURATION = self.configuration_autoload_direct
+        spack.modules._module_config = self.configuration_autoload_direct
         spec = spack.spec.Spec(mpich_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertTrue('-- -*- lua -*-' in content)
@@ -420,14 +420,14 @@ def test_simple_case(self):
         self.assertTrue('whatis([[Version : 3.0.4]])' in content)
 
     def test_autoload(self):
-        spack.modules.CONFIGURATION = self.configuration_autoload_direct
+        spack.modules._module_config = self.configuration_autoload_direct
         spec = spack.spec.Spec(mpileaks_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertEqual(
             len([x for x in content if 'if not isloaded(' in x]), 2)
         self.assertEqual(len([x for x in content if 'load(' in x]), 2)
 
-        spack.modules.CONFIGURATION = self.configuration_autoload_all
+        spack.modules._module_config = self.configuration_autoload_all
         spec = spack.spec.Spec(mpileaks_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertEqual(
@@ -435,7 +435,7 @@ def test_autoload(self):
         self.assertEqual(len([x for x in content if 'load(' in x]), 5)
 
     def test_alter_environment(self):
-        spack.modules.CONFIGURATION = self.configuration_alter_environment
+        spack.modules._module_config = self.configuration_alter_environment
         spec = spack.spec.Spec('mpileaks platform=test target=x86_64')
         content = self.get_modulefile_content(spec)
         self.assertEqual(
@@ -460,7 +460,7 @@ def test_alter_environment(self):
             len([x for x in content if 'unsetenv("BAR")' in x]), 0)
 
     def test_blacklist(self):
-        spack.modules.CONFIGURATION = self.configuration_blacklist
+        spack.modules._module_config = self.configuration_blacklist
         spec = spack.spec.Spec(mpileaks_spec_string)
         content = self.get_modulefile_content(spec)
         self.assertEqual(
@@ -499,14 +499,14 @@ class DotkitTests(MockPackagesTest):
 
     def setUp(self):
         super(DotkitTests, self).setUp()
-        self.configuration_obj = spack.modules.CONFIGURATION
+        self.configuration_obj = spack.modules._module_config
         spack.modules.open = mock_open
         # Make sure that a non-mocked configuration will trigger an error
-        spack.modules.CONFIGURATION = None
+        spack.modules._module_config = None
 
     def tearDown(self):
         del spack.modules.open
-        spack.modules.CONFIGURATION = self.configuration_obj
+        spack.modules._module_config = self.configuration_obj
         super(DotkitTests, self).tearDown()
 
     def get_modulefile_content(self, spec):
@@ -517,7 +517,7 @@ def get_modulefile_content(self, spec):
         return content
 
     def test_dotkit(self):
-        spack.modules.CONFIGURATION = self.configuration_dotkit
+        spack.modules._module_config = self.configuration_dotkit
         spec = spack.spec.Spec('mpileaks arch=x86-linux')
         content = self.get_modulefile_content(spec)
         self.assertTrue('#c spack' in content)