diff --git a/README.md b/README.md
index fb739b52652239ce9ec367ecea89ad68465ef4e8..09b7033775ff7dc856c4376e633f68373d768a1a 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,16 @@ freeradius::config { 'realm-checks.conf':
 }
 ```
 
+#### `freeradius::dictionary`
+
+Install custom dictionaries without breaking the default FreeRADIUS dictionary. Custom dictionaries are installed in `/etc/raddb/dictionary.d` and automatically included in the global dictionary.
+
+```puppet
+freeradius::dictionary { 'mydict':
+  source => 'puppet:///modules/site_freeradius/dictionary.mydict',
+}
+```
+
 #### `freeradius::instantiate`
 
 Instantiate a module that is not automatically instantiated.
diff --git a/files/dictionary.footer b/files/dictionary.footer
new file mode 100644
index 0000000000000000000000000000000000000000..29dcd1e5a83f84ce3a1db4f0e40b47a9efbf7e44
--- /dev/null
+++ b/files/dictionary.footer
@@ -0,0 +1,12 @@
+
+#
+#       If you want to add entries to the dictionary file,
+#       which are NOT going to be placed in a RADIUS packet,
+#       add them here.  The numbers you pick should be between
+#       3000 and 4000.
+#
+
+#ATTRIBUTE      My-Local-String         3000    string
+#ATTRIBUTE      My-Local-IPAddr         3001    ipaddr
+#ATTRIBUTE      My-Local-Integer        3002    integer
+
diff --git a/files/dictionary.header b/files/dictionary.header
new file mode 100644
index 0000000000000000000000000000000000000000..4cecbdef514926ebb77a650f8c486273d1c3cc81
--- /dev/null
+++ b/files/dictionary.header
@@ -0,0 +1,19 @@
+#
+#       This is the master dictionary file, which references the
+#       pre-defined dictionary files included with the server.
+#
+#       Any new/changed attributes MUST be placed in this file, as
+#       the pre-defined dictionaries SHOULD NOT be edited.
+#
+#       $Id$
+
+#       The filename given here should be an absolute path.
+
+$INCLUDE        /usr/share/freeradius/dictionary
+
+#       Place additional attributes or $INCLUDEs here.  They will
+#       over-ride the definitions in the pre-defined dictionaries.
+
+#       See the 'man' page for 'dictionary' for information on
+#       the format of the dictionary files.
+
diff --git a/manifests/dictionary.pp b/manifests/dictionary.pp
new file mode 100644
index 0000000000000000000000000000000000000000..28fe8ec2f7676e8ddf977cfcd95e423b9612f4c2
--- /dev/null
+++ b/manifests/dictionary.pp
@@ -0,0 +1,25 @@
+# Install FreeRADIUS custom dictionaries
+define freeradius::dictionary ($source, $order=50) {
+  $fr_package = $::freeradius::params::fr_package
+  $fr_service = $::freeradius::params::fr_service
+  $fr_basepath = $::freeradius::params::fr_basepath
+
+  # Install dictionary in dictionary.d 
+  file { "${fr_basepath}/dictionary.d/dictionary.${name}":
+    mode    => '0644',
+    owner   => 'root',
+    group   => 'radiusd',
+    source  => $source,
+    require => Package[$fr_package],
+    notify  => Service[$fr_service],
+  }
+
+  # Reference policy.d in the global includes file
+  # If no order priority is given, assume 50
+  concat::fragment { "dictionary.${name}":
+    target  => "${fr_basepath}/dictionary",
+    content => "\$INCLUDE ${fr_basepath}/dictionary.d/dictionary.${name}\n",
+    order   => $order,
+    require => File["${fr_basepath}/dictionary.d/dictionary.${name}"],
+  }
+}
diff --git a/manifests/init.pp b/manifests/init.pp
index d1c91afbc4041741a820e1025feac0fbf20dc488..8bd177dbc37716d6be9d9979f65b723ea3e3566b 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -26,6 +26,7 @@ class freeradius (
     "$fr_basepath/attr.d",
     "$fr_basepath/users.d",
     "$fr_basepath/policy.d",
+    "$fr_basepath/dictionary.d",
     "$fr_basepath/scripts",
     "$fr_basepath/certs",
   ]:
@@ -55,6 +56,24 @@ class freeradius (
     order   => '99',
   }
 
+  # Install a slightly tweaked stock dictionary that includes
+  # our custom dictionaries
+  concat { "$fr_basepath/dictionary":
+    owner => 'root',
+    group => 'radiusd',
+    mode  => '0640',
+  }
+  concat::fragment { 'dictionary_header':
+    target  => "$fr_basepath/dictionary",
+    source  => 'puppet:///modules/freeradius/dictionary.header',
+    order   => 10,
+  }
+  concat::fragment { 'dictionary_footer':
+    target  => "$fr_basepath/dictionary",
+    source  => 'puppet:///modules/freeradius/dictionary.footer',
+    order   => 90,
+  }
+
   # Install FreeRADIUS packages from ResNet repo, which is newer than stock CentOS 
   package { 'freeradius':
     name   => $fr_package,
diff --git a/templates/dictionary.erb b/templates/dictionary.erb
new file mode 100644
index 0000000000000000000000000000000000000000..6107ab9ded81e5f14199134a637d3d339eb3216a
--- /dev/null
+++ b/templates/dictionary.erb
@@ -0,0 +1,33 @@
+#
+#	This is the master dictionary file, which references the
+#	pre-defined dictionary files included with the server.
+#
+#	Any new/changed attributes MUST be placed in this file, as
+#	the pre-defined dictionaries SHOULD NOT be edited.
+#
+#	$Id$
+#
+
+#
+#	The filename given here should be an absolute path. 
+#
+$INCLUDE	/usr/share/freeradius/dictionary
+$INCLUDE	<%= @fr_basepath %>/dictionary.custom
+
+#
+#	Place additional attributes or $INCLUDEs here.  They will
+#	over-ride the definitions in the pre-defined dictionaries.
+#
+#	See the 'man' page for 'dictionary' for information on
+#	the format of the dictionary files.
+
+#
+#	If you want to add entries to the dictionary file,
+#	which are NOT going to be placed in a RADIUS packet,
+#	add them here.  The numbers you pick should be between
+#	3000 and 4000.
+#
+
+#ATTRIBUTE	My-Local-String		3000	string
+#ATTRIBUTE	My-Local-IPAddr		3001	ipaddr
+#ATTRIBUTE	My-Local-Integer	3002	integer