diff --git a/src/config.rs b/src/config.rs
index a6ab63e3..4a3a0544 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -68,6 +68,8 @@ pub struct Config {
     #[serde(default = "default_turn_ttl")]
     pub turn_ttl: u64,
 
+    pub emergency_password: Option<String>,
+
     #[serde(flatten)]
     pub catchall: BTreeMap<String, IgnoredAny>,
 }
diff --git a/src/database.rs b/src/database.rs
index e0745c54..69cf3fc8 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -19,7 +19,14 @@ use abstraction::DatabaseEngine;
 use directories::ProjectDirs;
 use futures_util::{stream::FuturesUnordered, StreamExt};
 use lru_cache::LruCache;
-use ruma::{DeviceId, EventId, RoomId, UserId};
+use ruma::{
+    events::{
+        push_rules::PushRulesEventContent, room::message::RoomMessageEventContent, EventType,
+        GlobalAccountDataEvent,
+    },
+    push::Ruleset,
+    DeviceId, EventId, RoomId, UserId,
+};
 use std::{
     collections::{BTreeMap, HashMap, HashSet},
     fs::{self, remove_dir_all},
@@ -747,6 +754,23 @@ impl Database {
         guard.rooms.edus.presenceid_presence.clear()?;
 
         guard.admin.start_handler(Arc::clone(&db), admin_receiver);
+
+        // Set emergency access for the conduit user
+        match set_emergency_access(&guard) {
+            Ok(pwd_set) => {
+                if pwd_set {
+                    warn!("The Conduit account emergency password is set! Please unset it as soon as you finish admin account recovery!");
+                    guard.admin.send_message(RoomMessageEventContent::text_plain("The Conduit account emergency password is set! Please unset it as soon as you finish admin account recovery!"));
+                }
+            }
+            Err(e) => {
+                error!(
+                    "Could not set the configured emergency password for the conduit user: {}",
+                    e
+                )
+            }
+        };
+
         guard
             .sending
             .start_handler(Arc::clone(&db), sending_receiver);
@@ -928,6 +952,32 @@ impl Database {
     }
 }
 
+/// Sets the emergency password and push rules for the @conduit account in case emergency password is set
+fn set_emergency_access(db: &Database) -> Result<bool> {
+    let conduit_user = UserId::parse_with_server_name("conduit", db.globals.server_name())
+        .expect("@conduit:server_name is a valid UserId");
+
+    db.users
+        .set_password(&conduit_user, db.globals.emergency_password().as_deref())?;
+
+    let (ruleset, res) = match db.globals.emergency_password() {
+        Some(_) => (Ruleset::server_default(&conduit_user), Ok(true)),
+        None => (Ruleset::new(), Ok(false)),
+    };
+
+    db.account_data.update(
+        None,
+        &conduit_user,
+        EventType::PushRules,
+        &GlobalAccountDataEvent {
+            content: PushRulesEventContent { global: ruleset },
+        },
+        &db.globals,
+    )?;
+
+    res
+}
+
 pub struct DatabaseGuard(OwnedRwLockReadGuard<Database>);
 
 impl Deref for DatabaseGuard {
diff --git a/src/database/admin.rs b/src/database/admin.rs
index f2e66e43..f5f3ba6d 100644
--- a/src/database/admin.rs
+++ b/src/database/admin.rs
@@ -8,7 +8,7 @@ use std::{
 use crate::{
     error::{Error, Result},
     pdu::PduBuilder,
-    server_server,
+    server_server, utils,
     utils::HtmlEscape,
     Database, PduEvent,
 };
@@ -262,6 +262,12 @@ enum AdminCommand {
 
     /// Show configuration values
     ShowConfig,
+
+    /// Reset user password
+    ResetPassword {
+        /// Username of the user for whom the password should be reset
+        username: String,
+    },
 }
 
 fn process_admin_command(
@@ -435,6 +441,45 @@ fn process_admin_command(
             // Construct and send the response
             RoomMessageEventContent::text_plain(format!("{}", db.globals.config))
         }
+        AdminCommand::ResetPassword { username } => {
+            let user_id = match UserId::parse_with_server_name(
+                username.as_str().to_lowercase(),
+                db.globals.server_name(),
+            ) {
+                Ok(id) => id,
+                Err(e) => {
+                    return Ok(RoomMessageEventContent::text_plain(format!(
+                        "The supplied username is not a valid username: {}",
+                        e
+                    )))
+                }
+            };
+
+            // Check if the specified user is valid
+            if !db.users.exists(&user_id)?
+                || db.users.is_deactivated(&user_id)?
+                || user_id
+                    == UserId::parse_with_server_name("conduit", db.globals.server_name())
+                        .expect("conduit user exists")
+            {
+                return Ok(RoomMessageEventContent::text_plain(
+                    "The specified user does not exist or is deactivated!",
+                ));
+            }
+
+            let new_password = utils::random_string(20);
+
+            match db.users.set_password(&user_id, Some(new_password.as_str())) {
+                Ok(()) => RoomMessageEventContent::text_plain(format!(
+                    "Successfully reset the password for user {}: {}",
+                    user_id, new_password
+                )),
+                Err(e) => RoomMessageEventContent::text_plain(format!(
+                    "Couldn't reset the password for user {}: {}",
+                    user_id, e
+                )),
+            }
+        }
     };
 
     Ok(reply_message_content)
diff --git a/src/database/globals.rs b/src/database/globals.rs
index 9a9163be..ee7db539 100644
--- a/src/database/globals.rs
+++ b/src/database/globals.rs
@@ -264,6 +264,10 @@ impl Globals {
         &self.config.turn_secret
     }
 
+    pub fn emergency_password(&self) -> &Option<String> {
+        &self.config.emergency_password
+    }
+
     /// TODO: the key valid until timestamp is only honored in room version > 4
     /// Remove the outdated keys and insert the new ones.
     ///
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index 88a07295..7939edc4 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -1491,7 +1491,11 @@ impl Rooms {
                     let server_user = format!("@conduit:{}", db.globals.server_name());
 
                     let to_conduit = body.starts_with(&format!("{}: ", server_user));
-                    let from_conduit = pdu.sender == server_user;
+
+                    // This will evaluate to false if the emergency password is set up so that
+                    // the administrator can execute commands as conduit
+                    let from_conduit =
+                        pdu.sender == server_user && db.globals.emergency_password().is_none();
 
                     if to_conduit && !from_conduit && admin_room.as_ref() == Some(&pdu.room_id) {
                         db.admin.process_message(body.to_string());