diff --git a/manifests/site.pp b/manifests/site.pp
index ed82adfcb8..69a12e3fc5 100644
--- a/manifests/site.pp
+++ b/manifests/site.pp
@@ -613,6 +613,7 @@ node 'mirror-update.openstack.org' {
     bandersnatch_keytab => hiera('bandersnatch_keytab'),
     admin_keytab        => hiera('afsadmin_keytab'),
     reprepro_keytab     => hiera('reprepro_keytab'),
+    gem_keytab          => hiera('gem_keytab'),
     npm_keytab          => hiera('npm_keytab'),
     centos_keytab       => hiera('centos_keytab'),
     epel_keytab         => hiera('epel_keytab'),
diff --git a/modules/openstack_project/manifests/gem_mirror.pp b/modules/openstack_project/manifests/gem_mirror.pp
new file mode 100644
index 0000000000..9e0cf7d673
--- /dev/null
+++ b/modules/openstack_project/manifests/gem_mirror.pp
@@ -0,0 +1,65 @@
+# == Class: openstack_project::gem_mirror
+#
+class openstack_project::gem_mirror (
+  $data_directory = '/afs/.openstack.org/mirror/gem',
+  $parallelism    = '10',
+  $cron_frequency = '*/5',
+) {
+
+  include ::logrotate
+
+  logrotate::file { 'rubygems-mirror':
+    log     => '/var/log/rubygems/mirror.log',
+    options => [
+      'compress',
+      'copytruncate',
+      'missingok',
+      'rotate 7',
+      'daily',
+      'notifempty',
+    ],
+  }
+
+  group { 'rubygems':
+    ensure => 'present',
+    before => User['rubygems'],
+  }
+
+  user { 'rubygems':
+    ensure     => 'present',
+    comment    => 'Service used to run rubygems mirror synchronization',
+    managehome => true,
+    require    => Package['rubygems-mirror'],
+  }
+
+  file { '/home/rubygems/.gem':
+    ensure  => directory,
+    owner   => 'rubygems',
+    group   => 'rubygems',
+    mode    => '0600',
+    replace => true,
+    require => User['rubygems'],
+  }
+
+  file { '/home/rubygems/.gem/.mirrorrc':
+    ensure  => present,
+    owner   => 'rubygems',
+    group   => 'rubygems',
+    mode    => '0600',
+    content => template('openstack_project/rubygems_mirrorrc.erb'),
+    replace => true,
+    require => File['/home/rubygems/.gem'],
+  }
+
+  package { 'rubygems-mirror':
+    ensure   => latest,
+    provider => gem,
+  }
+
+  file { ['/var/run/rubygems','/var/log/rubygems']:
+    ensure  => directory,
+    owner   => 'rubygems',
+    group   => 'rubygems',
+    require => User['rubygems'],
+  }
+}
diff --git a/modules/openstack_project/manifests/mirror.pp b/modules/openstack_project/manifests/mirror.pp
index adf227cd3c..ddb6e87d52 100644
--- a/modules/openstack_project/manifests/mirror.pp
+++ b/modules/openstack_project/manifests/mirror.pp
@@ -10,6 +10,7 @@ class openstack_project::mirror (
   $npm_root = "${mirror_root}/npm"
   $ceph_deb_hammer_root = "${mirror_root}/ceph-deb-hammer"
   $ceph_deb_jewel_root = "${mirror_root}/ceph-deb-jewel"
+  $gem_root = "${mirror_root}/gem"
 
   $www_base = '/var/www'
   $www_root = "${www_base}/mirror"
@@ -162,6 +163,16 @@ class openstack_project::mirror (
     ]
   }
 
+  file { "${www_root}/gem":
+    ensure  => link,
+    target  => "${gem_root}",
+    owner   => root,
+    group   => root,
+    require => [
+      File["${www_root}"],
+    ]
+  }
+
   file { "${www_root}/robots.txt":
     ensure   => present,
     owner    => 'root',
diff --git a/modules/openstack_project/manifests/mirror_update.pp b/modules/openstack_project/manifests/mirror_update.pp
index 6070dbed6d..e06ff058b6 100644
--- a/modules/openstack_project/manifests/mirror_update.pp
+++ b/modules/openstack_project/manifests/mirror_update.pp
@@ -5,6 +5,7 @@ class openstack_project::mirror_update (
   $bandersnatch_keytab = '',
   $reprepro_keytab = '',
   $admin_keytab = '',
+  $gem_keytab = '',
   $npm_keytab = '',
   $centos_keytab = '',
   $epel_keytab = '',
@@ -24,6 +25,8 @@ class openstack_project::mirror_update (
     uri_rewrite    => $uri_rewrite,
   }
 
+  class { 'openstack_project::gem_mirror': }
+
   class { 'bandersnatch': }
 
   class { 'bandersnatch::mirror':
@@ -40,6 +43,14 @@ class openstack_project::mirror_update (
     content => $bandersnatch_keytab,
   }
 
+  file { '/etc/gem.keytab':
+    owner   => 'rubygems',
+    group   => 'root',
+    mode    => '0400',
+    content => $gem_keytab,
+    require  => Class['openstack_project::gem_mirror'],
+  }
+
   file { '/etc/npm.keytab':
     owner   => 'root',
     group   => 'root',
@@ -83,6 +94,18 @@ class openstack_project::mirror_update (
     ]
   }
 
+  cron { 'rubygems-mirror':
+    user        => 'rubygems',
+    minute      => '*/5',
+    command     => 'flock -n /var/run/rubygems/mirror.lock timeout -k 2m 30m gem mirror >>/var/log/rubygems/mirror.log 2>&1',
+    environment => 'PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin',
+    require     => [
+      File['/etc/afsadmin.keytab'],
+      File['/etc/gem.keytab'],
+      Class['openstack_project::gem_mirror'],
+    ]
+  }
+
   cron { 'npm-mirror-update':
     user        => $user,
     minute      => '*/5',
diff --git a/modules/openstack_project/templates/rubygems_mirrorrc.erb b/modules/openstack_project/templates/rubygems_mirrorrc.erb
new file mode 100644
index 0000000000..cb6c64f82f
--- /dev/null
+++ b/modules/openstack_project/templates/rubygems_mirrorrc.erb
@@ -0,0 +1,4 @@
+---
+- from: http://rubygems.org
+  to: <%= @destination_path %>
+  parallelism: <%= @parallelism %>