diff --git a/config/application.config.php b/config/application.config.php
index 0cdb7c948d1aaf39ffe7581a0d9d20098961d073..5a39bff34ca019f7e409732fc9e1118badaab701 100644
--- a/config/application.config.php
+++ b/config/application.config.php
@@ -22,7 +22,7 @@ if ($localModules = getenv('VUFIND_LOCAL_MODULES')) {
 // Set up cache directory (be sure to keep separate cache for CLI vs. web and
 // to account for potentially variant environment settings):
 $baseDir = ($local = getenv('VUFIND_LOCAL_DIR')) ? $local : 'data';
-$cacheDir = $baseDir . '/cache';
+$cacheDir = ($cache = getenv('VUFIND_CACHE_DIR')) ? $cache : $baseDir . '/cache';
 if (!is_dir($cacheDir)) {
     mkdir($cacheDir);
 }
diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 973a708cabd6b4b9e5e0dff7ca0cbb6a5998dd34..9a28d271c49150c4b991b233167dd71eea1d9131 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -1139,16 +1139,12 @@ dewey = title
 HMACkey = mySuperSecretValue
 
 ; This section sets global defaults for caches; file caching is used by default.
+; A custom directory for caching can be defined by the environment variable
+; VUFIND_CACHE_DIR (see httpd-vufind.conf). The default location is inside the
+; local settings directory.
 ;[Cache]
 ; Set time to live value for Zend caches (in seconds), 0 means maximum possible.
 ;ttl = 0
-; This setting can be used to force caching in a specific location other than the
-; default location inside the local settings directory. This directory must exist
-; and be writable by the web server. Do not share this directory between multiple
-; instances of VuFind or you may encounter unexpected side effects -- while this
-; directory may be outside of the local settings directory, there should be exactly
-; one separate cache location per local settings directory.
-;cache_dir = "local/cache/"
 ; Override umask for cache directories and files.
 ;umask = 022
 ; Permissions for Zend-created cache directories and files, subject to umask
diff --git a/config/vufind/httpd-vufind.conf b/config/vufind/httpd-vufind.conf
index 3cfdfea49be3d89febaaa05f3b16154cb3bd0222..b93691e97693ce32d9ae5963e26937264fa9b2dd 100644
--- a/config/vufind/httpd-vufind.conf
+++ b/config/vufind/httpd-vufind.conf
@@ -57,6 +57,14 @@ Alias /vufind /usr/local/vufind/public
   # to override VuFind core features/settings.  Set to blank string ("") to disable.
   SetEnv VUFIND_LOCAL_DIR /usr/local/vufind/local
 
+  # This line can be used to force caching in a specific location other than the
+  # default location inside the local settings directory.
+  # Do not share this directory between multiple instances of VuFind or you may
+  # encounter unexpected side effects -- while this directory may be outside of the
+  # local settings directory, there should be exactly one separate cache location per
+  # local settings directory.
+  #SetEnv VUFIND_CACHE_DIR /usr/local/vufind/cache
+
   # This line specifies additional Zend Framework 2 modules to load after the standard VuFind module.
   # Multiple modules may be specified separated by commas.  This mechanism can be used to override
   # core VuFind functionality without modifying core code.
diff --git a/module/VuFind/src/VuFind/Cache/Manager.php b/module/VuFind/src/VuFind/Cache/Manager.php
index 837d78aa1200acabc4aaee279c2f55e5d74620ea..fb1d8fdac2340900a1802f89c0b7a69a6e76bb3e 100644
--- a/module/VuFind/src/VuFind/Cache/Manager.php
+++ b/module/VuFind/src/VuFind/Cache/Manager.php
@@ -148,11 +148,16 @@ class Manager
     public function getCacheDir($allowCliOverride = true)
     {
         if ($this->defaults && isset($this->defaults['cache_dir'])) {
-            $dir = $this->defaults['cache_dir'];
-            // ensure trailing slash:
-            if (substr($dir, -1) != '/') {
-                $dir .= '/';
-            }
+            // cache_dir setting in config.ini is deprecated
+            throw new \Exception(
+                'Deprecated cache_dir setting found in config.ini - please use '
+                . 'Apache environment variable VUFIND_CACHE_DIR in '
+                . 'httpd-vufind.conf instead.'
+            );
+        }
+
+        if (strlen(LOCAL_CACHE_DIR) > 0) {
+            $dir = LOCAL_CACHE_DIR . '/';
         } else if (strlen(LOCAL_OVERRIDE_DIR) > 0) {
             $dir = LOCAL_OVERRIDE_DIR . '/cache/';
         } else {
diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php
index fb319fda7d44793965d446cbdd9be690498c2f1c..98ff2988a3c3d6270072a13c213d751393afd162 100644
--- a/module/VuFind/src/VuFind/Controller/CombinedController.php
+++ b/module/VuFind/src/VuFind/Controller/CombinedController.php
@@ -73,7 +73,8 @@ class CombinedController extends AbstractSearch
         $searchClassId = $this->params()->fromQuery('id');
         $config = $this->getServiceLocator()->get('VuFind\Config')->get('combined')
             ->toArray();
-        if (!isset($config[$searchClassId])) {
+        $tabConfig = $this->getTabConfig($config);
+        if (!isset($tabConfig[$searchClassId])) {
             throw new \Exception('Illegal ID');
         }
 
@@ -83,7 +84,7 @@ class CombinedController extends AbstractSearch
         $currentOptions = $options->get($searchClassId);
         list($controller, $action)
             = explode('-', $currentOptions->getSearchAction());
-        $settings = $config[$searchClassId];
+        $settings = $tabConfig[$searchClassId];
 
         $this->adjustQueryForSettings($settings);
         $settings['view'] = $this->forwardTo($controller, $action);
@@ -149,11 +150,7 @@ class CombinedController extends AbstractSearch
             ->toArray();
         $supportsCart = false;
         $supportsCartOptions = [];
-        foreach ($config as $current => $settings) {
-            // Special case -- ignore recommendation config:
-            if ($current == 'Layout' || $current == 'RecommendationModules') {
-                continue;
-            }
+        foreach ($this->getTabConfig($config) as $current => $settings) {
             $this->adjustQueryForSettings($settings);
             $currentOptions = $options->get($current);
             $supportsCartOptions[] = $currentOptions->supportsCart();
@@ -274,4 +271,20 @@ class CombinedController extends AbstractSearch
             $query->noRecommend = 'top,side';
         }
     }
+
+    /**
+     * Get tab configuration based on the full combined results configuration.
+     *
+     * @param array $config Combined results configuration
+     *
+     * @return array
+     */
+    protected function getTabConfig($config)
+    {
+        // Strip out non-tab sections of the configuration:
+        unset($config['Layout']);
+        unset($config['RecommendationModules']);
+
+        return $config;
+    }
 }
diff --git a/public/index.php b/public/index.php
index 39e0afbcece92586874933fcdd27c2c92bb3d477..de75a183832caa2c56a43843ec5c2a770c524a2c 100644
--- a/public/index.php
+++ b/public/index.php
@@ -33,6 +33,14 @@ defined('LOCAL_OVERRIDE_DIR')
         (getenv('VUFIND_LOCAL_DIR') ? getenv('VUFIND_LOCAL_DIR') : '')
     );
 
+// Define path to cache directory
+defined('LOCAL_CACHE_DIR')
+    || define(
+        'LOCAL_CACHE_DIR',
+        (getenv('VUFIND_CACHE_DIR')
+            ? getenv('VUFIND_CACHE_DIR') : LOCAL_OVERRIDE_DIR . '/cache')
+    );
+
 // Save original working directory in case we need to remember our context, then
 // switch to the application directory for convenience:
 define('ORIGINAL_WORKING_DIRECTORY', getcwd());