{"id":468,"date":"2023-07-20T15:15:17","date_gmt":"2023-07-20T13:15:17","guid":{"rendered":"https:\/\/gilbert.busana.lu\/?p=468"},"modified":"2023-07-24T16:24:09","modified_gmt":"2023-07-24T14:24:09","slug":"running-you-own-matrix-synapse-server","status":"publish","type":"post","link":"https:\/\/www.homeserver.lu\/?p=468","title":{"rendered":"Running you own Matrix-Synapse server"},"content":{"rendered":"\n<p>We are setting up a matrix-synapse instance on our homeserver using an Ubuntu 22.04 VM. Most of these instructions were collected from the <a rel=\"noreferrer noopener\" href=\"https:\/\/matrix-org.github.io\/synapse\/develop\/setup\/installation.html\" target=\"_blank\">official documentation on github<\/a>.  We want to have our domain (example.com) responding for our matrix handle (e.g. @john:example.com), not the hostname (matrix.example.com) of the server. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installation of Matrix-synapse<\/h2>\n\n\n\n<p>First install some packages we&#8217;ll need:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>sudo apt install -y lsb-release wget apt-transport-https<\/code><\/pre><\/div>\n\n\n\n<p>Now add the keyrings and the repository for matrix-synapse server:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"matrix-synapse repository\" data-lang=\"Bash\"><code>sudo wget -O \/usr\/share\/keyrings\/matrix-org-archive-keyring.gpg https:\/\/packages.matrix.org\/debian\/matrix-org-archive-keyring.gpg\necho &quot;deb [signed-by=\/usr\/share\/keyrings\/matrix-org-archive-keyring.gpg] https:\/\/packages.matrix.org\/debian\/ $(lsb_release -cs) main&quot; |\n    sudo tee \/etc\/apt\/sources.list.d\/matrix-org.list<\/code><\/pre><\/div>\n\n\n\n<p>Now update your apt repositories:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>sudo apt update<\/code><\/pre><\/div>\n\n\n\n<p>And install matrix-synapse<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>sudo apt install matrix-synapse-py3<\/code><\/pre><\/div>\n\n\n\n<p>When asked for the server name, we enter <em>example.com<\/em> . For further informations on this, consult the first chapter of the installation instructions: <em><a rel=\"noreferrer noopener\" href=\"https:\/\/matrix-org.github.io\/synapse\/develop\/setup\/installation.html\" target=\"_blank\">Choosing your server name<\/a><\/em>. Decide if you want to have homeserver usage statistics and you are done.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up Synapse<\/h2>\n\n\n\n<p><strong>Install PostgreSQL<\/strong><\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>sudo apt install postgresql<\/code><\/pre><\/div>\n\n\n\n<p>Select your geographic area. Done. Install the libpq5 libraries:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"libpq5\" data-lang=\"Bash\"><code>apt install libpq5<\/code><\/pre><\/div>\n\n\n\n<p>To set up the database, you need to be logged in as the postgres user:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"switch user\" data-lang=\"Bash\"><code>sudo -u postgres bash<\/code><\/pre><\/div>\n\n\n\n<p><strong>Create the synapse user<\/strong><\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"Create synapse user\" data-lang=\"Bash\"><code>createuser --pwprompt synapse_user<\/code><\/pre><\/div>\n\n\n\n<p>Create a safe password and note it down. Create the database:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"Create DB\" data-lang=\"Bash\"><code>createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse<\/code><\/pre><\/div>\n\n\n\n<p>Let&#8217;s enable password authentication so that synapse_user can connect to the database:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>cd \/etc\/postgresql\/14\/main\nnano pg_hba.conf<\/code><\/pre><\/div>\n\n\n\n<p>Add the (last) line for the synapse_user as follows to the <em>pg_hba.conf<\/em> file. As we use local, you do not need to provide an address (leave the fourth column empty). Save and exit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local   replication   all                                peer\nhost    replication   all        127.0.0.1\/32            scram-sha-256\nhost    replication   all        ::1\/128                 scram-sha-256\nlocal   synapse       synapse_user                       scram-sha-256<\/code><\/pre>\n\n\n\n<p>Exit the shell for postgres user and fall back to your standard user:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>exit<\/code><\/pre><\/div>\n\n\n\n<p><strong>Configure synapse to use postgreSQL<\/strong><\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"Edit Synapse config file\" data-lang=\"Bash\"><code>cd \/etc\/matrix-synapse\nnano homeserver.yaml<\/code><\/pre><\/div>\n\n\n\n<p>Modify the database parameters in <em>homeserver.yaml <\/em>to match the following, save and exit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>database:\n  name: psycopg2\n  args:\n    user: synapse_user\n    password: &lt;password&gt;\n    database: synapse\n    host: localhost\n    cp_min: 5\n    cp_max: 10<\/code><\/pre>\n\n\n\n<p>Make sure that postgreSQL starts on boot. Open the postgres.conf file:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"Edit postgresql.conf\" data-lang=\"Bash\"><code>cd \/etc\/postgresql\/14\/main\nnano postgresql.conf<\/code><\/pre><\/div>\n\n\n\n<p>Under <em>Connection Settings<\/em>, uncomment (delete the hash sign) the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#listen_addresses = 'localhost' <\/code><\/pre>\n\n\n\n<p>Save, exit. Now let&#8217;s restart matrix-synaose and the postgres service.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>systemctl restart postgresql\nsystemctl restart matrix-synapse<\/code><\/pre><\/div>\n\n\n\n<p>For more information or debugging, consult the official <a rel=\"noreferrer noopener\" href=\"https:\/\/matrix-org.github.io\/synapse\/develop\/postgres.html\" target=\"_blank\">documentation<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">TLS certificates and reverse proxy setup<\/h2>\n\n\n\n<p>We assume that you have a functioning Nginx server. We set up two (see first paragraph of this page for the reason) basic reverse proxy configuration files in \/etc\/nginx\/sites-available, one for the matrix server (matrix.example.com) and one for the domain itself (example.com), using the default files provided. Create the <a rel=\"noreferrer noopener\" href=\"https:\/\/gilbert.busana.lu\/?p=186\" target=\"_blank\">SSL certificates<\/a> (do not forget to <a rel=\"noreferrer noopener\" href=\"https:\/\/gilbert.busana.lu\/?p=165\" target=\"_blank\">enable the sites<\/a> first). Do not forget to point the corresponding DNS records to your reverse proxy and allow the firewall to let the incoming connections (port 80 &amp; 443) through.<\/p>\n\n\n\n<p>The <em>matrix.example.com<\/em> sites configuration file should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n\n    listen 443 ssl http2;\n    listen &#91;::]:443 ssl http2;\n\n    ssl_certificate \/etc\/letsencrypt\/live\/matrix.example.com\/fullchain.pem; # managed by Certbot\n    ssl_certificate_key \/etc\/letsencrypt\/live\/matrix.exmaple.com\/privkey.pem; # managed by Certbot\n    include \/etc\/letsencrypt\/options-ssl-nginx.conf; # managed by Certbot\n    ssl_dhparam \/etc\/letsencrypt\/ssl-dhparams.pem; # managed by Certbot\n\n\n    server_name matrix.example.com;\n    access_log \/var\/log\/nginx\/matrix.example.com.access.log;\n    error_log \/var\/log\/nginx\/matrix.example.com.error.log;\n\n   location ~ ^(\/|\/_matrix|\/_synapse\/client) {\n        # note: do not add a path (even a single \/) after the port in `proxy_pass`,\n        # otherwise nginx will canonicalise the URI and cause signature verification\n        # errors.\n        proxy_pass http:\/\/&lt;IP OF SYNAPSE SERVER&gt;:8008;\n        proxy_set_header X-Forwarded-For $remote_addr;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header Host $host;\n\n        # Nginx by default only allows file uploads up to 1M in size\n        # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml\n        client_max_body_size 50M;\n\n    # Synapse responses may be chunked, which is an HTTP\/1.1 feature.\n    proxy_http_version 1.1;\n    }\n\n}\n\n\nserver {\n    if ($host = matrix.example.com) {\n        return 301 https:\/\/$host$request_uri;\n    } # managed by Certbot\n\n    listen 80;\n\n    server_name matrix.example.com;\n    return 404; # managed by Certbot\n\n}<\/code><\/pre>\n\n\n\n<p>The<em> example.com<\/em> sites configuration file should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n\n    server_name example.com;\n    access_log \/var\/log\/nginx\/example.com.access.log;\n    error_log \/var\/log\/nginx\/example.com.error.log;\n\n    listen 443 ssl; # managed by Certbot\n    ssl_certificate \/etc\/letsencrypt\/live\/example.com\/fullchain.pem; # managed by Certbot\n    ssl_certificate_key \/etc\/letsencrypt\/live\/example.com\/privkey.pem; # managed by Certbot\n    include \/etc\/letsencrypt\/options-ssl-nginx.conf; # managed by Certbot\n    ssl_dhparam \/etc\/letsencrypt\/ssl-dhparams.pem; # managed by Certbot\n\n# the root folder should redirect to your regular website under your domain name (if needed)\nlocation \/ {\n\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_headers_hash_max_size 512;\n        proxy_headers_hash_bucket_size 128;\n        proxy_pass http:\/\/&lt;WEBSERVER&gt;;\n        include proxy_params;\n     }\n\nlocation \/.well-known\/matrix\/client {\n    return 200 '{\"m.server\": \"matrix.example.com:443\"}';\n    default_type application\/json;\n    add_header Access-Control-Allow-Origin *;\n}\n\nlocation \/.well-known\/matrix\/server {\n    return 200 '{\"m.server\": \"matrix.example.com:443\"}';\n    default_type application\/json;\n    add_header Access-Control-Allow-Origin *;\n}\n}\n\n\nserver {\n    if ($host = example.com) {\n        return 301 https:\/\/$host$request_uri;\n    } # managed by Certbot\n\n\n    listen 80;\n\n    server_name example.com;\n    return 404; # managed by Certbot\n\n\n}<\/code><\/pre>\n\n\n\n<p>When configuring your client, use the <em>matrix.example.com<\/em> URL. The <em>.well-known<\/em> json message is used by other matrix servers that want to connect to your server. They will be informed that they should use a different hostname than the one provided by the user&#8217;s handles. More information is available in the official <a rel=\"noreferrer noopener\" href=\"https:\/\/matrix-org.github.io\/synapse\/develop\/delegate.html\" target=\"_blank\">delegation<\/a> documentation.<\/p>\n\n\n\n<p>The official documentation states that port 8448 should be open for federation and also listened to by the reverse proxy, but our configuration works fine without it. Maybe the other matrix servers also try port 443 if 8448 is not available?<\/p>\n\n\n\n<p>If your reverse proxy is running on a different machine than the synapse server, than you have to adjust the <em>listeners bind_addresses<\/em> in the <em>\/etc\/matrix-synapse\/homeserver.yaml<\/em> to the following. Do not forget to restart the matrix service after saving the changes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>bind_addresses: &#91;'::1', '0.0.0.0']<\/code><\/pre>\n\n\n\n<p>Test delegation \/ federation using the <a rel=\"noreferrer noopener\" href=\"https:\/\/federationtester.matrix.org\" target=\"_blank\">Matrix Federation Tester<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Adding a Matrix user<\/h2>\n\n\n\n<p>In order to be able to add users, you need to define the <em>registration shared secret<\/em> in the <em>\/etc\/matrix-synapse\/homeserver.yaml<\/em> file. Add the following line at the end, generating some random salt. Restart the matrix service afterwards.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>registration_shared_secret: YOURRANDOMSALTSTRING<\/code><\/pre>\n\n\n\n<p>Now add a user, using the following command:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-file=\"Matrix user creation\" data-lang=\"Bash\"><code>register_new_matrix_user -u john -c \/etc\/matrix-synapse\/homeserver.yaml -a https:\/\/matrix.example.com<\/code><\/pre><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>-u, --user<\/strong>\nLocal part of the new user. Will prompt if omitted.\n<strong>-p, --password<\/strong>\nNew password for user. Will prompt if omitted. Supplying the password on the command line is not recommended. Use the STDIN instead.\n<strong>-a, --admin<\/strong>\nRegister new user as an admin. Will prompt if omitted.\n<strong>-c, --config<\/strong>\nPath to server config file containing the shared secret.\n<strong>-k, --shared-secret<\/strong>\nShared secret as defined in server config file. This is an optional parameter as it can be also supplied via the YAML file.\n<strong>server_url<\/strong>\nURL of the home server. Defaults to \u00b4https:\/\/localhost:8448\u00b4.<\/code><\/pre>\n\n\n\n<p>Use a matrix client (e.g.<a href=\" https:\/\/app.element.io\"> https:\/\/app.element.io<\/a>) to test your server and user. Have fun!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are setting up a matrix-synapse instance on our homeserver using an Ubuntu 22.04 VM. Most of these instructions were collected from the official documentation on github. We want to have our domain (example.com) responding for our matrix handle (e.g. @john:example.com), not the hostname (matrix.example.com) of the server. Installation of Matrix-synapse First install some packages [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[31,20],"tags":[29],"class_list":["post-468","post","type-post","status-publish","format-standard","hentry","category-fediverse","category-webapps","tag-fediverse"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=\/wp\/v2\/posts\/468","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=468"}],"version-history":[{"count":55,"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=\/wp\/v2\/posts\/468\/revisions"}],"predecessor-version":[{"id":528,"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=\/wp\/v2\/posts\/468\/revisions\/528"}],"wp:attachment":[{"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=468"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=468"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.homeserver.lu\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=468"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}