diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php
index fd237b604a9a16c74caae51f188b6782ef305066..9e78d21a39d614f2f6b2219f79ac69da97e7373e 100644
--- a/apps/dav/lib/Connector/Sabre/Node.php
+++ b/apps/dav/lib/Connector/Sabre/Node.php
@@ -272,7 +272,7 @@ abstract class Node implements \Sabre\DAV\INode {
 				$mountpointpath = substr($mountpointpath, 0, -1);
 			}
 
-			if ($mountpointpath === $this->info->getPath()) {
+			if (!$mountpoint->getOption('readonly', false) && $mountpointpath === $this->info->getPath()) {
 				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
 			}
 		}
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index ffe1e9720718975784ccf1e3d8fd4b60efcc5819..983348397d101eb63a8ec8e2bc48d0f906c30e51 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -48,6 +48,12 @@ var MOUNT_OPTIONS_DROPDOWN_TEMPLATE =
 	'				<label for="mountOptionsEncoding">{{mountOptionsEncodingLabel}}</label>'+
 	'			</span>'+
 	'		</li>'+
+	'		<li class="optionRow">' +
+	'			<span class="menuitem">' +
+	'				<input id="mountOptionsReadOnly" class="checkbox" name="readonly" type="checkbox" value="true"/>' +
+	'				<label for="mountOptionsReadOnly">{{t "files_external" "Read only"}}</label>' +
+	'			</span>' +
+	'		</li>' +
 	'	</ul>'+
 	'</div>';
 
@@ -916,7 +922,8 @@ MountConfigListView.prototype = _.extend({
 				'previews': true,
 				'enable_sharing': false,
 				'filesystem_check_changes': 1,
-				'encoding_compatibility': false
+				'encoding_compatibility': false,
+				'readonly': false,
 			}));
 		}
 
@@ -1303,7 +1310,8 @@ MountConfigListView.prototype = _.extend({
 			'previews',
 			'filesystem_check_changes',
 			'enable_sharing',
-			'encoding_compatibility'
+			'encoding_compatibility',
+			'readonly'
 		];
 		if (this._encryptionEnabled) {
 			visibleOptions.push('encrypt');
diff --git a/apps/files_external/lib/Command/ListCommand.php b/apps/files_external/lib/Command/ListCommand.php
index efb2669e28164465c615188edac0e274e6da861f..89bdcf5e5d6dd1d2937efe9a7dfcf04c89d66623 100644
--- a/apps/files_external/lib/Command/ListCommand.php
+++ b/apps/files_external/lib/Command/ListCommand.php
@@ -192,7 +192,8 @@ class ListCommand extends Base {
 				'previews' => true,
 				'filesystem_check_changes' => 1,
 				'enable_sharing' => false,
-				'encoding_compatibility' => false
+				'encoding_compatibility' => false,
+				'readonly' => false,
 			];
 			$rows = array_map(function (StorageConfig $config) use ($userId, $defaultMountOptions, $full) {
 				$storageConfig = $config->getBackendOptions();
diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php
index 895be719ab4966d795e4eb94d60abfd274302276..236faf37d6d7139f00d01e8c775a4ef389fdd5d3 100644
--- a/apps/files_external/templates/settings.php
+++ b/apps/files_external/templates/settings.php
@@ -12,6 +12,7 @@
 	$l->t("Check for changes");
 	$l->t("Never");
 	$l->t("Once every direct access");
+	$l->t('Read only');
 
 	script('files_external', 'settings');
 	style('files_external', 'settings');
diff --git a/apps/files_external/tests/js/settingsSpec.js b/apps/files_external/tests/js/settingsSpec.js
index 56bdcff8345b26ce2b39286e63cdb7b61a959fa8..fbbb341c3070268968516be78f7e63342a270784 100644
--- a/apps/files_external/tests/js/settingsSpec.js
+++ b/apps/files_external/tests/js/settingsSpec.js
@@ -376,7 +376,8 @@ describe('OCA.External.Settings tests', function() {
 					previews: true,
 					enable_sharing: false,
 					filesystem_check_changes: 0,
-					encoding_compatibility: false
+					encoding_compatibility: false,
+					readonly: false
 				});
 			});
 		});
diff --git a/apps/files_sharing/tests/js/sharedfilelistSpec.js b/apps/files_sharing/tests/js/sharedfilelistSpec.js
index 492a7255c61eac7b4358d3a9cb57bf6de75fd579..0897e9c956df1ba5cca9e800582505fde3915706 100644
--- a/apps/files_sharing/tests/js/sharedfilelistSpec.js
+++ b/apps/files_sharing/tests/js/sharedfilelistSpec.js
@@ -727,7 +727,8 @@ describe('OCA.Sharing.FileList tests', function() {
 				etag: 'abc',
 				shareOwner: 'User One',
 				recipients: 'User Two',
-				mountType: 'external-root'
+				mountType: 'external-root',
+				sharePermissions: OC.PERMISSION_READ,
 			}]);
 			$tr = fileList.$el.find('tr:first');
 
@@ -749,7 +750,8 @@ describe('OCA.Sharing.FileList tests', function() {
 				etag: 'abc',
 				shareOwner: 'User One',
 				recipients: 'User Two',
-				mountType: 'external-root'
+				mountType: 'external-root',
+				sharePermissions: OC.PERMISSION_READ | OC.PERMISSION_SHARE,
 			}]);
 			$tr = fileList.$el.find('tr:first');
 
diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php
index d3599d14e7afe523de82ae3d18ad2f80514b8abf..356d336f687e69265a50c40e955a887e7603abf1 100644
--- a/lib/private/legacy/util.php
+++ b/lib/private/legacy/util.php
@@ -259,6 +259,23 @@ class OC_Util {
 			return $storage;
 		});
 
+		\OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
+			/*
+			 * Do not allow any operations that modify the storage
+			 */
+			if ($mount->getOption('readonly', false)) {
+				return new \OC\Files\Storage\Wrapper\PermissionsMask([
+					'storage' => $storage,
+					'mask' => \OCP\Constants::PERMISSION_ALL & ~(
+						\OCP\Constants::PERMISSION_UPDATE |
+						\OCP\Constants::PERMISSION_CREATE |
+						\OCP\Constants::PERMISSION_DELETE
+					),
+				]);
+			}
+			return $storage;
+		});
+
 		OC_Hook::emit('OC_Filesystem', 'preSetup', array('user' => $user));
 		\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(true);