diff --git a/README.md b/README.md
index f7cd07b7a28b5068de366f9034a32bda7305dd98..e9926683161c28a2214bac49171794f7a0006094 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@
        * [`freeradius::home_server_pool`](#freeradiushomeserverpool)
        * [`freeradius::instantiate`](#freeradiusinstantiate)
        * [`freeradius::ldap`](#freeradiusldap)
+       * [`freeradius::krb5`](#freeradiuskrb5)
        * [`freeradius::module`](#freeradiusmodule)
        * [`freeradius::policy`](#freeradiuspolicy)
        * [`freeradius::realm`](#freeradiusrealm)
@@ -96,6 +97,9 @@ Install FreeRADIUS utils. Default: `false`
 ##### `ldap_support`
 Install support for LDAP. Default: `false`
 
+##### `krb5_support`
+Install support for Kerberos. Default: `false`
+
 ##### `wpa_supplicant`
 Install wpa_supplicant utility. Default: `false`
 
@@ -467,6 +471,28 @@ Certificate Verification requirements. Choose from:
 
 Default: `allow`
 
+#### `freeradius::krb5`
+Configure Kerberos support for FreeRADIUS
+
+##### `keytab`
+Full path to the Kerberos keytab file
+
+##### `principal`
+Name of the service principal
+
+##### `start`
+Connections to create during module instantiation. If the server cannot create specified number of
+connections during instantiation it will exit. Set to 0 to allow the server to start without the
+directory being available. Default: `${thread[pool].start_servers}`
+
+##### `min`
+Minimum number of connections to keep open. Default: `${thread[pool].min_spare_servers}`
+
+##### `max`
+Maximum number of connections. Default: `${thread[pool].max_servers}`
+
+##### `spare`
+Spare connections to be left idle. Default: `${thread[pool].max_spare_servers}`
 
 #### `freeradius::module`
 
diff --git a/manifests/init.pp b/manifests/init.pp
index 318d5205a5f161c6fea352825def0aa80ba856a0..dd01108162375cefe2a514b0b1187f9674547aea 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -7,6 +7,7 @@ class freeradius (
   $perl_support    = false,
   $utils_support   = false,
   $ldap_support    = false,
+  $krb5_support    = false,
   $wpa_supplicant  = false,
   $winbind_support = false,
   $syslog          = false,
@@ -218,6 +219,11 @@ class freeradius (
       ensure => installed,
     }
   }
+  if $krb5_support {
+    package { 'freeradius-krb5':
+      ensure => installed,
+    }
+  }
   if $wpa_supplicant {
     package { 'wpa_supplicant':
       ensure => installed,
diff --git a/manifests/krb5.pp b/manifests/krb5.pp
new file mode 100644
index 0000000000000000000000000000000000000000..3f40a3fb919044c3c77ec0ccd283192dbe66e128
--- /dev/null
+++ b/manifests/krb5.pp
@@ -0,0 +1,26 @@
+# Configure Kerberos support for FreeRADIUS
+define freeradius::krb5 (
+  $keytab,
+  $principal,
+  $start       = '${thread[pool].start_servers}',
+  $min         = '${thread[pool].min_spare_servers}',
+  $max         = '${thread[pool].max_servers}',
+  $spare       = '${thread[pool].max_spare_servers}',
+  $ensure      = 'present',
+) {
+  $fr_package          = $::freeradius::params::fr_package
+  $fr_service          = $::freeradius::params::fr_service
+  $fr_modulepath       = $::freeradius::params::fr_modulepath
+  $fr_group            = $::freeradius::params::fr_group
+
+  # Generate a module config
+  file { "${fr_modulepath}/${name}":
+    ensure  => $ensure,
+    mode    => '0640',
+    owner   => 'root',
+    group   => $fr_group,
+    content => template('freeradius/krb5.erb'),
+    require => [Package[$fr_package], Group[$fr_group]],
+    notify  => Service[$fr_service],
+  }
+}
diff --git a/spec/classes/freeradius_spec.rb b/spec/classes/freeradius_spec.rb
index 5f6d633a65dbe8ad0f9c2f122b7512020202b767..acfe75bdc117b85bf2e853b22fcc6618604be46a 100644
--- a/spec/classes/freeradius_spec.rb
+++ b/spec/classes/freeradius_spec.rb
@@ -28,6 +28,7 @@ describe 'freeradius' do
       #:perl_support => false,
       #:utils_support => false,
       #:ldap_support => false,
+      #:krb5_support => false,
       #:wpa_supplicant => false,
       #:winbind_support => false,
       #:syslog => false,
@@ -332,6 +333,12 @@ describe 'freeradius' do
         'ensure' => 'installed'
       )
   end
+  it do
+    is_expected.to contain_package('freeradius-krb5')
+      .with(
+        'ensure' => 'installed'
+      )
+  end
   it do
     is_expected.to contain_package('wpa_supplicant')
       .with(
diff --git a/spec/defines/krb5_spec.rb b/spec/defines/krb5_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..753495762a52fcd64f3435a6d8d465595b850349
--- /dev/null
+++ b/spec/defines/krb5_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+require 'shared_contexts'
+
+describe 'freeradius::krb5' do
+  # by default the hiera integration uses hiera data from the shared_contexts.rb file
+  # but basically to mock hiera you first need to add a key/value pair
+  # to the specific context in the spec/shared_contexts.rb file
+  # Note: you can only use a single hiera context per describe/context block
+  # rspec-puppet does not allow you to swap out hiera data on a per test block
+  #include_context :hiera
+
+  let(:title) { 'XXreplace_meXX' }
+  
+  # below is the facts hash that gives you the ability to mock
+  # facts on a per describe/context block.  If you use a fact in your
+  # manifest you should mock the facts below.
+  let(:facts) do
+    {}
+  end
+  # below is a list of the resource parameters that you can override.
+  # By default all non-required parameters are commented out,
+  # while all required parameters will require you to add a value
+  let(:params) do
+    {
+      :keytab => 'place_value_here',
+      :principal => 'place_value_here',
+      #:start => "${thread[pool].start_servers}",
+      #:min => "${thread[pool].min_spare_servers}",
+      #:max => "${thread[pool].max_servers}",
+      #:spare => "${thread[pool].max_spare_servers}",
+      #:ensure => "present",
+    }
+  end
+  # add these two lines in a single test block to enable puppet and hiera debug mode
+  # Puppet::Util::Log.level = :debug
+  # Puppet::Util::Log.newdestination(:console)
+  it do
+    is_expected.to contain_file('$::osfamily ? { RedHat => /etc/raddb, Debian => /etc/freeradius, default => /etc/raddb }/$fr_version ? { 2 => modules, 3 => mods-enabled, default => modules }/XXreplace_meXX')
+      .with(
+        'content' => 'template(freeradius/krb5.erb)',
+        'ensure'  => 'present',
+        'group'   => '$::osfamily ? { RedHat => radiusd, Debian => freerad, default => radiusd }',
+        'mode'    => '0640',
+        'notify'  => 'Service[$fr_service]',
+        'owner'   => 'root',
+        'require' => '[Package[$fr_package], Group[$fr_group]]'
+      )
+  end
+end
diff --git a/spec/shared_contexts.rb b/spec/shared_contexts.rb
index e90abe8625275aff1a50237e8815d295df1de658..f549bde4a0347e297a2019309afc393991c4fb55 100644
--- a/spec/shared_contexts.rb
+++ b/spec/shared_contexts.rb
@@ -11,6 +11,7 @@ shared_context :global_hiera_data do
        #"freeradius::control_socket" => '',
        #"freeradius::control_socket::mode" => '',
        #"freeradius::ldap_support" => '',
+       #"freeradius::krb5_support" => '',
        #"freeradius::max_requests" => '',
        #"freeradius::max_servers" => '',
        #"freeradius::mysql_support" => '',
diff --git a/templates/krb5.erb b/templates/krb5.erb
new file mode 100644
index 0000000000000000000000000000000000000000..b6210114ea5a8c631c828090b5a2ba17532cc5fd
--- /dev/null
+++ b/templates/krb5.erb
@@ -0,0 +1,67 @@
+# -*- text -*-
+#
+#  $Id: 29a92b9c099a8238fbff0dec60bef00cfb89010a $
+
+#
+#  Kerberos.  See doc/modules/rlm_krb5 for minimal docs.
+#
+krb5 <%= @name %> {
+	keytab = <%= @keytab %>
+	service_principal = <%= @principal %>
+
+        #  Pool of krb5 contexts, this allows us to make the module multithreaded
+        #  and to avoid expensive operations like resolving and opening keytabs
+        #  on every request.  It may also allow TCP connections to the KDC to be
+        #  cached if that is supported by the version of libkrb5 used.
+        #
+        #  The context pool is only used if the underlying libkrb5 reported
+        #  that it was thread safe at compile time.
+        #
+        pool {
+                # Number of connections to start
+		start = <%= @start %>
+
+                # Minimum number of connections to keep open
+		min = <%= @min %>
+
+                # Maximum number of connections
+                #
+                # If these connections are all in use and a new one
+                # is requested, the request will NOT get a connection.
+                #
+                # NOTE: This should be greater than or equal to "min" above.
+		max = <%= @max %>
+
+                # Spare connections to be left idle
+                #
+                # NOTE: Idle connections WILL be closed if "idle_timeout"
+                # is set.  This should be less than or equal to "max" above.
+		spare = <%= @spare %>
+
+                # Number of uses before the connection is closed
+                #
+                # NOTE: A setting of 0 means infinite (no limit).
+                uses = 0
+
+                # The lifetime (in seconds) of the connection
+                #
+                # NOTE: A setting of 0 means infinite (no limit).
+                lifetime = 0
+
+                # The idle timeout (in seconds).  A connection which is
+                # unused for this length of time will be closed.
+                #
+                # NOTE: A setting of 0 means infinite (no timeout).
+                idle_timeout = 0
+
+                # NOTE: All configuration settings are enforced.  If a
+                # connection is closed because of "idle_timeout",
+                # "uses", or "lifetime", then the total number of
+                # connections MAY fall below "min".  When that
+                # happens, it will open a new connection.  It will
+                # also log a WARNING message.
+                #
+                # The solution is to either lower the "min" connections,
+                # or increase lifetime/idle_timeout.
+        }
+}