synapse post
This commit is contained in:
@@ -0,0 +1,315 @@
|
||||
---
|
||||
layout: post
|
||||
author: Sam Hadow
|
||||
tags: messaging podman sysadmin
|
||||
---
|
||||
|
||||
In this blog post I'll describe how to self host a [matrix.org](https://matrix.org/) instance using podman. The homeserver used will be synapse.
|
||||
|
||||
# What are matrix.org and synapse?
|
||||
|
||||
First a short introduction:
|
||||
matrix.org is an open source, secure and decentralized communication protocol. Secure because it defines how end to end encryption should be implemented in the clients.
|
||||
With matrix.org you have [homeservers](https://matrix.org/ecosystem/servers/) and [clients](https://matrix.org/ecosystem/clients/). Homeservers are what the clients connect to and can federate with each other *(meaning someone with an account on homeserver A can talk to someone with an account on homeserver B)*.
|
||||
[Bridges](https://matrix.org/ecosystem/bridges/) to other messaging services can also be hosted alongside a homeserver. Hosting your own homeserver allows you to host the bridges you want.
|
||||
In this blog post I explain how to self host a specific homeserver, which is maintained by the matrix.org foundation: synapse.
|
||||
|
||||
# self hosting synapse
|
||||
|
||||
## initial setup
|
||||
|
||||
### creating secret and directories
|
||||
|
||||
Create the database secret not to expose it in your configuration files:
|
||||
|
||||
```bash
|
||||
echo -n "<postgres-pass>" > /tmp/secret
|
||||
podman secret create synapse_postgres_pass /tmp/secret
|
||||
```
|
||||
|
||||
Adapt the path to your own path for the directories:
|
||||
|
||||
```bash
|
||||
mkdir -p /home/data/podman/synapse/{db,config,media,logs}
|
||||
```
|
||||
|
||||
### generating the configuration file
|
||||
|
||||
*(adapt your-domain to your own, for example: example.org)*
|
||||
|
||||
```bash
|
||||
podman pod create --name synapse -p 8008:8008 -m=2048m
|
||||
|
||||
podman run -it --rm \
|
||||
-v /home/data/podman/synapse/config:/data:Z \
|
||||
-e SYNAPSE_SERVER_NAME=<your-domain> \
|
||||
-e SYNAPSE_REPORT_STATS=no \
|
||||
docker.io/matrixdotorg/synapse:latest generate
|
||||
```
|
||||
|
||||
### modifying the configuration file
|
||||
|
||||
The previous command will generate a homeserver.yaml file. You'll have to modify this file before using synapse. You'll have to modify at least the following parts:
|
||||
|
||||
+ modify the database part *(replace the password)*
|
||||
```yaml
|
||||
database:
|
||||
name: psycopg2
|
||||
txn_limit: 10000
|
||||
args:
|
||||
user: synapse
|
||||
password: <POSTGRES_PASSWORD>
|
||||
dbname: synapse
|
||||
host: 127.0.0.1
|
||||
port: 5432
|
||||
cp_min: 5
|
||||
cp_max: 10
|
||||
```
|
||||
+ set `enable_registration` to false unless you want users to register freely on your instance.
|
||||
+ set a shared secret file with `registration_shared_secret_path` to have access to an [API](https://element-hq.github.io/synapse/latest/admin_api/register_api.html) to create users. Be sure to use a secure secret as anyone having this secret can register on your instance as an admin. Also keep in mind the path is relative to the container, not the host.
|
||||
|
||||
|
||||
### reverse proxy
|
||||
|
||||
In this guide the port used is 8008, we'll use nginx to server the synapse homeserver on the port 443.
|
||||
*(adapt your-domain to your own)*
|
||||
This part is important for users to have the name user@your-domain while hosting synapse on a subdomain. And it's also important for clients and other homeserver to recognize your server.
|
||||
|
||||
in sites-available:
|
||||
|
||||
```nginx
|
||||
# synapse.conf
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name synapse.<your-domain>;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/<your-domain>/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/<your-domain>/privkey.pem;
|
||||
|
||||
location /.well-known/matrix/server {
|
||||
return 200 '{"m.server": "synapse.<your-domain>:443"}';
|
||||
add_header Content-Type application/json;
|
||||
}
|
||||
location /.well-known/matrix/client {
|
||||
return 200 '{"m.homeserver": {"base_url": "https://synapse.<your-domain>"},"m.identity_server": {"base_url": "https://vector.im"}}';
|
||||
add_header Content-Type application/json;
|
||||
add_header "Access-Control-Allow-Origin" *;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8008;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
# Nginx by default only allows file uploads up to 1M in size
|
||||
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
|
||||
client_max_body_size 256M;
|
||||
|
||||
# Synapse responses may be chunked, which is an HTTP/1.1 feature.
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
}
|
||||
```
|
||||
|
||||
In your http.conf add this snippet in the https server block:
|
||||
|
||||
```nginx
|
||||
location /.well-known/matrix/server {
|
||||
return 200 '{"m.server": "synapse.<your-domain>:443"}';
|
||||
add_header Content-Type application/json;
|
||||
add_header "Access-Control-Allow-Origin" *;
|
||||
}
|
||||
|
||||
location /.well-known/matrix/client {
|
||||
return 200 '{"m.homeserver": {"base_url": "https://synapse.<your-domain>"},"m.identity_server": {"base_url": "https://vector.im"}}';
|
||||
add_header Content-Type application/json;
|
||||
add_header "Access-Control-Allow-Origin" *;
|
||||
}
|
||||
```
|
||||
|
||||
## running the pod
|
||||
|
||||
### with podman command line
|
||||
|
||||
Again adapt the path:
|
||||
*The database version can be different but it needs to be pinned to a specific version to avoid issues with updates. You'll have to manually update this container.*
|
||||
|
||||
```bash
|
||||
podman run -d --pod=synapse \
|
||||
--secret synapse_postgres_pass,type=env,target=POSTGRES_PASSWORD \
|
||||
-e POSTGRES_DB="synapse" \
|
||||
-e POSTGRES_USER="synapse" \
|
||||
-e POSTGRES_INITDB_ARGS="--encoding=UTF-8 --lc-collate=C --lc-ctype=C" \
|
||||
-v /home/data/podman/synapse/db:/var/lib/postgresql/data:Z \
|
||||
--name=synapse-db \
|
||||
docker.io/library/postgres:16
|
||||
|
||||
podman run -d --pod=synapse \
|
||||
-e SYNAPSE_CONFIG_PATH=/data/homeserver.yaml \
|
||||
-v /home/data/podman/synapse/config:/data:Z \
|
||||
-v /home/data/podman/synapse/media:/data/media:z \
|
||||
-v /home/data/podman/synapse/logs:/data/logs:Z \
|
||||
--name=synapse-app \
|
||||
--label io.containers.autoupdate=registry docker.io/matrixdotorg/synapse:latest
|
||||
```
|
||||
|
||||
Then you can generate the systemd services:
|
||||
|
||||
```bash
|
||||
cd ~/.config/systemd/user/
|
||||
podman generate systemd --restart-policy=on-failure --files --new --name synapse
|
||||
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now pod-synapse.service
|
||||
```
|
||||
|
||||
### with systemd services directly
|
||||
|
||||
Create these files in `~/.config/systemd/user/`.
|
||||
|
||||
```ini
|
||||
# pod-synapse.service
|
||||
|
||||
[Unit]
|
||||
Description=Podman pod-synapse.service
|
||||
Documentation=man:podman-generate-systemd(1)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
RequiresMountsFor=/run/user/1000/containers
|
||||
Wants=container-synapse-app.service container-synapse-db.service
|
||||
Before=container-synapse-app.service container-synapse-db.service
|
||||
|
||||
[Service]
|
||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=70
|
||||
ExecStartPre=/usr/bin/podman pod create \
|
||||
--infra-conmon-pidfile %t/pod-synapse.pid \
|
||||
--pod-id-file %t/pod-synapse.pod-id \
|
||||
--exit-policy=stop \
|
||||
--name synapse \
|
||||
-p 8008:8008 \
|
||||
-m=2048m \
|
||||
--replace
|
||||
ExecStart=/usr/bin/podman pod start \
|
||||
--pod-id-file %t/pod-synapse.pod-id
|
||||
ExecStop=/usr/bin/podman pod stop \
|
||||
--ignore \
|
||||
--pod-id-file %t/pod-synapse.pod-id \
|
||||
-t 10
|
||||
ExecStopPost=/usr/bin/podman pod rm \
|
||||
--ignore \
|
||||
-f \
|
||||
--pod-id-file %t/pod-synapse.pod-id
|
||||
PIDFile=%t/pod-synapse.pid
|
||||
Type=forking
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
```ini
|
||||
# container-synapse-db.service
|
||||
[Unit]
|
||||
Description=Podman container-synapse-db.service
|
||||
Documentation=man:podman-generate-systemd(1)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
RequiresMountsFor=%t/containers
|
||||
BindsTo=pod-synapse.service
|
||||
After=pod-synapse.service
|
||||
|
||||
[Service]
|
||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=70
|
||||
ExecStart=/usr/bin/podman run \
|
||||
--cidfile=%t/%n.ctr-id \
|
||||
--cgroups=no-conmon \
|
||||
--rm \
|
||||
--pod-id-file %t/pod-synapse.pod-id \
|
||||
--sdnotify=conmon \
|
||||
--replace \
|
||||
-d \
|
||||
--secret synapse_postgres_pass,type=env,target=POSTGRES_PASSWORD \
|
||||
-e POSTGRES_DB=synapse \
|
||||
-e POSTGRES_USER=synapse \
|
||||
-e "POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C" \
|
||||
-v /home/data/podman/synapse/db:/var/lib/postgresql/data:Z \
|
||||
--name=synapse-db \
|
||||
docker.io/library/postgres:16
|
||||
ExecStop=/usr/bin/podman stop \
|
||||
--ignore -t 10 \
|
||||
--cidfile=%t/%n.ctr-id
|
||||
ExecStopPost=/usr/bin/podman rm \
|
||||
-f \
|
||||
--ignore -t 10 \
|
||||
--cidfile=%t/%n.ctr-id
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
```ini
|
||||
# container-synapse-app.service
|
||||
|
||||
[Unit]
|
||||
Description=Podman container-synapse-app.service
|
||||
Documentation=man:podman-generate-systemd(1)
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
RequiresMountsFor=%t/containers
|
||||
BindsTo=pod-synapse.service
|
||||
After=pod-synapse.service
|
||||
|
||||
[Service]
|
||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=70
|
||||
ExecStart=/usr/bin/podman run \
|
||||
--cidfile=%t/%n.ctr-id \
|
||||
--cgroups=no-conmon \
|
||||
--rm \
|
||||
--pod-id-file %t/pod-synapse.pod-id \
|
||||
--sdnotify=conmon \
|
||||
--replace \
|
||||
-d \
|
||||
-e SYNAPSE_CONFIG_PATH=/data/homeserver.yaml \
|
||||
-v /home/data/podman/synapse/config:/data:Z \
|
||||
-v /home/data/podman/synapse/media:/data/media:z \
|
||||
-v /home/data/podman/synapse/logs:/data/logs:Z \
|
||||
--name=synapse-app \
|
||||
--label io.containers.autoupdate=registry docker.io/matrixdotorg/synapse:latest
|
||||
ExecStop=/usr/bin/podman stop \
|
||||
--ignore -t 10 \
|
||||
--cidfile=%t/%n.ctr-id
|
||||
ExecStopPost=/usr/bin/podman rm \
|
||||
-f \
|
||||
--ignore -t 10 \
|
||||
--cidfile=%t/%n.ctr-id
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
|
||||
## managing the homeserver
|
||||
|
||||
### registering users
|
||||
|
||||
With access to the server, creating the user interactively:
|
||||
|
||||
```bash
|
||||
podman exec -it synapse-app /bin/sh
|
||||
register_new_matrix_user --user <username> --config /data/homeserver.yaml
|
||||
```
|
||||
|
||||
Or with the registration API, you can use [this script](https://git.hadow.fr/sam.hadow/Useful-scripts/src/branch/main/create_matrix_account.sh).
|
||||
Reference in New Issue
Block a user