diff --git a/modules.env b/modules.env
index 8e943649ad..afbfe3c28c 100644
--- a/modules.env
+++ b/modules.env
@@ -23,27 +23,7 @@
 
 # Source modules should use tags, explicit refs or remote branches because
 # we do not update local branches in this script.
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-apache"]="0.0.4"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-apt"]="1.4.2"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-concat"]="1.1.0"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-firewall"]="1.1.3"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-haproxy"]="0.4.1"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-inifile"]="1.1.3"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-mysql"]="0.6.1"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-ntp"]="3.1.2"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-postgresql"]="3.4.2"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-stdlib"]="4.3.2"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-puppetdb"]="3.0.1"
-SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-rabbitmq"]="5.0.0"
-SOURCE_MODULES["https://github.com/puppet-community/puppet-module-puppetboard"]="2.4.0"
-SOURCE_MODULES["https://github.com/saz/puppet-memcached"]="a0d4bdca6283d64acb484bb7671c0305cafd76b4"
-SOURCE_MODULES["https://github.com/rafaelfelix/puppet-pear"]="1.0.3"
-SOURCE_MODULES["https://github.com/stankevich/puppet-python"]="1.9.4"
-SOURCE_MODULES["https://github.com/spiette/puppet-selinux"]="v0.5.1"
-SOURCE_MODULES["https://github.com/nanliu/puppet-staging"]="1.0.0"
-SOURCE_MODULES["https://github.com/biemond/biemond-wildfly"]="v0.2.4"
-SOURCE_MODULES["https://github.com/vamsee/puppet-solr"]="0.0.7"
-SOURCE_MODULES["https://github.com/maestrodev/puppet-wget"]="v1.6.0"
+# Keep sorted
 # freenode #puppet 2012-09-25:
 # 18:25 < jeblair> i would like to use some code that someone wrote,
 # but it's important that i understand how the author wants me to use
@@ -55,8 +35,30 @@ SOURCE_MODULES["https://github.com/maestrodev/puppet-wget"]="v1.6.0"
 # - our intent was not to limit it's use and it should be Apache
 # licensed
 SOURCE_MODULES["https://git.openstack.org/openstack-infra/puppet-vcsrepo"]="0.0.8"
+SOURCE_MODULES["https://github.com/biemond/biemond-wildfly"]="v0.2.4"
+SOURCE_MODULES["https://github.com/maestrodev/puppet-wget"]="v1.6.0"
+SOURCE_MODULES["https://github.com/nanliu/puppet-staging"]="1.0.0"
+SOURCE_MODULES["https://github.com/puppet-community/puppet-module-puppetboard"]="2.4.0"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-apache"]="0.0.4"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-apt"]="1.4.2"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-concat"]="1.1.0"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-firewall"]="1.1.3"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-haproxy"]="0.4.1"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-inifile"]="1.1.3"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-mysql"]="0.6.1"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-ntp"]="3.1.2"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-postgresql"]="3.4.2"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-puppetdb"]="3.0.1"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-rabbitmq"]="5.0.0"
+SOURCE_MODULES["https://github.com/puppetlabs/puppetlabs-stdlib"]="4.3.2"
+SOURCE_MODULES["https://github.com/rafaelfelix/puppet-pear"]="1.0.3"
+SOURCE_MODULES["https://github.com/saz/puppet-memcached"]="a0d4bdca6283d64acb484bb7671c0305cafd76b4"
+SOURCE_MODULES["https://github.com/spiette/puppet-selinux"]="v0.5.1"
+SOURCE_MODULES["https://github.com/stankevich/puppet-python"]="1.9.4"
+SOURCE_MODULES["https://github.com/vamsee/puppet-solr"]="0.0.7"
 
 # Add modules that should be part of the openstack-infra integration test here
+# Please keep sorted
 OPENSTACK_GIT_ROOT=https://git.openstack.org
 INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/openstack-infra/puppet-accessbot"]="origin/master"
 INTEGRATION_MODULES["$OPENSTACK_GIT_ROOT/openstack-infra/puppet-ansible"]="origin/master"
diff --git a/tools/sorted_modules_env.py b/tools/sorted_modules_env.py
new file mode 100644
index 0000000000..a5a4a70f98
--- /dev/null
+++ b/tools/sorted_modules_env.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env
+
+import sys
+import difflib
+
+
+def assert_sorted(lines):
+    if lines == sorted(lines):
+        return True
+    else:
+        print "Modules not sorted:"
+        for line in difflib.context_diff(lines, sorted(lines)):
+            print line
+        sys.exit(1)
+
+
+with open(sys.argv[1]) as f:
+    lines = f.readlines()
+
+integration = [i for i in lines if i.startswith('INTEGRATION')]
+source = [i for i in lines if i.startswith('SOURCE')]
+
+assert_sorted(integration)
+assert_sorted(source)
diff --git a/tox.ini b/tox.ini
index b311b321fd..9bf7590574 100644
--- a/tox.ini
+++ b/tox.ini
@@ -27,4 +27,7 @@ select = H231
 commands = {toxinidir}/tools/run-bashate.sh
 
 [testenv:nodepool]
-commands = nodepool -c {toxinidir}/modules/openstack_project/templates/nodepool/nodepool.yaml.erb config-validate
\ No newline at end of file
+commands = nodepool -c {toxinidir}/modules/openstack_project/templates/nodepool/nodepool.yaml.erb config-validate
+
+[testenv:modulesenv]
+commands = python {toxinidir}/tools/sorted_modules_env.py {toxinidir}/modules.env