diff --git a/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php b/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php
index 3ddea13e99d88bdec313a66ed66f40e160b87b8e..9916b72e57246892ac373fb15e1093b5e4cc8e5b 100644
--- a/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php
+++ b/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php
@@ -58,12 +58,12 @@ class cronjob_jailkit_maintenance extends cronjob {
 		$jailkit_config = $app->getconf->get_server_config($conf['server_id'], 'jailkit');
 		if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) {
 			if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') {
-				$update_options = array('hardlink');
+				$options = array('hardlink');
 			} elseif ($this->jailkit_config['jailkit_hardlinks'] == 'no') {
-				$update_options = array();
+				$options = array();
 			}
 		} else {
-			$update_options = array('allow_hardlink');
+			$options = array('allow_hardlink');
 		}
 
 		// limit the number of jails we update at one time according to time of day
@@ -86,6 +86,14 @@ class cronjob_jailkit_maintenance extends cronjob {
 			// check for any cron job using this jail
 			$cron_inuse = $app->db->queryOneRecord('SELECT id FROM `cron` WHERE `parent_domain_id` = ? AND `type` = ? AND `server_id` = ?', $rec['domain_id'], 'chrooted', $conf['server_id']);
 
+			$records2 = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $rec['domain_id'], $rec['document_root'], $conf['server_id']);
+			foreach ($records2 as $record2) {
+				if ($record2['web_folder'] == NULL || $record2['web_folder'] == '') {
+					continue;
+				}
+				$options[] = 'skip='.$record2['web_folder'];
+			}
+
 			if ($shell_user_inuse || $cron_inuse || $rec['php_fpm_chroot'] == 'y' || $rec['delete_unused_jailkit'] != 'y') {
 				$sections = $jailkit_config['jailkit_chroot_app_sections'];
 				if (isset($rec['jailkit_chroot_app_sections']) && $rec['jailkit_chroot_app_sections'] != '') {
@@ -104,7 +112,7 @@ class cronjob_jailkit_maintenance extends cronjob {
 
 				if ($update_hash != $rec['last_jailkit_hash']) {
 					$app->system->web_folder_protection($rec['document_root'], false);
-					$app->system->update_jailkit_chroot($rec['document_root'], $sections, $programs, $update_options);
+					$app->system->update_jailkit_chroot($rec['document_root'], $sections, $programs, $options);
 					$app->system->web_folder_protection($rec['document_root'], true);
 					$app->db->query("UPDATE `web_domain` SET `last_jailkit_update` = NOW(), `last_jailkit_hash` = ? WHERE `document_root` = ?", $update_hash, $rec['document_root']);
 				} else {
@@ -114,7 +122,7 @@ class cronjob_jailkit_maintenance extends cronjob {
 				//$app->log('Removing unused jail: '.$rec['document_root'], LOGLEVEL_DEBUG);
 				print 'Removing unused jail: '.$rec['document_root']."\n";
 				$app->system->web_folder_protection($rec['document_root'], false);
-				$app->system->delete_jailkit_chroot($rec['document_root']);
+				$app->system->delete_jailkit_chroot($rec['document_root'], $options);
 				$app->system->web_folder_protection($rec['document_root'], true);
 
 				$app->db->query("UPDATE `web_domain` SET `last_jailkit_update` = NOW(), `last_jailkit_hash` = NULL WHERE `document_root` = ?", $rec['document_root']);
diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php
index 3aceb82c5dcfc8529c4daad5c8ce7f2ae7f87726..131d10f2442f2f5115a757ab0e49a249adb270d5 100644
--- a/server/lib/classes/system.inc.php
+++ b/server/lib/classes/system.inc.php
@@ -2415,6 +2415,9 @@ class system{
 		# /etc/jailkit/jk_init.ini is the default path, probably not needed?
 		$program_args .= ' -c /etc/jailkit/jk_init.ini -j ?';
 		foreach($app_sections as $app_section) {
+			if ($app_section == '') {
+				continue;
+			}
 			# should check that section exists with jk_init --list ?
 			$program_args .= ' ' . escapeshellarg($app_section);
 		}
@@ -2494,6 +2497,9 @@ class system{
 
 		$bad_paths = array();
 		foreach($programs as $prog) {
+			if ($prog == '') {
+				continue;
+			}
 			foreach ($blacklisted_paths_regex as $re) {
 				if (preg_match($re, $prog, $matches)) {
 					$bad_paths[] = $matches[0];
@@ -2531,9 +2537,23 @@ $app->log("update_jailkit_chroot called for $home_dir with options ".print_r($op
 			return false;
 		}
 
+		$jailkit_directories = array(
+			'bin',
+			'dev',
+			'etc',
+			'lib',
+			'lib32',
+			'lib64',
+			'opt',
+			'sys',
+			'usr',
+			'var',
+		);
+
 		$opts = array();
 		$jk_update_args = '';
 		$jk_cp_args = '';
+		$skips = '';
 		foreach ($options as $opt) {
 			switch ($opt) {
 			case '-k':
@@ -2547,6 +2567,16 @@ $app->log("update_jailkit_chroot called for $home_dir with options ".print_r($op
 				$opts[] = 'force';
 				$jk_cp_args .= ' -f';
 				break;
+			default:
+				if (preg_match('@^skip[ =]/?(.+)$@', $opt, $matches) ) {
+					if (in_array($matches[1], $jailkit_directories)) {
+						$app->log("update_jailkit_chroot: skipping update of jailkit directory $home_dir/".$matches[1]
+							. "; if this is in use as a web folder, it is insecure and should be fixed.", LOGLEVEL_WARN);
+					}
+					$jailkit_directories = $app->functions->array_unset_by_value($jailkit_directories, $matches[1]);
+					$skips .= ' --skip=/'.escapeshellarg($matches[1]);
+				}
+				break;
 			}
 		}
 
@@ -2554,20 +2584,6 @@ $app->log("update_jailkit_chroot called for $home_dir with options ".print_r($op
 		$this->chown($home_dir, 'root');
 		$this->chgrp($home_dir, 'root');
 
-		$jailkit_directories = array(
-			'bin',
-			'dev',
-			'etc',
-			'lib',
-			'lib32',
-			'lib64',
-			'opt',
-			'sys',
-			'usr',
-			'var',
-		);
-
-		$skips = '';
 		$multiple_links = array();
 		foreach ($jailkit_directories as $dir) {
 			$root_dir = '/'.$dir;
@@ -2739,9 +2755,10 @@ $app->log("update_jailkit_chroot: removing deprecated directory which jk_update
 		return true;
 	}
 
-	public function delete_jailkit_chroot($home_dir) {
+	public function delete_jailkit_chroot($home_dir, $options = array()) {
 		global $app;
 
+$app->log("delete_jailkit_chroot called for $home_dir with options ".print_r($options, true), LOGLEVEL_DEBUG);
 		$app->uses('ini_parser');
 
 		// Disallow operating on root directory
@@ -2769,6 +2786,21 @@ $app->log("update_jailkit_chroot: removing deprecated directory which jk_update
 			'run',		# not used by jailkit, but added for cleanup
 		);
 
+		foreach ($options as $opt) {
+			switch ($opt) {
+			default:
+				if (preg_match('@^skip[ =]/?(.+)$@', $opt, $matches) ) {
+					$matches[1] = ltrim($matches[1], '/');
+					if (in_array($matches[1], $jailkit_directories)) {
+						$app->log("delete_jailkit_chroot: skipping removal of jailkit directory .$home_dir/".$matches[1]
+							. "; if this is in use as a web folder, it is insecure and should be fixed.", LOGLEVEL_WARN);
+					}
+					$jailkit_directories = $app->functions->array_unset_by_value($jailkit_directories, $matches[1]);
+				}
+				break;
+			}
+		}
+
 		$removed = '';
 		foreach ($jailkit_directories as $dir) {
 			$jail_dir = rtrim($home_dir, '/') . '/'.$dir;
diff --git a/server/plugins-available/apache2_plugin.inc.php b/server/plugins-available/apache2_plugin.inc.php
index 103cfef339b7fb5564a6c98633b0b19eedadbb7f..cc4bea9f600fa334653edeb58c5becf10b0cdf9d 100644
--- a/server/plugins-available/apache2_plugin.inc.php
+++ b/server/plugins-available/apache2_plugin.inc.php
@@ -831,6 +831,11 @@ class apache2_plugin {
 			$programs = $jailkit_config['jailkit_chroot_app_programs'] . ' '
 				  . $jailkit_config['jailkit_chroot_cron_programs'];
 
+			$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $data['new']['domain_id'], $data['new']['document_root'], $conf['server_id']);
+			foreach ($records as $record) {
+				$options[] = 'skip='.$record['web_folder'];
+			}
+
 			// don't update if last_jailkit_hash is the same
 			$tmp = $app->db->queryOneRecord('SELECT `last_jailkit_hash` FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
 			if ($update_hash != $tmp['last_jailkit_hash']) {
@@ -3683,7 +3688,7 @@ class apache2_plugin {
 
 	function _setup_jailkit_chroot()
 	{
-		global $app;
+		global $app, $conf;
 
 		$app->uses('system');
 
@@ -3746,6 +3751,11 @@ class apache2_plugin {
 				return;
 			}
 
+			$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $this->website['domain_id'], $this->website['document_root'], $conf['server_id']);
+			foreach ($records as $record) {
+				$options[] = 'skip='.$record['web_folder'];
+			}
+
 			$app->system->update_jailkit_chroot($this->website['document_root'], $sections, $programs, $options);
 		}
 
@@ -3824,7 +3834,13 @@ class apache2_plugin {
 			return;
 		}
 
-		$app->system->delete_jailkit_chroot($parent_domain['document_root']);
+		$options = array();
+		$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $parent_domain_id, $parent_domain['document_root'], $conf['server_id']);
+		foreach ($records as $record) {
+			$options[] = 'skip='.$record['web_folder'];
+		}
+
+		$app->system->delete_jailkit_chroot($parent_domain['document_root'], $options);
 
 		// this gets last_jailkit_update out of sync with master db, but that is ok,
 		// as it is only used as a timestamp to moderate the frequency of updating on the slaves
diff --git a/server/plugins-available/cron_jailkit_plugin.inc.php b/server/plugins-available/cron_jailkit_plugin.inc.php
index deb6211f0e47bd9d82659e8a4286a64cc885ad2a..a186a128867f8d941a4591aa60c35aca72d4eac7 100644
--- a/server/plugins-available/cron_jailkit_plugin.inc.php
+++ b/server/plugins-available/cron_jailkit_plugin.inc.php
@@ -296,6 +296,11 @@ class cron_jailkit_plugin {
 				return;
 			}
 
+			$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $this->parent_domain['domain_id'], $this->parent_domain['document_root'], $conf['server_id']);
+			foreach ($records as $record) {
+				$options[] = 'skip='.$record['web_folder'];
+			}
+
 			$app->system->update_jailkit_chroot($this->parent_domain['document_root'], $sections, $programs, $options);
 		}
 
@@ -392,7 +397,13 @@ class cron_jailkit_plugin {
 			return;
 		}
 
-		$app->system->delete_jailkit_chroot($parent_domain['document_root']);
+		$options = array();
+		$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $parent_domain_id, $parent_domain['document_root'], $conf['server_id']);
+		foreach ($records as $record) {
+			$options[] = 'skip='.$record['web_folder'];
+		}
+
+		$app->system->delete_jailkit_chroot($parent_domain['document_root'], $options);
 
 		// this gets last_jailkit_update out of sync with master db, but that is ok,
 		// as it is only used as a timestamp to moderate the frequency of updating on the slaves
diff --git a/server/plugins-available/nginx_plugin.inc.php b/server/plugins-available/nginx_plugin.inc.php
index fc2088fefbd275976c4961d430d5d23b57e2b244..59cc56bf0889bf80c3bb929641c468d3071623ee 100644
--- a/server/plugins-available/nginx_plugin.inc.php
+++ b/server/plugins-available/nginx_plugin.inc.php
@@ -669,6 +669,11 @@ class nginx_plugin {
 			$programs = $jailkit_config['jailkit_chroot_app_programs'] . ' '
 				  . $jailkit_config['jailkit_chroot_cron_programs'];
 
+			$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $data['new']['domain_id'], $data['new']['document_root'], $conf['server_id']);
+			foreach ($records as $record) {
+				$options[] = 'skip='.$record['web_folder'];
+			}
+
 			// don't update if last_jailkit_hash is the same
 			$tmp = $app->db->queryOneRecord('SELECT `last_jailkit_hash` FROM web_domain WHERE domain_id = ?', $data['new']['parent_domain_id']);
 			if ($update_hash != $tmp['last_jailkit_hash']) {
@@ -3462,7 +3467,7 @@ class nginx_plugin {
 
 	function _setup_jailkit_chroot()
 	{
-		global $app;
+		global $app, $conf;
 
 		$app->uses('system');
 
@@ -3525,6 +3530,11 @@ class nginx_plugin {
 				return;
 			}
 
+			$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $this->website['domain_id'], $this->website['document_root'], $conf['server_id']);
+			foreach ($records as $record) {
+				$options[] = 'skip='.$record['web_folder'];
+			}
+
 			$app->system->update_jailkit_chroot($this->website['document_root'], $sections, $programs, $options);
 		}
 
@@ -3602,7 +3612,13 @@ class nginx_plugin {
 			return;
 		}
 
-		$app->system->delete_jailkit_chroot($parent_domain['document_root']);
+		$options = array();
+		$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $parent_domain_id, $parent_domain['document_root'], $conf['server_id']);
+		foreach ($records as $record) {
+			$options[] = 'skip='.$record['web_folder'];
+		}
+
+		$app->system->delete_jailkit_chroot($parent_domain['document_root'], $options);
 
 		// this gets last_jailkit_update out of sync with master db, but that is ok,
 		// as it is only used as a timestamp to moderate the frequency of updating on the slaves
diff --git a/server/plugins-available/shelluser_jailkit_plugin.inc.php b/server/plugins-available/shelluser_jailkit_plugin.inc.php
index 7c003e44683e6a3dda2585b179fef099e0ad03fd..3f8d94d2a7787251f355f60fe41989db49f84e24 100755
--- a/server/plugins-available/shelluser_jailkit_plugin.inc.php
+++ b/server/plugins-available/shelluser_jailkit_plugin.inc.php
@@ -286,7 +286,7 @@ class shelluser_jailkit_plugin {
 
 	function _setup_jailkit_chroot()
 	{
-		global $app;
+		global $app, $conf;
 
 		if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) {
 			if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') {
@@ -356,6 +356,11 @@ class shelluser_jailkit_plugin {
 				return;
 			}
 
+			$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $this->data['new']['parent_domain_id'], $this->data['new']['dir'], $conf['server_id']);
+			foreach ($records as $record) {
+				$options[] = 'skip='.$record['web_folder'];
+			}
+
 			$app->system->update_jailkit_chroot($this->data['new']['dir'], $sections, $programs, $options);
 		}
 
@@ -621,7 +626,13 @@ class shelluser_jailkit_plugin {
 			return;
 		}
 
-		$app->system->delete_jailkit_chroot($parent_domain['document_root']);
+		$options = array();
+		$records = $app->db->queryAllRecords('SELECT web_folder FROM `web_domain` WHERE `parent_domain_id` = ? AND `document_root` = ? AND web_folder != \'\' AND web_folder IS NOT NULL AND `server_id` = ?', $parent_domain_id, $parent_domain['document_root'], $conf['server_id']);
+		foreach ($records as $record) {
+			$options[] = 'skip='.$record['web_folder'];
+		}
+
+		$app->system->delete_jailkit_chroot($parent_domain['document_root'], $options);
 
 		// this gets last_jailkit_update out of sync with master db, but that is ok,
 		// as it is only used as a timestamp to moderate the frequency of updating on the slaves