diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d3daab789407e0f26360fd1b9e45d2b83d92f3df..1679ae378c90a56e1d25fed8f6f52b3c150c2ad9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.7-golang-1.9-git-2.17-chrome-65.0-node-8.x-yarn-1.2-postgresql-9.6"
+image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.17-chrome-65.0-node-8.x-yarn-1.2-postgresql-9.6"
 
 .dedicated-runner: &dedicated-runner
   retry: 1
@@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.7-golang-1.9-git
     - gitlab-org
 
 .default-cache: &default-cache
-  key: "ruby-2.3.7-debian-stretch-with-yarn"
+  key: "ruby-2.4.4-debian-stretch-with-yarn"
   paths:
     - vendor/ruby
     - .yarn-cache/
@@ -550,7 +550,7 @@ static-analysis:
   script:
     - scripts/static-analysis
   cache:
-    key: "ruby-2.3.7-debian-stretch-with-yarn-and-rubocop"
+    key: "ruby-2.4.4-debian-stretch-with-yarn-and-rubocop"
     paths:
       - vendor/ruby
       - .yarn-cache/
diff --git a/.ruby-version b/.ruby-version
index 00355e29d11ac4a7ee62410face3b0adb50201ac..79a614418f747a2c5e6c8a8a4c42d12e16b06607 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.3.7
+2.4.4
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index ba6552f238f0b0020d9b908c18d9c36083d6763b..25eac5160f16d40b33ecb599110ac1020b907cb5 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -11,12 +11,12 @@ class Kubernetes < ActiveRecord::Base
 
       attr_encrypted :password,
         mode: :per_attribute_iv,
-        key: Gitlab::Application.secrets.db_key_base,
+        key: Settings.attr_encrypted_db_key_base,
         algorithm: 'aes-256-cbc'
 
       attr_encrypted :token,
         mode: :per_attribute_iv,
-        key: Gitlab::Application.secrets.db_key_base,
+        key: Settings.attr_encrypted_db_key_base,
         algorithm: 'aes-256-cbc'
 
       before_validation :enforce_namespace_to_lower_case
diff --git a/app/models/clusters/providers/gcp.rb b/app/models/clusters/providers/gcp.rb
index 7fac32466abe08c7b6c34cf4d6286a4ff3d4a927..eb2e42fd3fe7b431d2540ebdd6b2017a8aa109cc 100644
--- a/app/models/clusters/providers/gcp.rb
+++ b/app/models/clusters/providers/gcp.rb
@@ -11,7 +11,7 @@ class Gcp < ActiveRecord::Base
 
       attr_encrypted :access_token,
         mode: :per_attribute_iv,
-        key: Gitlab::Application.secrets.db_key_base,
+        key: Settings.attr_encrypted_db_key_base,
         algorithm: 'aes-256-cbc'
 
       validates :gcp_project_id,
diff --git a/app/models/concerns/has_variable.rb b/app/models/concerns/has_variable.rb
index 8a241e4374ac4fb93b5c02d6634ebdda853b985c..c8e20c0ab81507ea6bc93e66482bdbbcdba33678 100644
--- a/app/models/concerns/has_variable.rb
+++ b/app/models/concerns/has_variable.rb
@@ -13,7 +13,7 @@ module HasVariable
     attr_encrypted :value,
        mode: :per_attribute_iv_and_salt,
        insecure_mode: true,
-       key: Gitlab::Application.secrets.db_key_base,
+       key: Settings.attr_encrypted_db_key_base,
        algorithm: 'aes-256-cbc'
 
     def key=(new_key)
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 2e478a247789b0c037ae73a30998b8de955e4576..bfea64c3759d5bc2ec7f9734a07de38449f4c8bb 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -19,7 +19,7 @@ class PagesDomain < ActiveRecord::Base
   attr_encrypted :key,
     mode: :per_attribute_iv_and_salt,
     insecure_mode: true,
-    key: Gitlab::Application.secrets.db_key_base,
+    key: Settings.attr_encrypted_db_key_base,
     algorithm: 'aes-256-cbc'
 
   after_initialize :set_verification_code
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index 6da6632f4f21c9f8d6a4d2ee5c3ceb31e15e4761..1d7089ccfc731ed368f341a27fd80329f99bee5c 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -3,7 +3,7 @@
 class ProjectImportData < ActiveRecord::Base
   belongs_to :project, inverse_of: :import_data
   attr_encrypted :credentials,
-                 key: Gitlab::Application.secrets.db_key_base,
+                 key: Settings.attr_encrypted_db_key_base,
                  marshal: true,
                  encode: true,
                  mode: :per_attribute_iv_and_salt,
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 9722cbb2b7c9de883ac986e968409baf8fea1c72..5cd222e18a41621111deb105ea3b2c5441faa0e3 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -5,7 +5,7 @@ class RemoteMirror < ActiveRecord::Base
   UNPROTECTED_BACKOFF_DELAY = 5.minutes
 
   attr_encrypted :credentials,
-                 key: Gitlab::Application.secrets.db_key_base,
+                 key: Settings.attr_encrypted_db_key_base,
                  marshal: true,
                  encode: true,
                  mode: :per_attribute_iv_and_salt,
diff --git a/config/initializers/secret_token.rb b/config/initializers/01_secret_token.rb
similarity index 95%
rename from config/initializers/secret_token.rb
rename to config/initializers/01_secret_token.rb
index 750a5b34f3be24d0d512fb26c014ec48521cf840..02bded43083534cb858d37ce4ab8cf000658ae42 100644
--- a/config/initializers/secret_token.rb
+++ b/config/initializers/01_secret_token.rb
@@ -1,3 +1,6 @@
+# This file needs to be loaded BEFORE any initializers that attempt to
+# prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb).
+#
 # Be sure to restart your server when you modify this file.
 
 require 'securerandom'
diff --git a/config/settings.rb b/config/settings.rb
index 69d637761ea79675e0b4dfb9825b727c7fc2f114..4aa903109ea41f8d3e2d61489c88b1cf8ec3bee3 100644
--- a/config/settings.rb
+++ b/config/settings.rb
@@ -85,6 +85,10 @@ def absolute(path)
       File.expand_path(path, Rails.root)
     end
 
+    def attr_encrypted_db_key_base
+      Gitlab::Application.secrets.db_key_base[0..31]
+    end
+
     private
 
     def base_url(config)
diff --git a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
index 611767ac7fe2497457df2e7fa629b1c4c3f905bd..951051187646cafc891d5cec7ff74e1e03cfe31b 100644
--- a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
+++ b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
@@ -8,7 +8,7 @@ class ProjectImportDataFake
     extend AttrEncrypted
     attr_accessor :credentials
     attr_encrypted :credentials,
-                   key: Gitlab::Application.secrets.db_key_base,
+                   key: Settings.attr_encrypted_db_key_base,
                    marshal: true,
                    encode: true,
                    :mode => :per_attribute_iv_and_salt,
diff --git a/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb b/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb
index 11b581e4b5784720a56d11214501d80ae43c6fe9..1586a7eb92f6c6cbf4d21d5da04eec08019d87b4 100644
--- a/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb
+++ b/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb
@@ -48,7 +48,7 @@ class PlatformsKubernetes < ActiveRecord::Base
 
     attr_encrypted :token,
       mode: :per_attribute_iv,
-      key: Gitlab::Application.secrets.db_key_base,
+      key: Settings.attr_encrypted_db_key_base,
       algorithm: 'aes-256-cbc'
   end
 
diff --git a/doc/install/installation.md b/doc/install/installation.md
index a0ae9017f71b034e7e8c96a5a32e47ca27ca6c96..34268c671403345713b7dae168c84d8020021d2c 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -133,9 +133,9 @@ Remove the old Ruby 1.8 if present:
 Download Ruby and compile it:
 
     mkdir /tmp/ruby && cd /tmp/ruby
-    curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.7.tar.gz
-    echo '540996fec64984ab6099e34d2f5820b14904f15a  ruby-2.3.7.tar.gz' | shasum -c - && tar xzf ruby-2.3.7.tar.gz
-    cd ruby-2.3.7
+    curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
+    echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c  ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
+    cd ruby-2.4.4
 
     ./configure --disable-install-rdoc
     make
diff --git a/spec/initializers/secret_token_spec.rb b/spec/initializers/secret_token_spec.rb
index d56e14e0e0b0f30be66315e4f3b247c0671cafb7..c3dfd7bedbe32d39dea858b4fbccb614821c9f93 100644
--- a/spec/initializers/secret_token_spec.rb
+++ b/spec/initializers/secret_token_spec.rb
@@ -1,5 +1,5 @@
 require 'spec_helper'
-require_relative '../../config/initializers/secret_token'
+require_relative '../../config/initializers/01_secret_token'
 
 describe 'create_tokens' do
   include StubENV
diff --git a/spec/models/concerns/has_variable_spec.rb b/spec/models/concerns/has_variable_spec.rb
index f87869a2fdc1279fbdc761b38658c3c7aa8bedf7..3fbe86c5b56f2e0d8c5cc476de8b8cf931148d69 100644
--- a/spec/models/concerns/has_variable_spec.rb
+++ b/spec/models/concerns/has_variable_spec.rb
@@ -45,8 +45,10 @@
     end
 
     it 'fails to decrypt if iv is incorrect' do
-      subject.encrypted_value_iv = SecureRandom.hex
+      # attr_encrypted expects the IV to be 16 bytes and base64-encoded
+      subject.encrypted_value_iv = [SecureRandom.hex(8)].pack('m')
       subject.instance_variable_set(:@value, nil)
+
       expect { subject.value }
         .to raise_error(OpenSSL::Cipher::CipherError, 'bad decrypt')
     end