1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
|
Document: WM-067 P. Webb
Category: Self Hosting 2025.04.25
Enter the Matrix
Abstract
When all else fails, DIY!
Body
When Element decided to change their cloud hosting pricing last year,
I had a decision to make; pay more money[1] per user on my account
(€60 per user/year, paid annually), setup my own server using Synapse
(the only Matrix software that was out at the time), or go with some
third‑party. Synapse was hella complicated to deal with so I decided
to go with the latter.
Long story short, this third‑party (Federated Computer) is not good.
Just this past weekend, they performed an unannounced server upgrade
which broke my instance and I was gaslit by someone on their support
team until I mentioned I only experienced issues over the weekend.
They refused to answer my very direct question ("how can I export my
data?") three times before pointing me to the room chat export
feature of Element, which was not what I asked for. EMS (Element
Matrix Services) provided everyone on their platform with a dashboard
where they could export the database and other files necessary to
import to a new host. When I approached FC (who were listed as hosts
recommended by EMS), they instructed me to upload to SwissTransfer[2]
so they could concierge the process.
You'd think the folks at Federated Computer would remember/understand
that, no?
They've also got quite the lackluster dashboard UI. I've designed
better when I got my start coding in 2008. Anyhoo, YMMV but FC is not
for me. This experience was enough impetus to explore if the Matrix
self‑host landscape changed and luckily, it has!
After some quick research, I decided to go with Conduit[3] as my
Matrix server. It's written in Rust, is in beta at the time of this
post, and its instructions are slightly wrong so I'm writing this
post for future me and friends.
Before I get into it, a few things:
Sliding Sync[4] is not implemented yet. The fancy Element X client
uses it for quick syncing of Matrix rooms and I wanna use it.
I asked about SS in Conduit's Matrix room:
> The current sliding sync implementation is not working as we need
> simple sliding sync now. And that is not ready in conduit yet.
The developer leading this feature has said it is high on his list
of priorities.
Also, when I invited my friends to my new server I wasn't able to see
their messages decrypted, even after verifying my sessions. I still
can't see those initial messages but the syncing has been fine for
the past few days so maybe that was just some setup weirdness.
1. Installing Conduit
I'll assume you're installing Conduit on Linux. I prefer Ubuntu
LTS for my servers. The Conduit install tutorial gives you three
types of binaries to install: statically linked Debian package,
statically linked binary, and OCI image.
I didn't realize the Debian package didn't work for me until much
later. The statically linked binary worked though. Unless you are
on an ARM platform, you should choose one of the `x86_64` options.
I used `x86_64-unknown-linux-musl`:
```sh
# download binary to your system
wget -O /usr/local/bin/matrix-conduit https://gitlab.com/api/v4/projects/famedly%2Fconduit/jobs/artifacts/master/raw/x86_64-unknown-linux-musl?job=artifacts
# make binary executable
chmod +x /usr/local/bin/matrix-conduit
# add a user that will handle the Conduit process
adduser --system conduit --group --disabled-login --no-create-home
```
Next, we'll set up the systemd service:
```sh
nano /etc/systemd/system/conduit.service
```
```toml
[Unit]
Description=Conduit Matrix Server
After=network.target
[Service]
Environment="CONDUIT_CONFIG=/etc/matrix-conduit/conduit.toml"
User=conduit
Group=conduit
Restart=always
ExecStart=/usr/local/bin/matrix-conduit
[Install]
WantedBy=multi-user.target
```
Reload systemd so it knows about Conduit:
```sh
systemctl daemon-reload
```
Now it's the fun part, creating the Conduit configuration file so
you can customize (like increasing the file upload limit past the
default 20MB)!
```sh
# create directory
mkdir -p /etc/matrix-conduit
nano /etc/matrix-conduit/conduit.toml
```
The only things I've changed are `max_request_size` (so I can
share gaming clips with my friends, 20MB is NOT enough),
`enable_lightning_bolt`, `registration_token`, and `server_name`.
I thought I needed to give my friends the token but I just sent
invites to their Matrix addresses instead. I wonder if I can set
`allow_registration` to false and still invite people to
my server…
```toml
[global]
# This makes sure Conduit can only be reached using the
# reverse proxy
address = "127.0.0.1"
allow_check_for_updates = true
allow_federation = true
# Enables registration. If set to false, no users can register on
# this server.
allow_registration = true
database_backend = "rocksdb"
# This is the only directory where Conduit will save its data
database_path = "/var/lib/matrix-conduit/"
# Enable the display name lightning bolt on registration.
enable_lightning_bolt = false
# Max size for uploads in bytes (100MB)
max_request_size = 100_000_000
# The port Conduit will be running on. You need to set up a
# reverse proxy in your web server (e.g. apache or nginx), so all
# requests to /_matrix on port 443 and 8448 will be forwarded to
# the Conduit instance running on this port
port = 6167
# A static registration token that new users will have to provide
# when creating an account. YOU NEED TO EDIT THIS.
# - Insert a password that users will have to enter
# on registration
# - Start the line with "#" to remove the condition
registration_token = "your-generated-token"
server_name = "matrix.webb.page"
# Servers listed here will be used to gather public keys of
# other servers.
trusted_servers = ["matrix.org"]
```
Now we've gotta set file permissions. Almost done!
```sh
chown -R root:root /etc/matrix-conduit
chmod 755 /etc/matrix-conduit
# gotta make more directories
mkdir -p /var/lib/matrix-conduit/
chown -R conduit:conduit /var/lib/matrix-conduit/
chmod 700 /var/lib/matrix-conduit/
```
I already had Caddy setup from my new server install script[6],
but here's the relevant portion:
```sh
apt install debian-keyring debian-archive-keyring apt-transport-https curl -y
curl -1sLf "https://dl.cloudsmith.io/public/caddy/stable/gpg.key" | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf "https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt" | tee /etc/apt/sources.list.d/caddy-stable.list
apt update -y
apt install caddy -y
```
The Conduit tutorial mentions making a particular directory for
the Caddy config but that didn't work for me. Instead, do this:
```sh
nano /etc/caddy/Caddyfile
```
Obviously you'll swap my domains for yours.
```
matrix.webb.page, matrix.webb.page:8448 {
reverse_proxy /_matrix/* 127.0.0.1:6167
}
```
Reload Caddy and enable Conduit!
```sh
service caddy reload
systemctl start conduit
systemctl enable conduit
```
To ensure your Matrix server works, run these locally (not on your
server). Oh, and if you don't have `jq`[7] installed…why not? Just
remove "| jq" to get raw JSON (jq is a pretty formatter).
```sh
curl https://matrix.webb.page/_matrix/client/versions | jq
# if using port 8448
curl https://matrix.webb.page:8448/_matrix/client/versions | jq
```
Your response should look like this:
```json
{
"versions": [
"r0.5.0",
"r0.6.0",
"v1.1",
"v1.2",
"v1.3",
"v1.4",
"v1.5"
],
"unstable_features": {
"org.matrix.e2e_cross_signing": true,
"org.matrix.msc3916.stable": true
}
}
```
2. Install Element
Getting Elememt installed[8] is quite simple.
```sh
apt install -y wget apt-transport-https
wget -O /usr/share/keyrings/element-io-archive-keyring.gpg https://packages.element.io/debian/element-io-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/element-io-archive-keyring.gpg] https://packages.element.io/debian/ default main" | sudo tee /etc/apt/sources.list.d/element-io.list
apt update -y
apt install -y element-web
nano /etc/element-web/config.json
```
Here is the relevant portion that I changed in my Element config:
```json
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.webb.page",
"server_name": "webb.page"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
```
You're gonna add something new to your Caddyfile as well:
```sh
nano /etc/caddy/Caddyfile
```
```
# again, swap my domain for yours
element.webb.page {
file_server
root * /usr/share/element-web
}
```
You made another change so refresh Caddy.
```sh
service caddy reload
```
FIN
That should be it! I hope I didn't leave anything out and if I
did, you know where to find and correct me. Hope this helps!
🕸️
EDIT: Made my file upload limit 200MB because 100MB wasn't enough.
Also learned that you need to close and re‑open your Element
client so it syncs the new limit. You'd think
`service conduit restart` would actually restart but it seems to
hang for me…or maybe I'm just impatient so I end up rebooting
my server.
References
[1] <https://element.io/pricing>
[2] <https://www.swisstransfer.com>
[3] <https://conduit.rs>
[4] <https://ems-docs.element.io/books/element-server-suite-documentation-lts-2310/page/setting-up-sliding-sync>
[5] <https://docs.conduit.rs/deploying/generic.html#installing-conduit>
[6] <https://gist.github.com/NetOpWibby/4b8c4729b18171a1c3d322837835cf68>
[7] <https://formulae.brew.sh/formula/jq>
[8] <https://github.com/element-hq/element-web/blob/develop/docs/install.md>
|