Category: Matrix

  • Set up sliding sync for Matrix self-hosted instances

    As I am working on a brand new Discord-styled modern Matrix client, I went into an issue: because I use the newest Matrix Rust SDK, it requires Sliding Sync (as does the new Element X app).

    Now, the original article includes guides on setting up a separate sliding sync proxy. But, since the newest Matrix Synapse already support native sliding sync. I am just going to give you my docker compose file and my Nginx file:

    Docker compose file

    services:
      app:
        image: dotwee/matrix-synapse-s3
        restart: always
        ports:
          - 8008:8008
        volumes:
          - /var/docker_data/matrix:/data
        depends_on:
          - postgres
    
      postgres:
        image: postgres:13
        container_name: postgres
        environment:
          POSTGRES_DB: syncv3
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
        volumes:
          - postgres_data:/var/lib/postgresql/data
    
      sliding_sync:
        image: ghcr.io/matrix-org/sliding-sync:latest
        container_name: sliding_sync
        depends_on:
          - postgres
          - app
        ports:
          - "8009:8009"
        environment:
          SYNCV3_SERVER: "http://app:8008"
          SYNCV3_DB: "postgres://postgres:${DATABASE_PASSWORD}@postgres:5432/syncv3?sslmode=disable"
          SYNCV3_SECRET: ${SYNCV3_SECRET}
          SYNCV3_BINDADDR: ":8009"
    
    volumes:
      postgres_data:

    If you already have a docker compose of Matrix Synapse running, run docker compose pull to update all the containers to the latest version.

    Also, generate the .env file for your docker containers

    touch .env
    echo "SYNCV3_SECRET=$(openssl rand -hex 32)" > .env
    echo "DATABASE_PASSWORD=$(openssl rand -hex 32)" >> .env

    If you have installed Synapse using other methods, update according to the documentation.

    Nginx configuration

    (with push service and Matrix instance server):

    server {
    
        root /var/www/html;
    
        server_name m1rai.net push.mszdev.com chat-web-hook.mszdev.com;
    
        location / {
            index index.html index.htm index.html inde.php;
        }
    
        location ~* ^(\/_matrix\/push) {
            proxy_pass http://localhost:7183;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
        }
    
        location ~* ^(\/_matrix|\/_synapse\/client) {
            # note: do not add a path (even a single /) after the port in `proxy_pass`,
            # otherwise nginx will canonicalise the URI and cause signature verification
            # errors.
            proxy_pass http://localhost: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 50M;
        }
    
        location /.well-known/matrix/client {
            alias /var/www/html/.well-known/matrix/client;
            default_type application/json;
        }
    
        location /.well-known/matrix/server {
            alias /var/www/html/.well-known/matrix/server;
            default_type application/json;
        }
    
        listen 80;
        listen [::]:443 ssl;
        listen 443 ssl;
        ssl_certificate /home/azureuser/chat.crt;
        ssl_certificate_key /home/azureuser/chat.key;
    
    }

    Modify your Matrix .well-known file

    It should look like this, but with all hostname replaced:

    msz@Mszs-MacBook-Pro ~ % curl https://matrix.org/.well-known/matrix/client
    {
        "m.homeserver": {
            "base_url": "https://matrix-client.matrix.org"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        },
        "org.matrix.msc3575.proxy": {
            "url": "https://slidingsync.lab.matrix.org"
        }
    }

    If your sliding sync proxy `org.matrix.msc3575.proxy` runs on the same server, set it to be the same as your `m.homeserver`

    If you’re hosting your website on CloudFlare, you should use a CloudFlare worker to respond the well known file:

    const HOMESERVER_URL = "https://matrix.org";
    const IDENTITY_SERVER_URL = "https://vector.im";
    const FEDERATION_SERVER = "matrix-federation.matrix.org:443";
    const SLIDING_PROXY_URL = "https://slidingsync.lab.matrix.org";
    
    export default {
      async fetch(request, env) {
        const path = new URL(request.url).pathname;
        const headers = new Headers({ "Content-Type": "application/json" });
    
        switch (path) {
          case "/.well-known/matrix/client":
            return new Response(
              JSON.stringify({
                "m.homeserver": {
                  "base_url": HOMESERVER_URL
                },
                "m.identity_server": {
                  "base_url": IDENTITY_SERVER_URL
                },
                "org.matrix.msc3575.proxy": {
                  "url": SLIDING_PROXY_URL
                }
              }, null, 4),
              { headers }
            );
          case "/.well-known/matrix/server":
            return new Response(
              JSON.stringify({
                "m.server": FEDERATION_SERVER
              }, null, 4),
              { headers }
            );
          default:
            return new Response("Invalid request", { headers });
        }
      },
    };

    If you’re using Nginx, you should provide a custom well known file, and write the rule to read all well known requests from your given path.

        location /.well-known/matrix/client {
            alias /var/www/html/.well-known/matrix/client;
            default_type application/json;
        }
    
        location /.well-known/matrix/server {
            alias /var/www/html/.well-known/matrix/server;
            default_type application/json;
        }

    Here is the example content of the client file located at `/var/www/html/.well-known/matrix/client`

    {
        "m.homeserver": {
            "base_url": "https://matrix-client.matrix.org"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        },
        "org.matrix.msc3575.proxy": {
            "url": "https://slidingsync.lab.matrix.org"
        }
    }

    Here is the example content of the server file located at `/var/www/html/.well-known/matrix/server`

    { "m.server": "matrix-federation.matrix.org:443" }

    Don’t forget to apply the updated configuration file:

    systemctl nginx reload

    Cheers!