diff --git a/gateway/platforms/matrix.py b/gateway/platforms/matrix.py index 9ba63c083..9f3d6358c 100644 --- a/gateway/platforms/matrix.py +++ b/gateway/platforms/matrix.py @@ -18,6 +18,7 @@ Environment variables: MATRIX_REQUIRE_MENTION Require @mention in rooms (default: true) MATRIX_FREE_RESPONSE_ROOMS Comma-separated room IDs exempt from mention requirement MATRIX_AUTO_THREAD Auto-create threads for room messages (default: true) + MATRIX_RECOVERY_KEY Recovery key for cross-signing verification after device key rotation MATRIX_DM_MENTION_THREADS Create a thread when bot is @mentioned in a DM (default: false) """ diff --git a/hermes_cli/config.py b/hermes_cli/config.py index 3d8004cd3..8c46f8bba 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -50,6 +50,7 @@ _EXTRA_ENV_KEYS = frozenset({ "MATTERMOST_HOME_CHANNEL", "MATTERMOST_REPLY_MODE", "MATRIX_PASSWORD", "MATRIX_ENCRYPTION", "MATRIX_DEVICE_ID", "MATRIX_HOME_ROOM", "MATRIX_REQUIRE_MENTION", "MATRIX_FREE_RESPONSE_ROOMS", "MATRIX_AUTO_THREAD", + "MATRIX_RECOVERY_KEY", }) import yaml @@ -1293,6 +1294,14 @@ OPTIONAL_ENV_VARS = { "category": "messaging", "advanced": True, }, + "MATRIX_RECOVERY_KEY": { + "description": "Matrix recovery key for cross-signing verification after device key rotation (from Element: Settings → Security → Recovery Key)", + "prompt": "Matrix recovery key", + "url": None, + "password": True, + "category": "messaging", + "advanced": True, + }, "BLUEBUBBLES_SERVER_URL": { "description": "BlueBubbles server URL for iMessage integration (e.g. http://192.168.1.10:1234)", "prompt": "BlueBubbles server URL", diff --git a/website/docs/reference/environment-variables.md b/website/docs/reference/environment-variables.md index bec5ff1c3..ff832a036 100644 --- a/website/docs/reference/environment-variables.md +++ b/website/docs/reference/environment-variables.md @@ -277,6 +277,7 @@ For cloud sandbox backends, persistence is filesystem-oriented. `TERMINAL_LIFETI | `MATRIX_FREE_RESPONSE_ROOMS` | Comma-separated room IDs where bot responds without `@mention` | | `MATRIX_AUTO_THREAD` | Auto-create threads for room messages (default: `true`) | | `MATRIX_DM_MENTION_THREADS` | Create a thread when bot is `@mentioned` in a DM (default: `false`) | +| `MATRIX_RECOVERY_KEY` | Recovery key for cross-signing verification after device key rotation. Recommended for E2EE setups with cross-signing enabled. | | `HASS_TOKEN` | Home Assistant Long-Lived Access Token (enables HA platform + tools) | | `HASS_URL` | Home Assistant URL (default: `http://homeassistant.local:8123`) | | `WEBHOOK_ENABLED` | Enable the webhook platform adapter (`true`/`false`) | diff --git a/website/docs/user-guide/messaging/matrix.md b/website/docs/user-guide/messaging/matrix.md index ccde0740d..de03ff817 100644 --- a/website/docs/user-guide/messaging/matrix.md +++ b/website/docs/user-guide/messaging/matrix.md @@ -272,6 +272,18 @@ When E2EE is enabled, Hermes: - Decrypts incoming messages and encrypts outgoing messages automatically - Auto-joins encrypted rooms when invited +### Cross-Signing Verification (Recommended) + +If your Matrix account has cross-signing enabled (the default in Element), set the recovery key so the bot can self-sign its device on startup. Without this, other Matrix clients may refuse to share encryption sessions with the bot after a device key rotation. + +```bash +MATRIX_RECOVERY_KEY=EsT... your recovery key here +``` + +**Where to find it:** In Element, go to **Settings** → **Security & Privacy** → **Encryption** → your recovery key (also called the "Security Key"). This is the key you were asked to save when you first set up cross-signing. + +On each startup, if `MATRIX_RECOVERY_KEY` is set, Hermes imports cross-signing keys from the homeserver's secure secret storage and signs the current device. This is idempotent and safe to leave enabled permanently. + :::warning If you delete the `~/.hermes/platforms/matrix/store/` directory, the bot loses its encryption keys. You'll need to verify the device again in your Matrix client. Back up this directory if you want to preserve encrypted sessions. ::: @@ -374,7 +386,7 @@ changed identity keys for the same device as suspicious. -d '{ "type": "m.login.password", "identifier": {"type": "m.id.user", "user": "@hermes:your-server.org"}, - "password": "your-password", + "password": "***", "initial_device_display_name": "Hermes Agent" }' ``` @@ -388,17 +400,27 @@ changed identity keys for the same device as suspicious. rm -f ~/.hermes/platforms/matrix/store/crypto_store.* ``` -3. **Force your Matrix client to rotate the encryption session**. In Element, +3. **Set your recovery key** (if you use cross-signing — most Element users do). Add to `~/.hermes/.env`: + + ```bash + MATRIX_RECOVERY_KEY=EsT... your recovery key here + ``` + + This lets the bot self-sign with cross-signing keys on startup, so Element trusts the new device immediately. Without this, Element may see the new device as unverified and refuse to share encryption sessions. Find your recovery key in Element under **Settings** → **Security & Privacy** → **Encryption**. + +4. **Force your Matrix client to rotate the encryption session**. In Element, open the DM room with the bot and type `/discardsession`. This forces Element to create a new encryption session and share it with the bot's new device. -4. **Restart the gateway**: +5. **Restart the gateway**: ```bash hermes gateway run ``` -5. **Send a new message**. The bot should decrypt and respond normally. + If `MATRIX_RECOVERY_KEY` is set, you should see `Matrix: cross-signing verified via recovery key` in the logs. + +6. **Send a new message**. The bot should decrypt and respond normally. :::note After migration, messages sent *before* the upgrade cannot be decrypted -- the old