diff --git a/api/custom/quarantine.go b/api/custom/quarantine.go
index 459e59fb0640db4ce8364cca3183268c4d19b057..4922cf9304592d77b65c7d65d14fad53284c21ee 100644
--- a/api/custom/quarantine.go
+++ b/api/custom/quarantine.go
@@ -117,6 +117,45 @@ func QuarantineUserMedia(r *http.Request, log *logrus.Entry, user api.UserInfo)
 	return &api.DoNotCacheResponse{Payload: &MediaQuarantinedResponse{NumQuarantined: total}}
 }
 
+func QuarantineDomainMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} {
+	canQuarantine, allowOtherHosts, isLocalAdmin := getQuarantineRequestInfo(r, log, user)
+	if !canQuarantine {
+		return api.AuthFailed()
+	}
+
+	params := mux.Vars(r)
+
+	serverName := params["serverName"]
+
+	log = log.WithFields(logrus.Fields{
+		"serverName": serverName,
+		"localAdmin": isLocalAdmin,
+	})
+
+	if !allowOtherHosts && serverName != r.Host {
+		return api.AuthFailed()
+	}
+
+	db := storage.GetDatabase().GetMediaStore(r.Context(), log)
+	userMedia, err := db.GetAllMediaForServer(serverName)
+	if err != nil {
+		log.Error("Error while listing media for the server: " + err.Error())
+		return api.InternalServerError("error retrieving media for server")
+	}
+
+	total := 0
+	for _, media := range userMedia {
+		resp, ok := doQuarantineOn(media, allowOtherHosts, log, r.Context())
+		if !ok {
+			return resp
+		}
+
+		total += resp.(*MediaQuarantinedResponse).NumQuarantined
+	}
+
+	return &api.DoNotCacheResponse{Payload: &MediaQuarantinedResponse{NumQuarantined: total}}
+}
+
 func QuarantineMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} {
 	canQuarantine, allowOtherHosts, isLocalAdmin := getQuarantineRequestInfo(r, log, user)
 	if !canQuarantine {
diff --git a/api/webserver/webserver.go b/api/webserver/webserver.go
index 724cb383ae8eb540d94b16fa70eb0c010f95a1b5..570c18cdf0cffaf472780e8fbb1224b93685d6f1 100644
--- a/api/webserver/webserver.go
+++ b/api/webserver/webserver.go
@@ -41,6 +41,7 @@ func Init() {
 	quarantineHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineMedia), "quarantine_media", counter, false}
 	quarantineRoomHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineRoomMedia), "quarantine_room", counter, false}
 	quarantineUserHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineUserMedia), "quarantine_user", counter, false}
+	quarantineDomainHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineDomainMedia), "quarantine_domain", counter, false}
 	localCopyHandler := handler{api.AccessTokenRequiredRoute(unstable.LocalCopy), "local_copy", counter, false}
 	infoHandler := handler{api.AccessTokenRequiredRoute(unstable.MediaInfo), "info", counter, false}
 	configHandler := handler{api.AccessTokenRequiredRoute(r0.PublicConfig), "config", counter, false}
@@ -91,6 +92,7 @@ func Init() {
 		routes["/_matrix/media/"+version+"/admin/quarantine/{server:[a-zA-Z0-9.:\\-_]+}/{mediaId:[a-zA-Z0-9.\\-_]+}"] = route{"POST", quarantineHandler}
 		routes["/_matrix/media/"+version+"/admin/quarantine/room/{roomId:[^/]+}"] = route{"POST", quarantineRoomHandler}
 		routes["/_matrix/media/"+version+"/admin/quarantine/user/{userId:[^/]+}"] = route{"POST", quarantineUserHandler}
+		routes["/_matrix/media/"+version+"/admin/quarantine/server/{serverName:[^/]+}"] = route{"POST", quarantineDomainHandler}
 		routes["/_matrix/media/"+version+"/admin/datastores/{datastoreId:[^/]+}/size_estimate"] = route{"GET", storageEstimateHandler}
 		routes["/_matrix/media/"+version+"/admin/datastores"] = route{"GET", datastoreListHandler}
 		routes["/_matrix/media/"+version+"/admin/datastores/{sourceDsId:[^/]+}/transfer_to/{targetDsId:[^/]+}"] = route{"POST", dsTransferHandler}
diff --git a/docs/admin.md b/docs/admin.md
index aad4fbf70cb9af6f8f6ef1745bd2a5f5a275565b..a00bf4774ca4e8ba1773e4ee3336f3472d3453a9 100644
--- a/docs/admin.md
+++ b/docs/admin.md
@@ -80,6 +80,12 @@ URL: `POST /_matrix/media/unstable/admin/quarantine/room/<room id>?access_token=
 
 URL: `POST /_matrix/media/unstable/admin/quarantine/user/<user id>?access_token=your_access_token`
 
+#### Quarantine a whole server's worth of media
+
+URL: `POST /_matrix/media/unstable/admin/quarantine/server/<server name>?access_token=your_access_token`
+
+Note that this will only quarantine what is currently known to the repo. It will not flag the domain for future quarantines.
+
 ## Datastore management
 
 Datastores are used by the media repository to put files. Typically these match what is configured in the config file, such as s3 and directories.