Files
website/dist/articles/synapse-revitalization-script/index.html

78 lines
6.7 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<!--<link rel="icon" type="image/svg+xml" href="/favicon.svg" />-->
<meta name="generator" content="Astro v2.10.7">
<meta name="description" content="{frontmatter.description}">
<meta name="keywords" content="nothing crypto free software libre self host {frontmatter.keys}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/nothingrun-favicon-whiteonblack.png" type="image/png">
<title>Restoration of Synapse after disappearing 1 year of database history</title>
2025-08-20 03:10:01 +03:00
<link rel="stylesheet" href="/_astro/contact.5916896f.css" /></head>
<body>
<div class="header astro-HPNW4VWY">
<a href="/" class="astro-HPNW4VWY">~/</a>
<a href="/contact" class="astro-HPNW4VWY">Contact</a>
<a href="https://uptime.nothing.run" class="astro-HPNW4VWY">Uptime</a>
<a href="/news" class="astro-HPNW4VWY">News</a>
<a href="/notes" class="astro-HPNW4VWY">Notes</a>
<a href="/donate" class="astro-HPNW4VWY">Donate :3</a>
</div>
<h1>Restoration of Synapse after disappearing 1 year of database history</h1>
<div class="article"><h2 id="introduction">Introduction</h2><p>In July 2025, my PostgreSQL had broken, so I needed to restore it from my 1-y.o. backup. I was thinking about what to do, and my friend sent me <a href="https://blog.erethon.com/blog/2023/06/21/what-happens-when-a-matrix-server-disappears/">this</a> article, so we understood what to do!</p><p>For example, there is a room called #example:example.org (roomid !example:example.org), whose member was @user:example.net.
The problem is that every server knows @user:example.net is in the room #example:example.org. But our server doesnt! So that is what we should aim at solving the problem.</p><h2 id="architecture">Architecture</h2><p>We get 2 types of error messages:</p><ul>
<li><code>synapse.handlers.receipts: [PUT-...] Ignoring receipt for room &#39;!example:example.org&#39; from server example.org as we&#39;re not in the room</code> (there is the same error message, but when you get a typing event from an unknown room)</li>
<li><code>synapse.federation.federation_server: [PUT-...] Ignoring PDU for unknown room_id: !example:example.org</code></li>
</ul><p>We can read the journal and parse the error message (I use a bash script to do that).
Okay, we have a room id! In the given article, the author is the only user of their server, so they can just send <a href="https://spec.matrix.org/v1.15/client-server-api/#post_matrixclientv3joinroomidoralias">POST /_matrix/client/v3/join/!example:example.org</a> request, and everything will be good.
But my server has multiple users, so I cant use the easiest way. We need to get information about membership (so we need to get state).</p><p>As we are admins of our servers, we have their signing keys.
We will need them because we are going to get state via Federation API requests.
How? There are different ways to do that.
However, all of them require at least 1 event id, so firstly we need to do <a href="https://spec.matrix.org/v1.15/server-server-api/#get_matrixfederationv1timestamp_to_eventroomid">GET /_matrix/federation/v1/timestamp_to_event</a>.
Determining request parameters (?dir as direction (b[ackward] or f[orward]) and &amp;ts as timestamp in Unix time format in milliseconds), we have just got either the last or the first event id! In my case, I chose the way of getting the last event, so then Ill have to make <a href="https://spec.matrix.org/v1.15/server-server-api/#get_matrixfederationv1stateroomid">GET /_matrix/federation/v1/state/!example:example.org?event_id=$event_id</a>, and I will get the actual state.
Of course, both of the requests, as I said, should be signed using your servers key (<a href="https://spec.matrix.org/v1.15/server-server-api/#signing-events">how to sign events</a>).</p><br/><p>(There is no support of timestamp_to_event in Conduit, so it would be a good idea to make support of requesting different servers)</p><p>After we receive the state, we need to parse it, but I think this cant make a difficulty.
As a result, we have a list of our users that were in the given room, like [“@user:example.net”, “@anotheruser:example.net”, “@exampleuser:example.net”].
Then, the simplest way is to get temporary users auth token via <a href="https://github.com/matrix-org/synapse/blob/develop/docs/admin_api/user_admin_api.md#login-as-a-user">POST /_synapse/admin/v1/users/user_id/login</a> and make <a href="https://spec.matrix.org/v1.15/client-server-api/#post_matrixclientv3joinroomidoralias">POST /_matrix/client/v3/join/!example:example.org</a> from the name of the user using their token.
The problem is solved!</p><h2 id="external-links">External links</h2><ul>
<li><a href="https://blog.erethon.com/blog/2023/06/21/what-happens-when-a-matrix-server-disappears/">Article that gave me the idea</a></li>
<li><a href="https://spec.matrix.org/v1.15/server-server-api/">Matrix Federation API docs</a>
<ul>
<li><a href="https://spec.matrix.org/v1.15/server-server-api/#signing-events">How to sign Federation API requests</a></li>
<li><a href="https://spec.matrix.org/v1.15/server-server-api/#get_matrixfederationv1stateroomid">GET /_matrix/federation/v1/state/!example:example.org?event_id=$event_id</a></li>
<li><a href="https://spec.matrix.org/v1.15/server-server-api/#get_matrixfederationv1timestamp_to_eventroomid">GET /_matrix/federation/v1/timestamp_to_event</a></li>
</ul>
</li>
<li><a href="https://spec.matrix.org/v1.15/server-server-api/">Matrix Client API docs</a>
<ul>
<li><a href="https://spec.matrix.org/v1.15/client-server-api/#post_matrixclientv3joinroomidoralias">POST /_matrix/client/v3/join/!example:example.org</a></li>
</ul>
</li>
<li><a href="https://github.com/matrix-org/synapse/blob/develop/docs/admin_api/user_admin_api.md#login-as-a-user">Admin API POST /_synapse/admin/v1/users/user_id/login</a></li>
</ul></div>
<div id="footer">
<main>
<pre> .--.
." o \__
_.-" ,( `
_.-" ,;;|
_.-=" _," ,,;;;'
.-"`_.-"``-..,,;;;;:'
`"'` `\`\
/^\\\
</pre>
</main>
<aside>
<b>Made with ♥</b> by Thary<br>
<!-- Website sources are available on <a href="https://git.vector1.dev/thary/website">Gitea</a>!<br> -->
<!-- All content is in Public domain and licensed under <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a><br> -->
Logo is created by <a href="https://houl.floof.company/">Houl</a><br>
ASCII arts are taken from <a href="https://web.archive.org/web/20010420182629/http://www.geocities.com/spunk1111/indexjava.htm">this website</a>
</aside>
</div>
</body></html>