From f5cfa6f6eeb4e0fda89955466982753872ad88d9 Mon Sep 17 00:00:00 2001 From: Ari Archer Date: Wed, 27 Dec 2023 06:56:54 +0200 Subject: [PATCH] update @ Wed 27 Dec 06:56:54 EET 2023 Signed-off-by: Ari Archer --- blog.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog.json b/blog.json index 9ce6968..32e96c5 100644 --- a/blog.json +++ b/blog.json @@ -131,7 +131,7 @@ "set-up-matrix-server-dendrite-linux-nginx": { "title": "how to set up a matrix server with dendrite, linux and nginx", "description": "tutorial walking through setting up dendrite matrix homeserver with nginx ( together with certbot ) on linux ( in this case, specifically debian 12, but works everywhere ), also covers very annoying errors i've encountered making my own matrix homeserver -- matrix.ari.lt / ari.lt", - "content": "hello\n\nrecently i've set up a [matrix server](https://blog.ari.lt/b/ariweb-matrix-homeserver/)\nand i went through a lot of pain, so i'm here to document issues\ni've faced and hopefully i can help more people set up their homeservers\nquicker and with less issues\n\nalso, before we start, i want to clarify that all commands that start with `#`\nmust be ran as the root user ( for example through `sudo` or `su` ), and `$`\nshould be ran as normal user ( for example `matrix` or `user` or something ),\nunless stated otherwise\n\n## setup\n\n- [debian](https://debian.org/) 12\n- [contabo VPS](https://contabo.com/en/vps/) S SSD\n - 8 gb RAM\n - 4 cores\n - 200 gb SSD\n - 200 Mbit/s network speed\n- [dendrite](https://github.com/matrix-org/dendrite) implementation of the [matrix protocol](https://spec.matrix.org/latest/)\n- [golang](https://go.dev/) `1.20.0` and up\n\ni wouldn't suggest going below the contabo VPS S SSD hardware-level because it may\nget slow and painful, especially when joining bigger rooms, i'd even suggest going\nwith contabo VPS M SSD, which is why i'll upgrade soon\n\n## delegation of the main domain\n\ni assume you won't be running your website ( say like ) on the same\nserver you run your matrix server, in my case, i actually even couldn't because of how\nmy website is hosted on netlify and ye, but regardless, i'd very much suggest running\nmatrix ( dendrite )\n\ni personally went for the [.well-known delegation](https://matrix-org.github.io/synapse/latest/delegate.html#well-known-delegation) method, but you can go for anything you like as there's multiple methods\n\nhere's how my .well-known stuff looks :\n\n`.well-known/matrix/client` :\n\n {\n \"m.homeserver\": {\n \"base_url\": \"https://matrix.ari.lt\"\n }\n }\n\n`.well-known/matrix/server` :\n\n {\n \"m.server\": \"matrix.ari.lt:443\"\n }\n\nas seen at , they also don't have to be pretty-printed, i don't\nknow why i made them pretty, but it's fine\n\nfew key notes :\n\n- do not forget the port in `.well-known/matrix/server`, it is not implicit,\n i don't remember the default port, but prefer to be explicit\n- the files must point to your matrix server ( where dendrite will be hosted )\n- make sure that the files return `Content-Type` header as JSON, aka `application/json`\n- make sure CORS is set up correctly\n - `Access-Control-Allow-Origin` = `*`\n - `Access-Control-Allow-Methods` = `GET`\n\nthis is the easy part\n\n## golang\n\nbefore anything, we will need to install golang, on debian you can do `apt install go-golang`, but that\nmay install an old version of go, which isn't desirable, here's how i did it :\n\n- went to \n- downloaded the latest package for linux ( in my case )\n- followed the [go installation instructions from package](https://go.dev/doc/install)\n\nthis gave me the latest go language compiler, which we will use to compile dendrite as it's\nwritten in go\n\n## installing other dependencies\n\nother dependencies are defined in , but\nat the moment they're :\n\n- go ( already covered in <#:golang> )\n- postgresql database\n- built-in [NATS server](https://github.com/nats-io/nats-server) ( we don't need to do anything here, dendrite comes with one )\n- reverse proxy, such as [nginx](https://nginx.org/), which we will use in this case\n\nand for SSL stuff we will also add `certbot` to our dependencies so we could have a\nsecure SSL connection\n\nto install them, you can run the following :\n\n # apt install postgresql postgresql-client nginx certbot python3-certbot-nginx\n\n- `postgresql` and `postgresql-client` for postgresql dependency and interface\n- `nginx` as our reverse proxy\n- `certbot` and `python3-certbot-nginx` for SSL things\n\n## preparing database\n\npreparing the database is fairly easy as per\n[the matrix dendrite database setup](https://matrix-org.github.io/dendrite/installation/manual/database)\n\nfirstly, you need to start and enable the postgresql service :\n\n # systemctl enable --now postgresql\n\nnext, run the following to switch to postgresql control user :\n\n # su postgres\n $ cd\n\nnow you should be in the postgres user's home dir, now you will\nhave to create the role for dendrite, set its password and create\nits database, but before, i have to warn you to create a password\nsuch as it shouldn't include non-url-safe characters, else it may\nbe a pain to configure dendrite in the future, this is why i'd recommend\nyou just generate the password using the following command :\n\n $ head -n 16 /dev/urandom | base64 -w 0 | shuf | sed 's/[^A-Za-z0-9]//g' | head -c 123\n\nand then using these commands to create the role, set its password and create the database :\n\n $ createuser -P dendrite\n $ createdb -O dendrite -E UTF-8 dendrite\n\nnow you're all set with the database\n\n## compiling dendrite\n\nfirstly, let's set up the user we'll run dendrite on, it is a good practice\nto run applications such as this under lowest possible privileges so we don't\nrun into nasty attacks in the future, here's how you do it :\n\nrun the following command\n\n # useradd -m matrix\n\nthis will create a new user called `matrix` with its own `/home/matrix/` directory,\nwe will run dendrite under this user,, next -- set the password for the user :\n\n # passwd matrix\n\nmake sure to use a secure password, may i recommend [pwdtools](https://ari.lt/gh/pwdtools) ? though you can use anything\n\nyou may also want to run this to make the home directory of this user only readable by that user :\n\n $ chmod 700 -R /home/matrix/\n\nbut it's optional\n\nthen, switch to the matrix user, you can use any user to do this :\n\n $ su matrix\n\nnow as you're the `matrix` user, you should go into your `~` ( home )\ndirectory :\n\n $ cd\n\nnow as you're the matrix user in its home direcotory,\ndownload the latest release tarball ( `.tar.gz` )\noff and extract it\n\nat the moment for me it's\n\nso i'll assume the same, although for future readers --\n**please grab the latest version**, here's an example of how to download it and\nextract it :\n\n $ curl -fLO https://github.com/matrix-org/dendrite/archive/refs/tags/v0.13.5.tar.gz\n $ tar xvf v0.13.5.tar.gz\n $ cd dendrite-0.13.5/\n\nnow you should end up in the latest release of dendrite\n\naccording to \nyou should now run the following :\n\n $ go build -o bin/ ./cmd/...\n\nkeep in mind it's LITERALLY `go build -o bin/ ./cmd/...`\nand not for example `go build -o bin/ ./cmd/*`, it's a literal\nelipsis, run the command as-is with the 3 dots as go is weird\nand quirky like that i guess\n\nthis should build dendrite, keep in mind this will be network\nand resource heavy\n\nnow you can install it :\n\n $ go install ./cmd/dendrite\n\nand your dendrite installation should end up in `~/go/bin/dendrite` :)\n\n## signing keys\n\nnow, you will generate signing keys for your matrix encryption, which will be used\nin authentication of federation requests\n[as explained here, the tutorial for setting up keys in dendrite](https://matrix-org.github.io/dendrite/installation/manual/signingkeys)\n\nrun the following command in the dendrite directory ( the one you ran commands in <#:compiling dendrite> ) :\n\n $ ./bin/generate-keys --private-key matrix_key.pem\n\n**never share this key with anyone**\n\n## configuring dendrite\n\nthis part is based off [my own config of dendrite](https://ari.lt/lh/matrix.ari.lt), which\nis set up by help of people, my own research and [the setup docs](https://matrix-org.github.io/dendrite/installation/manual/configuration),\nkeep up-to-date with my configuration and the docs as this section\nmay get outdated, although i'll do my best to keep this up to date\nas long as i run the ari-web matrix server\n\nfirstly copy the example config :\n\n $ cp dendrite-sample.yaml dendrite.yaml\n\nand now, open it in your favourite text editor, such as `vim` for example, maybe `nano` even :\n\n $ vim dendrite.yaml\n\nnow, i will cover only some parts of the config which you may want to change,\nbut also the default config includes a lot of comments, so you may want to\nlook through all of it and see what you want or don't\n\n`global` :\n\n- `server_name` -- this should be the domain you are delegating from, for example `ari.lt`\n has the `.well-known` delegation to `matrix.ari.lt` so the value of `server_name` will be `ari.lt`\n- `database.connection_string` -- this is the connection string of your postgresql database,\n this should be a url as follows : `postgresql://dendrite:@127.0.0.1/dendrite`, replace ``\n with your password, for example `postgresql://dendrite:password123@127.0.0.1/dendrite`\n- `well_known_server_name` and `well_known_client_name` -- these two keys should have\n the same value of `https://:443`, for example `https://matrix.ari.lt:443`, the\n domain must be the same as your matrix server, not delegated domain ( so `matrix.ari.lt` and not `ari.lt` )\n- make sure `disable_federation` is set to `false`\n- `presence.*` -- set all keys that are `false` to `true`, if you want presence to be a thing\n ( such as typing, online status, etc ), this is optional\n\n`client_api` :\n\n- i'd suggest setting `registration_disabled` and `guests_disabled` to `true` so you'd have full\n control over what people have accounts, if you want open registrations you may want to set both\n of them to `false` or just `registration_disabled` to `false`, depending on your wants, you will\n be able to create new accounts using `./bin/create-account` later on regardless\n- if you disabled registrations, you'll need to set `registration_shared_secret` to some value,\n you can use the password generator command from before -- `head -n 16 /dev/urandom | base64 -w 0 | shuf | sed 's/[^A-Za-z0-9]//g' | head -c 123`\n to generate something good enough\n- you may also want to set `rate_limiting.exempt_user_ids` to yourself ( like `@ari:ari.lt` as an example ),\n maybe even change the rate limiting in general\n\n`sync_api` :\n\n- set the `real_ip_header` to `X-Real-IP`, we will use this in the future\n- if you want search functionality, you may want to set `search.enable` to `true`\n\n`user_api` :\n\n- if you'll have / already have a main / lounge room, you may want to add it to `auto_join_rooms`, like `#root:ari.lt` for example\n\nthat's pretty much it with the configuration of dendrite, although i'd still suggest going through all config options\nat least once and thinking if you want them or not :)\n\n## running dendrite\n\nto run dendrite you can just run\n\n $ ~/go/bin/dendrite -config ./dendrite.yaml\n\nand if you want to run it in the background you just run this :\n\n $ ~/go/bin/dendrite -config ./dendrite.yaml & disown\n\nsimple as that, now dendrite will be listening on port 8008\n\n## dns records\n\nthe `A` record is required\n\n matrix.yourdomain.tld 3600 IN A \n matrix.yourdomain.tld 3600 IN CAA 0 issue \n\nyou may remove `CAA` IF you disable all the fancy SSL stuff in nginx\n\nyou can also optionally add `AAAA`\n\nfor ari-web i've set it up like this :\n\n matrix.ari.lt 3600 IN A 62.171.174.136\n matrix.ari.lt 3600 IN CAA 0 issue letsencrypt.org\n\n## configuring nginx\n\n**tldr** <#:final nginx config>\n\nin our case we will use nginx as our reverse proxy, this i will base off\n[my own nginx config for my vps](https://us.ari.lt/git/blob/main/res/nginx.conf)\n\nfirstly, you need to make sure if either user `www-data` or `http` exists, you can do that\nby running\n\n $ cat /etc/passwd\n\nwhich will show you all users\n\nif none do, run\n\n # useradd www-data # or http\n\nafter that, make sure that `/etc/nginx/mime.types` exists :\n\n $ ls /etc/nginx/mime.types\n\nif not, run the following command :\n\n # curl https://raw.githubusercontent.com/nginx/nginx/master/conf/mime.types -fLo /etc/nginx/mime.types\n\nnow, open up `/etc/nginx/nginx.conf` in your favourite text editor and configure it :\n\n # vim /etc/nginx/nginx.conf\n\nwe will start by setting up some base rules :\n\n user www-data;\n worker_processes auto;\n pid /run/nginx.pid;\n worker_rlimit_nofile 8192;\n\n events {\n use epoll;\n multi_accept on;\n worker_connections 4096;\n }\n\nmake sure to replace `www-data` with `http` if you're using the `http` user instead,\nhere's what this piece of config means :\n\n- `user www-data;` will make sure that the worker processes run under a low privilege user\n such as `www-data`\n- `worker_processes auto;` makes the worker process count optimal for your cpu\n core count, each worker than handle thousands of connections\n- `pid /run/nginx.pid;` specifies the file where the server will write its master process id\n- `worker_rlimit_nofile 8192;` sets the limit of maximum number of file descriptors opened by this process ( every connection is a unix socket, so also a file descriptor )\n- `use epoll;` sets the method to use to get notifications for network events, `epoll` is particularly good for linux\n- `multi_accept on;` allows to handle multiple simultaneous connections\n- `worker_connections 4096;` sets the limit of maximum number of connections per worker\n\nnext, we'll set up some basic config for our server :\n\n http {\n include mime.types;\n default_type application/octet-stream;\n\n access_log off;\n\n tcp_nopush on;\n tcp_nodelay on;\n keepalive_timeout 120;\n types_hash_max_size 2048;\n server_names_hash_bucket_size 256;\n\n sendfile on;\n }\n\nyou can dig into this config deeper, but abstractly :\n\n- `default_type application/octet-stream;` sets the default mime type to `application/octet-stream` ( binary data )\n- `access_log off;` turns off the access log so we don't log requests and their IPs\n- sets up some TCP options\n- sets `types_hash_max_size`, it's the mime type hash table size, this is for different types of mime types for different files as matrix also works on file uploading\n- `server_names_hash_bucket_size 256;` is for server directives, how much memory it's allowed to use\n- `sendfile on;` is for file uploads\n\nnow, we can set up a basic `server` :\n\n http {\n ...\n\n server {\n listen 80;\n listen [::]:80;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n return 301 https://$server_name$request_uri;\n }\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n }\n }\n\nhere you can also now start nginx :\n\n # systemctl enable --now nginx\n\nthis sets up the basic requirements for a server, make sure to\nreplace yourdomain.tld / matrix.yourdomain.tld with whatever your\npreferred domain is, 443 is the https ( tls ) port and 8448 is the secure\nfederation port,, this is where we have to take a step back,\nsave our nginx config and move on for a little bit\n\n### tls ( https )\n\nto set up tls ( https ) on our server now, we will have to run this command :\n\n certbot certonly --nginx\n\nand follow the directions on the screen\n\nnow, as you have that set up, you can continue setting up your proxy, add SSL stuff :\n\n http {\n ...\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n ssl_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/matrix.yourdomain.tld/privkey.pem;\n ssl_trusted_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n\n ssl_stapling on;\n ssl_stapling_verify on;\n ssl_session_timeout 1d;\n ssl_session_cache shared:MozSSL:10m;\n ssl_session_tickets off;\n ssl_protocols TLSv1.2 TLSv1.3;\n ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256';\n ssl_prefer_server_ciphers on;\n }\n }\n\nno, we dont need to touch the `:80` one, that will always stay the same as it'll just redirect to https\n\ni won't explain these options, but basically only two lines of SSL things are required :\n\n ssl_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/matrix.yourdomain.tld/privkey.pem;\n\nother stuff is sanity and security, i won't dig deep into it but basically this enables\n[ssl stapling](https://knowledge.digicert.com/quovadis/ssl-certificates/ssl-general-topics/what-is-ocsp-stapling)\nand also sets up some secure preferred ciphers so we know that secure encryption is happening\nat all times\n\nand now, you are done setting ssl up on nginx\n\n### after ssl ( https )\n\nnow, we add our locations :\n\n http {\n ...\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n ...\n\n location = / {\n access_log off;\n return 301 https://$server_name/_matrix/static/;\n }\n\n location ~ ^(/_matrix|/_synapse/client) {\n access_log off;\n\n proxy_pass http://127.0.0.1:8008;\n\n proxy_http_version 1.1;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n client_max_body_size 512M;\n proxy_max_temp_file_size 0;\n proxy_buffering off;\n }\n }\n }\n\n`location = /` sets up the `/` location of your server, it'll always redirect to\nthe dendrite static page so once you visit `matrix.yourdomain.tld`, it'll always\nredirect to the welcome page, so it doesn't look as boring, although you can just\nremove that, it's optional\n\nnow `location ~ ^(/_matrix|/_synapse/client)` is where the actual federation stuff happens,\nas always we turn off the access log and we pass our requests to our local dendrite instance\nrunning on port `8008` and then set up the following things :\n\n- always set the http version to 1.1\n- set a couple of headers ( such as `X-Real-IP` from before, this is used for multiple things )\n- `client_max_body_size 512M;` states that the accepted body of a client cannot exceed 512 megabytes,\n you can increase or decrease the size, this is only ever an issue in file uploads\n- `proxy_max_temp_file_size 0;` sets the maximum size of a temp file, keeping it `0` disables the\n buffering, which means the content coming FROM the proxy directly to the user, if not this\n breaks downloads in matrix and makes it so they break and only partially deliver something\n- `proxy_buffering off;` this is like `proxy_max_temp_file_size 0` but instead its TO user not FROM user\n\n## final nginx config\n\nafter all this work we end up with a config something like :\n\n user www-data;\n worker_processes auto;\n pid /run/nginx.pid;\n worker_rlimit_nofile 8192;\n\n events {\n use epoll;\n multi_accept on;\n worker_connections 4096;\n }\n\n http {\n include mime.types;\n default_type application/octet-stream;\n\n access_log off;\n\n tcp_nopush on;\n tcp_nodelay on;\n keepalive_timeout 120;\n types_hash_max_size 2048;\n server_names_hash_bucket_size 256;\n\n sendfile on;\n\n server {\n listen 80;\n listen [::]:80;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n return 301 https://$server_name$request_uri;\n }\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n ssl_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/matrix.yourdomain.tld/privkey.pem;\n ssl_trusted_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n\n ssl_stapling on;\n ssl_stapling_verify on;\n ssl_session_timeout 1d;\n ssl_session_cache shared:MozSSL:10m;\n ssl_session_tickets off;\n ssl_protocols TLSv1.2 TLSv1.3;\n ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256';\n ssl_prefer_server_ciphers on;\n\n location = / {\n access_log off;\n return 301 https://$server_name/_matrix/static/;\n }\n\n location ~ ^(/_matrix|/_synapse/client) {\n access_log off;\n\n proxy_pass http://127.0.0.1:8008;\n\n proxy_http_version 1.1;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n client_max_body_size 512M;\n proxy_max_temp_file_size 0;\n proxy_buffering off;\n }\n }\n }\n\nyou can now save the file and quit the editor, also, a tip : avoid gzip compression, it kills performance\nand cpu on your vps, it's painful, stick to vanilla\n\nyou can also add this to `http` block to enable [HSTS preload](https://scotthelme.co.uk/hsts-preloading/)\nwith which you can apply to [hstspreload.org](https://hstspreload.org/) :\n\n http {\n ...\n\n add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains; preload\";\n\n ...\n }\n\n## finalizing\n\nnow, after all this your matrix server is almost done, all you have to do is :\n\nlog into the matrix user :\n\n $ su matrix\n\nchange to its home :\n\n $ cd\n\nkill dendrite :\n\n $ pkill -f dendrite\n\nrestart nginx\n\n # systemctl restart nginx\n\nrestart dendrite :\n\n $ ~/go/bin/dendrite -config ./dendrite.yaml & disown\n\n## sanity check\n\nnow, as everything is up and running, make sure everything's okay by going to\n`matrix.yourdomain.tld`, it should show you the dendrite index page, if it doesn't,\nplease verify everything and make sure everything's okay\n\nif you cannot figure it out, you can come and ask in\n[#root:ari.lt](https://matrix.to/#/#root:ari.lt) or [#dendrite:matrix.org](https://matrix.to/#/#dendrite:matrix.org)\n\n## new user\n\nnow, as everything works, you can log in as the matrix user and create a new account for yourself by\ngoing into the directory which you built dendrite in ( the one with `bin/` directory in it )\nand run this :\n\n $ ./bin/create-account --config dendrite.yaml -username some_username -admin\n\nthis will prompt you for a password, dendrite doesn't seem to like passwords over 72 characters,\nso make sure it fits\n\nyou can also create normal user accounts by doing :\n\n $ ./bin/create-account --config dendrite.yaml -username some_username\n\naka removing the `-admin` argument\n\nnow, you can log in with your [favourite matrix client](https://matrix.org/ecosystem/clients/)\nsuch as for example [schildi](https://schildi.chat/)\nor [element](https://element.io/), have fun\n\n## concluding\n\ni hope i could help at least a little, it took me a while to figure out issues, solve problems,\nfind answers and come up with my own solutions, ask people, debug, etc etc etc\n\na lot of trouble went into this and i hope this popped up in your search engine whenever you're looking\nto solve such issues as :\n\n- how to set up dendrite on nginx properly and securely\n- dendrite matrix implementation on nginx not sending the full file / image ( partial send and then stream close )\n - main config options in <#:final nginx config> to look out for would be\n - `types_hash_max_size 2048;`\n - `server_names_hash_bucket_size 256;`\n - `sendfile on;`\n - `client_max_body_size 512M;`\n - `proxy_max_temp_file_size 0;`\n - `proxy_buffering off;`\n- failing to sync data in ( android ) clients on dendrite matrix instance\n - still unsure why web works, but i think it's related to it not sending full files\n- how to properly delegate a matrix domain\n- why am i getting `M_UNRECOGNIZED` in dendrite matrix server\n - probably because you have forwarding set up badly, make sure to not have just `location /` for example\n- why am i getting request signature errors in dendrite matrix server in nginx\n - also related to the `M_UNRECOGNIZED` problem, make sure to not overgeneralize the location, use `location ~ ^(/_matrix|/_synapse/client)`\n- generally setup errors and issues with setting up dendrite with nginx and ssl\n\n## related error messages\n\n( just in case someone decides to look them up and can't find an answer )\n\n- dendrite matrix implementation on nginx not sending the full file / image ( partial send and then stream close )\n\n```\ncurl: (92) HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)\n```\n\n( from curl )\n\n- failing to sync data in ( android ) clients on dendrite matrix instance\n\n```\n# [WARNING] Syncloop failed: Client has not connection to the server\n# [WARNING] Something went wrong: - Instance of 'SyncConnectionException'\n```\n\n( from fluffychat android )\n\n Initial sync:\n Downloading data...\n\n( from element android and schildichat android )\n\n Loading... Please wait.\n Oops something went wrong...\n\n( from fluffychat android )\n\n INFO[2023-12-26T19:32:19.277303943Z] Starting queue due to pending events or forceWakeup\n\n( from dendrite logs )\n\n time=\"2023-12-26T19:16:03.938083486Z\" level=info msg=\"Starting queue due to pending events or forceWakeup\" func=\"github.com/matrix-org/dendrite/federationapi/queue.(*destinationQueue).wakeQueueIfEventsPending\" file=\"/home/matrix/dendrite/federationapi/queue/destinationqueue.go:158\"\n\n( from dendrite logs )\n\n 2023-12-26T21:42:30*130GMT+00:00Z 171 E/ /Tag: ## Sync: sync service did fail true\n java.net.ProtocolException: unexpected end of stream\n ...\n\n( from fluffychat android data logs )\n\n- how to properly delegate a matrix domain\n\n```\nTesting matrix.ari.lt failed: mismatching server name, tested: matrix.ari.lt, got: ari.lt // Dendrite 0.13.5+9a5a567\n```\n\n( from [@version:envs.net](https://matrix.to/#/@version:envs.net) )\n\n Homeserver URL does not appear to be a valid Matrix homeserver\n\n( from element web )\n\n- why am i getting `M_UNRECOGNIZED` in dendrite matrix server\n\n```\n{\"errcode\":\"M_UNRECOGNIZED\",\"error\":\"Unrecognized request\"}\n```\n\n( from dendrite response )\n\n- why am i getting request signature errors in dendrite matrix server in nginx\n\n```\nINFO[2023-12-26T00:00:08.867552600Z] Invalid request signature error=\"Bad signature from \\\"4d2.org\\\" with ID \\\"ed25519:a_MgDi\\\"\" req.id=... req.method=PUT req.path=\"/\\_matrix/federation/v2/invite/!...:4d2.org/$...\"\n```\n\n( from dendrite logs )\n\ngood luck !", + "content": "hello\n\nrecently i've set up a [matrix server](https://blog.ari.lt/b/ariweb-matrix-homeserver/)\nand i went through a lot of pain, so i'm here to document issues\ni've faced and hopefully i can help more people set up their homeservers\nquicker and with less issues\n\nalso, before we start, i want to clarify that all commands that start with `#`\nmust be ran as the root user ( for example through `sudo` or `su` ), and `$`\nshould be ran as normal user ( for example `matrix` or `user` or something ),\nunless stated otherwise\n\n## setup\n\n- [debian](https://debian.org/) 12\n- [contabo VPS](https://contabo.com/en/vps/) S SSD\n - 8 gb RAM\n - 4 cores\n - 200 gb SSD\n - 200 Mbit/s network speed\n- [dendrite](https://github.com/matrix-org/dendrite) implementation of the [matrix protocol](https://spec.matrix.org/latest/)\n- [golang](https://go.dev/) `1.20.0` and up\n\ni wouldn't suggest going below the contabo VPS S SSD hardware-level because it may\nget slow and painful, especially when joining bigger rooms, i'd even suggest going\nwith contabo VPS M SSD, which is why i'll upgrade soon\n\n## delegation of the main domain\n\ni assume you won't be running your website ( say like ) on the same\nserver you run your matrix server, in my case, i actually even couldn't because of how\nmy website is hosted on netlify and ye, but regardless, i'd very much suggest running\nmatrix ( dendrite )\n\ni personally went for the [.well-known delegation](https://matrix-org.github.io/synapse/latest/delegate.html#well-known-delegation) method, but you can go for anything you like as there's multiple methods\n\nhere's how my .well-known stuff looks :\n\n`.well-known/matrix/client` :\n\n {\n \"m.homeserver\": {\n \"base_url\": \"https://matrix.ari.lt\"\n }\n }\n\n`.well-known/matrix/server` :\n\n {\n \"m.server\": \"matrix.ari.lt:443\"\n }\n\nas seen at , they also don't have to be pretty-printed, i don't\nknow why i made them pretty, but it's fine\n\nfew key notes :\n\n- do not forget the port in `.well-known/matrix/server`, it is not implicit,\n i don't remember the default port, but prefer to be explicit\n- the files must point to your matrix server ( where dendrite will be hosted )\n- make sure that the files return `Content-Type` header as JSON, aka `application/json`\n- make sure CORS is set up correctly\n - `Access-Control-Allow-Origin` = `*`\n - `Access-Control-Allow-Methods` = `GET`\n\nthis is the easy part\n\n## golang\n\nbefore anything, we will need to install golang, on debian you can do `apt install go-golang`, but that\nmay install an old version of go, which isn't desirable, here's how i did it :\n\n- went to \n- downloaded the latest package for linux ( in my case )\n- followed the [go installation instructions from package](https://go.dev/doc/install)\n\nthis gave me the latest go language compiler, which we will use to compile dendrite as it's\nwritten in go\n\n## installing other dependencies\n\nother dependencies are defined in , but\nat the moment they're :\n\n- go ( already covered in <#:golang> )\n- postgresql database\n- built-in [NATS server](https://github.com/nats-io/nats-server) ( we don't need to do anything here, dendrite comes with one )\n- reverse proxy, such as [nginx](https://nginx.org/), which we will use in this case\n\nand for SSL stuff we will also add `certbot` to our dependencies so we could have a\nsecure SSL connection\n\nto install them, you can run the following :\n\n # apt install postgresql postgresql-client nginx certbot python3-certbot-nginx\n\n- `postgresql` and `postgresql-client` for postgresql dependency and interface\n- `nginx` as our reverse proxy\n- `certbot` and `python3-certbot-nginx` for SSL things\n\n## preparing database\n\npreparing the database is fairly easy as per\n[the matrix dendrite database setup](https://matrix-org.github.io/dendrite/installation/manual/database)\n\nfirstly, you need to start and enable the postgresql service :\n\n # systemctl enable --now postgresql\n\nnext, run the following to switch to postgresql control user :\n\n # su postgres\n $ cd\n\nnow you should be in the postgres user's home dir, now you will\nhave to create the role for dendrite, set its password and create\nits database, but before, i have to warn you to create a password\nsuch as it shouldn't include non-url-safe characters, else it may\nbe a pain to configure dendrite in the future, this is why i'd recommend\nyou just generate the password using the following command :\n\n $ head -n 16 /dev/urandom | base64 -w 0 | shuf | sed 's/[^A-Za-z0-9]//g' | head -c 123\n\nand then using these commands to create the role, set its password and create the database :\n\n $ createuser -P dendrite\n $ createdb -O dendrite -E UTF-8 dendrite\n\nnow you're all set with the database\n\n## compiling dendrite\n\nfirstly, let's set up the user we'll run dendrite on, it is a good practice\nto run applications such as this under lowest possible privileges so we don't\nrun into nasty attacks in the future, here's how you do it :\n\nrun the following command\n\n # useradd -m matrix\n\nthis will create a new user called `matrix` with its own `/home/matrix/` directory,\nwe will run dendrite under this user,, next -- set the password for the user :\n\n # passwd matrix\n\nmake sure to use a secure password, may i recommend [pwdtools](https://ari.lt/gh/pwdtools) ? though you can use anything\n\nyou may also want to run this to make the home directory of this user only readable by that user :\n\n $ chmod 700 -R /home/matrix/\n\nbut it's optional\n\nthen, switch to the matrix user, you can use any user to do this :\n\n $ su matrix\n\nnow as you're the `matrix` user, you should go into your `~` ( home )\ndirectory :\n\n $ cd\n\nnow as you're the matrix user in its home direcotory,\ndownload the latest release tarball ( `.tar.gz` )\noff and extract it\n\nat the moment for me it's\n\nso i'll assume the same, although for future readers --\n**please grab the latest version**, here's an example of how to download it and\nextract it :\n\n $ curl -fLO https://github.com/matrix-org/dendrite/archive/refs/tags/v0.13.5.tar.gz\n $ tar xvf v0.13.5.tar.gz\n $ cd dendrite-0.13.5/\n\nnow you should end up in the latest release of dendrite\n\naccording to \nyou should now run the following :\n\n $ go build -o bin/ ./cmd/...\n\nkeep in mind it's LITERALLY `go build -o bin/ ./cmd/...`\nand not for example `go build -o bin/ ./cmd/*`, it's a literal\nelipsis, run the command as-is with the 3 dots as go is weird\nand quirky like that i guess\n\nthis should build dendrite, keep in mind this will be network\nand resource heavy\n\nnow you can install it :\n\n $ go install ./cmd/dendrite\n\nand your dendrite installation should end up in `~/go/bin/dendrite` :)\n\n## signing keys\n\nnow, you will generate signing keys for your matrix encryption, which will be used\nin authentication of federation requests\n[as explained here, the tutorial for setting up keys in dendrite](https://matrix-org.github.io/dendrite/installation/manual/signingkeys)\n\nrun the following command in the dendrite directory ( the one you ran commands in <#:compiling dendrite> ) :\n\n $ ./bin/generate-keys --private-key matrix_key.pem\n\n**never share this key with anyone**\n\n## configuring dendrite\n\nthis part is based off [my own config of dendrite](https://ari.lt/lh/matrix.ari.lt), which\nis set up by help of people, my own research and [the setup docs](https://matrix-org.github.io/dendrite/installation/manual/configuration),\nkeep up-to-date with my configuration and the docs as this section\nmay get outdated, although i'll do my best to keep this up to date\nas long as i run the ari-web matrix server\n\nfirstly copy the example config :\n\n $ cp dendrite-sample.yaml dendrite.yaml\n\nand now, open it in your favourite text editor, such as `vim` for example, maybe `nano` even :\n\n $ vim dendrite.yaml\n\nnow, i will cover only some parts of the config which you may want to change,\nbut also the default config includes a lot of comments, so you may want to\nlook through all of it and see what you want or don't\n\n`global` :\n\n- `server_name` -- this should be the domain you are delegating from, for example `ari.lt`\n has the `.well-known` delegation to `matrix.ari.lt` so the value of `server_name` will be `ari.lt`\n- `database.connection_string` -- this is the connection string of your postgresql database,\n this should be a url as follows : `postgresql://dendrite:@127.0.0.1/dendrite`, replace ``\n with your password, for example `postgresql://dendrite:password123@127.0.0.1/dendrite`\n- `well_known_server_name` and `well_known_client_name` -- these two keys should have\n the same value of `https://:443`, for example `https://matrix.ari.lt:443`, the\n domain must be the same as your matrix server, not delegated domain ( so `matrix.ari.lt` and not `ari.lt` )\n- make sure `disable_federation` is set to `false`\n- `presence.*` -- set all keys that are `false` to `true`, if you want presence to be a thing\n ( such as typing, online status, etc ), this is optional\n\n`client_api` :\n\n- i'd suggest setting `registration_disabled` and `guests_disabled` to `true` so you'd have full\n control over what people have accounts, if you want open registrations you may want to set both\n of them to `false` or just `registration_disabled` to `false`, depending on your wants, you will\n be able to create new accounts using `./bin/create-account` later on regardless\n- if you disabled registrations, you'll need to set `registration_shared_secret` to some value,\n you can use the password generator command from before -- `head -n 16 /dev/urandom | base64 -w 0 | shuf | sed 's/[^A-Za-z0-9]//g' | head -c 123`\n to generate something good enough\n- you may also want to set `rate_limiting.exempt_user_ids` to yourself ( like `@ari:ari.lt` as an example ),\n maybe even change the rate limiting in general\n\n`sync_api` :\n\n- set the `real_ip_header` to `X-Real-IP`, we will use this in the future\n- if you want search functionality, you may want to set `search.enable` to `true`\n\n`user_api` :\n\n- if you'll have / already have a main / lounge room, you may want to add it to `auto_join_rooms`, like `#root:ari.lt` for example\n\nthat's pretty much it with the configuration of dendrite, although i'd still suggest going through all config options\nat least once and thinking if you want them or not :)\n\n## running dendrite\n\nto run dendrite you can just run\n\n $ ~/go/bin/dendrite -config ./dendrite.yaml\n\nand if you want to run it in the background you just run this :\n\n $ ~/go/bin/dendrite -config ./dendrite.yaml & disown\n\nsimple as that, now dendrite will be listening on port 8008\n\n## dns records\n\nthe `A` record is required\n\n matrix.yourdomain.tld 3600 IN A \n matrix.yourdomain.tld 3600 IN CAA 0 issue \n\nyou may remove `CAA` if you disable all the fancy SSL stuff in nginx\n( which we're about to configure )\n\nyou can also optionally add `AAAA` for ipv6 support\n\nfor ari-web i've set it up like this :\n\n matrix.ari.lt 3600 IN A 62.171.174.136\n matrix.ari.lt 3600 IN CAA 0 issue letsencrypt.org\n\n## configuring nginx\n\n**tldr** <#:final nginx config>\n\nin our case we will use nginx as our reverse proxy, this i will base off\n[my own nginx config for my vps](https://us.ari.lt/git/blob/main/res/nginx.conf)\n\nfirstly, you need to make sure if either user `www-data` or `http` exists, you can do that\nby running\n\n $ cat /etc/passwd\n\nwhich will show you all users\n\nif none do, run\n\n # useradd www-data # or http\n\nafter that, make sure that `/etc/nginx/mime.types` exists :\n\n $ ls /etc/nginx/mime.types\n\nif not, run the following command :\n\n # curl https://raw.githubusercontent.com/nginx/nginx/master/conf/mime.types -fLo /etc/nginx/mime.types\n\nnow, open up `/etc/nginx/nginx.conf` in your favourite text editor and configure it :\n\n # vim /etc/nginx/nginx.conf\n\nwe will start by setting up some base rules :\n\n user www-data;\n worker_processes auto;\n pid /run/nginx.pid;\n worker_rlimit_nofile 8192;\n\n events {\n use epoll;\n multi_accept on;\n worker_connections 4096;\n }\n\nmake sure to replace `www-data` with `http` if you're using the `http` user instead,\nhere's what this piece of config means :\n\n- `user www-data;` will make sure that the worker processes run under a low privilege user\n such as `www-data`\n- `worker_processes auto;` makes the worker process count optimal for your cpu\n core count, each worker than handle thousands of connections\n- `pid /run/nginx.pid;` specifies the file where the server will write its master process id\n- `worker_rlimit_nofile 8192;` sets the limit of maximum number of file descriptors opened by this process ( every connection is a unix socket, so also a file descriptor )\n- `use epoll;` sets the method to use to get notifications for network events, `epoll` is particularly good for linux\n- `multi_accept on;` allows to handle multiple simultaneous connections\n- `worker_connections 4096;` sets the limit of maximum number of connections per worker\n\nnext, we'll set up some basic config for our server :\n\n http {\n include mime.types;\n default_type application/octet-stream;\n\n access_log off;\n\n tcp_nopush on;\n tcp_nodelay on;\n keepalive_timeout 120;\n types_hash_max_size 2048;\n server_names_hash_bucket_size 256;\n\n sendfile on;\n }\n\nyou can dig into this config deeper, but abstractly :\n\n- `default_type application/octet-stream;` sets the default mime type to `application/octet-stream` ( binary data )\n- `access_log off;` turns off the access log so we don't log requests and their IPs\n- sets up some TCP options\n- sets `types_hash_max_size`, it's the mime type hash table size, this is for different types of mime types for different files as matrix also works on file uploading\n- `server_names_hash_bucket_size 256;` is for server directives, how much memory it's allowed to use\n- `sendfile on;` is for file uploads\n\nnow, we can set up a basic `server` :\n\n http {\n ...\n\n server {\n listen 80;\n listen [::]:80;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n return 301 https://$server_name$request_uri;\n }\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n }\n }\n\nhere you can also now start nginx :\n\n # systemctl enable --now nginx\n\nthis sets up the basic requirements for a server, make sure to\nreplace yourdomain.tld / matrix.yourdomain.tld with whatever your\npreferred domain is, 443 is the https ( tls ) port and 8448 is the secure\nfederation port,, this is where we have to take a step back,\nsave our nginx config and move on for a little bit\n\n### tls ( https )\n\nto set up tls ( https ) on our server now, we will have to run this command :\n\n certbot certonly --nginx\n\nand follow the directions on the screen\n\nnow, as you have that set up, you can continue setting up your proxy, add SSL stuff :\n\n http {\n ...\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n ssl_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/matrix.yourdomain.tld/privkey.pem;\n ssl_trusted_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n\n ssl_stapling on;\n ssl_stapling_verify on;\n ssl_session_timeout 1d;\n ssl_session_cache shared:MozSSL:10m;\n ssl_session_tickets off;\n ssl_protocols TLSv1.2 TLSv1.3;\n ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256';\n ssl_prefer_server_ciphers on;\n }\n }\n\nno, we dont need to touch the `:80` one, that will always stay the same as it'll just redirect to https\n\ni won't explain these options, but basically only two lines of SSL things are required :\n\n ssl_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/matrix.yourdomain.tld/privkey.pem;\n\nother stuff is sanity and security, i won't dig deep into it but basically this enables\n[ssl stapling](https://knowledge.digicert.com/quovadis/ssl-certificates/ssl-general-topics/what-is-ocsp-stapling)\nand also sets up some secure preferred ciphers so we know that secure encryption is happening\nat all times\n\nif you didn't choose to use the `CAA` record you may use only those two lines instead of all those `ssl_*`\nconfigurations\n\nand now, you are done setting ssl up on nginx\n\n### after ssl ( https )\n\nnow, we add our locations :\n\n http {\n ...\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n ...\n\n location = / {\n access_log off;\n return 301 https://$server_name/_matrix/static/;\n }\n\n location ~ ^(/_matrix|/_synapse/client) {\n access_log off;\n\n proxy_pass http://127.0.0.1:8008;\n\n proxy_http_version 1.1;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n client_max_body_size 512M;\n proxy_max_temp_file_size 0;\n proxy_buffering off;\n }\n }\n }\n\n`location = /` sets up the `/` location of your server, it'll always redirect to\nthe dendrite static page so once you visit `matrix.yourdomain.tld`, it'll always\nredirect to the welcome page, so it doesn't look as boring, although you can just\nremove that, it's optional\n\nnow `location ~ ^(/_matrix|/_synapse/client)` is where the actual federation stuff happens,\nas always we turn off the access log and we pass our requests to our local dendrite instance\nrunning on port `8008` and then set up the following things :\n\n- always set the http version to 1.1\n- set a couple of headers ( such as `X-Real-IP` from before, this is used for multiple things )\n- `client_max_body_size 512M;` states that the accepted body of a client cannot exceed 512 megabytes,\n you can increase or decrease the size, this is only ever an issue in file uploads\n- `proxy_max_temp_file_size 0;` sets the maximum size of a temp file, keeping it `0` disables the\n buffering, which means the content coming FROM the proxy directly to the user, if not this\n breaks downloads in matrix and makes it so they break and only partially deliver something\n- `proxy_buffering off;` this is like `proxy_max_temp_file_size 0` but instead its TO user not FROM user\n\n## final nginx config\n\nafter all this work we end up with a config something like :\n\n user www-data;\n worker_processes auto;\n pid /run/nginx.pid;\n worker_rlimit_nofile 8192;\n\n events {\n use epoll;\n multi_accept on;\n worker_connections 4096;\n }\n\n http {\n include mime.types;\n default_type application/octet-stream;\n\n access_log off;\n\n tcp_nopush on;\n tcp_nodelay on;\n keepalive_timeout 120;\n types_hash_max_size 2048;\n server_names_hash_bucket_size 256;\n\n sendfile on;\n\n server {\n listen 80;\n listen [::]:80;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n return 301 https://$server_name$request_uri;\n }\n\n server {\n listen 443 ssl;\n listen [::]:443 ssl;\n\n listen 8448 ssl http2 default_server;\n listen [::]:8448 ssl http2 default_server;\n\n server_name matrix.yourdomain.tld;\n\n access_log off;\n\n ssl_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/matrix.yourdomain.tld/privkey.pem;\n ssl_trusted_certificate /etc/letsencrypt/live/matrix.yourdomain.tld/fullchain.pem;\n\n ssl_stapling on;\n ssl_stapling_verify on;\n ssl_session_timeout 1d;\n ssl_session_cache shared:MozSSL:10m;\n ssl_session_tickets off;\n ssl_protocols TLSv1.2 TLSv1.3;\n ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256';\n ssl_prefer_server_ciphers on;\n\n location = / {\n access_log off;\n return 301 https://$server_name/_matrix/static/;\n }\n\n location ~ ^(/_matrix|/_synapse/client) {\n access_log off;\n\n proxy_pass http://127.0.0.1:8008;\n\n proxy_http_version 1.1;\n\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $remote_addr;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n client_max_body_size 512M;\n proxy_max_temp_file_size 0;\n proxy_buffering off;\n }\n }\n }\n\nyou can now save the file and quit the editor, also, a tip : avoid gzip compression, it kills performance\nand cpu on your vps, it's painful, stick to vanilla\n\nyou can also add this to `http` block to enable [HSTS preload](https://scotthelme.co.uk/hsts-preloading/)\nwith which you can apply to [hstspreload.org](https://hstspreload.org/) :\n\n http {\n ...\n\n add_header Strict-Transport-Security \"max-age=63072000; includeSubDomains; preload\";\n\n ...\n }\n\n## finalizing\n\nnow, after all this your matrix server is almost done, all you have to do is :\n\nlog into the matrix user :\n\n $ su matrix\n\nchange to its home :\n\n $ cd\n\nkill dendrite :\n\n $ pkill -f dendrite\n\nrestart nginx\n\n # systemctl restart nginx\n\nrestart dendrite :\n\n $ ~/go/bin/dendrite -config ./dendrite.yaml & disown\n\n## sanity check\n\nnow, as everything is up and running, make sure everything's okay by going to\n`matrix.yourdomain.tld`, it should show you the dendrite index page, if it doesn't,\nplease verify everything and make sure everything's okay\n\nif you cannot figure it out, you can come and ask in\n[#root:ari.lt](https://matrix.to/#/#root:ari.lt) or [#dendrite:matrix.org](https://matrix.to/#/#dendrite:matrix.org)\n\n## new user\n\nnow, as everything works, you can log in as the matrix user and create a new account for yourself by\ngoing into the directory which you built dendrite in ( the one with `bin/` directory in it )\nand run this :\n\n $ ./bin/create-account --config dendrite.yaml -username some_username -admin\n\nthis will prompt you for a password, dendrite doesn't seem to like passwords over 72 characters,\nso make sure it fits\n\nyou can also create normal user accounts by doing :\n\n $ ./bin/create-account --config dendrite.yaml -username some_username\n\naka removing the `-admin` argument\n\nnow, you can log in with your [favourite matrix client](https://matrix.org/ecosystem/clients/)\nsuch as for example [schildi](https://schildi.chat/)\nor [element](https://element.io/), have fun\n\n## concluding\n\ni hope i could help at least a little, it took me a while to figure out issues, solve problems,\nfind answers and come up with my own solutions, ask people, debug, etc etc etc\n\na lot of trouble went into this and i hope this popped up in your search engine whenever you're looking\nto solve such issues as :\n\n- how to set up dendrite on nginx properly and securely\n- dendrite matrix implementation on nginx not sending the full file / image ( partial send and then stream close )\n - main config options in <#:final nginx config> to look out for would be\n - `types_hash_max_size 2048;`\n - `server_names_hash_bucket_size 256;`\n - `sendfile on;`\n - `client_max_body_size 512M;`\n - `proxy_max_temp_file_size 0;`\n - `proxy_buffering off;`\n- failing to sync data in ( android ) clients on dendrite matrix instance\n - still unsure why web works, but i think it's related to it not sending full files\n- how to properly delegate a matrix domain\n- why am i getting `M_UNRECOGNIZED` in dendrite matrix server\n - probably because you have forwarding set up badly, make sure to not have just `location /` for example\n- why am i getting request signature errors in dendrite matrix server in nginx\n - also related to the `M_UNRECOGNIZED` problem, make sure to not overgeneralize the location, use `location ~ ^(/_matrix|/_synapse/client)`\n- generally setup errors and issues with setting up dendrite with nginx and ssl\n\n## related error messages\n\n( just in case someone decides to look them up and can't find an answer )\n\n- dendrite matrix implementation on nginx not sending the full file / image ( partial send and then stream close )\n\n```\ncurl: (92) HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)\n```\n\n( from curl )\n\n- failing to sync data in ( android ) clients on dendrite matrix instance\n\n```\n# [WARNING] Syncloop failed: Client has not connection to the server\n# [WARNING] Something went wrong: - Instance of 'SyncConnectionException'\n```\n\n( from fluffychat android )\n\n Initial sync:\n Downloading data...\n\n( from element android and schildichat android )\n\n Loading... Please wait.\n Oops something went wrong...\n\n( from fluffychat android )\n\n INFO[2023-12-26T19:32:19.277303943Z] Starting queue due to pending events or forceWakeup\n\n( from dendrite logs )\n\n time=\"2023-12-26T19:16:03.938083486Z\" level=info msg=\"Starting queue due to pending events or forceWakeup\" func=\"github.com/matrix-org/dendrite/federationapi/queue.(*destinationQueue).wakeQueueIfEventsPending\" file=\"/home/matrix/dendrite/federationapi/queue/destinationqueue.go:158\"\n\n( from dendrite logs )\n\n 2023-12-26T21:42:30*130GMT+00:00Z 171 E/ /Tag: ## Sync: sync service did fail true\n java.net.ProtocolException: unexpected end of stream\n ...\n\n( from fluffychat android data logs )\n\n- how to properly delegate a matrix domain\n\n```\nTesting matrix.ari.lt failed: mismatching server name, tested: matrix.ari.lt, got: ari.lt // Dendrite 0.13.5+9a5a567\n```\n\n( from [@version:envs.net](https://matrix.to/#/@version:envs.net) )\n\n Homeserver URL does not appear to be a valid Matrix homeserver\n\n( from element web )\n\n- why am i getting `M_UNRECOGNIZED` in dendrite matrix server\n\n```\n{\"errcode\":\"M_UNRECOGNIZED\",\"error\":\"Unrecognized request\"}\n```\n\n( from dendrite response )\n\n- why am i getting request signature errors in dendrite matrix server in nginx\n\n```\nINFO[2023-12-26T00:00:08.867552600Z] Invalid request signature error=\"Bad signature from \\\"4d2.org\\\" with ID \\\"ed25519:a_MgDi\\\"\" req.id=... req.method=PUT req.path=\"/\\_matrix/federation/v2/invite/!...:4d2.org/$...\"\n```\n\n( from dendrite logs )\n\ngood luck !", "keywords": [ "cinny", "golang",