Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

We need a way to rename homeservers (SYN-28) #1209

Closed
matrixbot opened this issue Dec 15, 2023 · 2 comments
Closed

We need a way to rename homeservers (SYN-28) #1209

matrixbot opened this issue Dec 15, 2023 · 2 comments

Comments

@matrixbot
Copy link
Collaborator

matrixbot commented Dec 15, 2023

This issue has been migrated from #1209.


The current common use case for Synapse is that people install it running as localhost - have a play with it; see that it's good.

They then want to expose the same server to run as --server-name foo.net - except there isn't (as far as I know) an easy way to change the server-name without vaping the whole HS DB. We need one.

(Imported from https://matrix.org/jira/browse/SYN-28)

(Reported by @ara4n)

@matrixbot matrixbot changed the title Dummy issue We need a way to rename homeservers (SYN-28) Dec 21, 2023
@rnhmjoj
Copy link

rnhmjoj commented Oct 16, 2024

So, this has been open for 10 years; at this rate I'm sure it will never be implemented.
Does anybody know if there is a way to at least preserve some rooms history by importing them into the new database?

@rnhmjoj
Copy link

rnhmjoj commented Oct 27, 2024

I found this script called matrix-copy-room-history, it's not meant to migrate between different databases/homeservers, but with some minor changes it does work.
Sadly you can't preserve the timestamps, because the appservice API doesn't allow that.

Specifically you need to add a mapping between old and new user IDs and some tweaking to handle threads, the rest works okish:

diff --git a/index.js b/index.js
index 8c221d1..76c5220 100644
--- a/index.js
+++ b/index.js
@@ -13,6 +13,7 @@ async function asyncForEach(array, callback) {
 }
 
 const ROOMS = require('./mapped_rooms.json');
+const USERS = require('./mapped_users.json');
 
 let bridge;
 
@@ -56,6 +57,7 @@ new Cli({
     bridge.run(port, config).then(async () => {
       let importFolders = fs.readdirSync(ELEMENT_EXPORT_FOLDER).sort();
       await asyncForEach(importFolders, async (jsonFile) => {
+        console.log('copying ' + jsonFile + '...')
         let hasJoined = {}
         let isInvited = {}
 
@@ -84,38 +86,53 @@ new Cli({
           return 0;
         });
 
+        console.log('sorted messages');
+
         await asyncForEach(messages, async (msg) => {
+
           if (!msg.hasOwnProperty('type') || msg.type !== "m.room.message") {
+            console.log('no type');
             return;
           }
 
           if (!msg.hasOwnProperty('room_id')) {
+            console.log('no room id');
             return;
           }
 
           let originalRoomId = msg.room_id;
 
           if (!ROOMS.hasOwnProperty(originalRoomId)) {
+            console.log('room not in mapped_rooms');
             return;
           }
 
           if (!msg.hasOwnProperty('content')) {
+            console.log('no content');
             return;
           }
 
           if (!msg.content.hasOwnProperty('body')) {
+            console.log('no body');
             return;
           }
 
           let content = msg.content;
 
           if (!msg.hasOwnProperty('sender')) {
+            console.log('no sender');
             return;
           }
 
-          let userID = msg.sender;
+          let userID;
+          if (USERS.hasOwnProperty(msg.sender)) {
+            userID = USERS[msg.sender];
+          } else {
+            userID = msg.sender.split(":")[0] + ":new_domain_here";
+          }
 
           if (!msg.hasOwnProperty('event_id')) {
+            console.log('no event_id');
             return;
           }
 
@@ -130,6 +147,9 @@ new Cli({
               let newEventID = mappedEvents[oldEventID];
 
               content["m.relates_to"]["m.in_reply_to"]["event_id"] = newEventID;
+              content["m.relates_to"]["event_id"] = newEventID;
+            } else {
+              delete content["m.relates_to"];
             }
           }
 
@@ -146,14 +166,24 @@ new Cli({
           let roomID = ROOMS[originalRoomId];
 
           if (!isInvited.hasOwnProperty(userID) && userID !== INVITER) {
-            await ownerIntent.invite(roomID, userID);
+            try {
+              await ownerIntent.invite(roomID, userID);
+            }
+            catch(e) {
+              console.log('already invited ' + userID)
+            }
             isInvited[userID] = true;
           }
 
           let intent = bridge.getIntent(userID);
 
           if (!hasJoined.hasOwnProperty(userID) && userID !== INVITER) {
-            await intent.join(roomID);
+            try {
+              await intent.join(roomID);
+            }
+            catch(e) {
+              console.log('already joined ' + roomID)
+            }
             hasJoined[userID] = true;
           }

So, the steps are:

  1. Generate exports of all the rooms you want to preserve using element, if these are encrypted you need the cooperation of at least one member. Don't include attachments: element has a 2GB limit on the export file and you don't need them anyway. (if you really want, you need to bypass the limit by patching matrix-react-sdk and run element in a browser that allows large memory allocations, not chromium, yes firefox).

  2. Grep all the local mxc:// URIs from the exported JSON files, build a list of the medi IDs, query the local_media_repository table for these IDs and dump the result in a big SQL file.

  3. Copy over all the files from /var/lib/matrix-synapse/media_store/local_content that matches the media IDs. Note: the first 4 characters of the media ID are used to split the files into two order of subdirectories (eg. ZdfEkUtucffsnHvngwLBJWCG -> /Zd/fE/kUtucffsnHvngwLBJWCG)

  4. Rereate every local user and room in the new homeserver, replace the user IDs in the SQL file with the new IDs, and run it to insert the preserved medias. Note: there's no need to manually invite the users to the rooms.

  5. Follow the instructions to set up the matrix-copy-room-history appservice and run the script to import all the room events. In my case it run at about 10msg/s, so it will take about a day to recreate a few years worth of messages.

  6. Assuming you can still access the old homeserver, you can use the EMS migration tool to join all federated rooms with your new users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants