I posted this on the serverbuilds.net forums, and noticed that several users here were interested, so cross-posting!
This a somewhat complex yet in-demand installation, so I figured I'd share my steps in getting a Riot.im chat server syndicated through a Matrix bridge that supports a Jitsi voip/video conference bridge. The end result is a self-hosted discord-like chat server where any chat room can become a video conference with a single click! It has some other neat features like end-to-end encryption and syndication with other matrix server AND other types of chat servers (you can have a chat room that links to a discord room, irc channel, etc). We'll do almost all of this using apps from the Unraid Community Applications repo!
Summary:
We'll setup some domains for each of our components, then use a LetsEncrypt proxy to generate certificates. Matrix will run the back-end, Riot Chat will run the front-end, and Jitsi will handle the A/V.
DNS Setup:
You're gonna want a few subdomains, even if you have a dyndns setup pointing to your host. Then can all point to the same IP, or you can use CNAME or ALIAS records to point to the root domain. A DNS setup for somedomain.gg might look like this:
Type - Host - Value
A - @ - 1.2.3.4 (Your WAN IP)
CNAME - bridge - somedomain.gg
CNAME - chat - somedomain.gg
CNAME - meet - somedomain.gg
In the above-the `@` A-record will set the IP for your domain root, and the CNAME-records will cause the 3 subdomains to resolved to whatever domain name you point them at (the root domain, this this case).
Each domain will host the following:
bridge: matrix - The core communications protocol
chat: riot - The chat web UI
meet: jitsi - The video conferencing bridge
Firewall Setup:
You'll need the following ports forwarded from you WAN to you Unraid server:
LetsEncrypt: WAN TCP 80 -> LAN 180 , WAN TCP 443 -> LAN 1443, WAN TCP 8448 -> LAN 1443, all on your Unraid server IP
- 80: Used by LetsEncrypt to validate your certificate signing request -- this can be disabled after setup, then only enabled when you need to renew a certificate.
- 443: LetsEncrypt proxy for encrypted web, duh
- 8448: Matrix Integrations port for enabling plugins. Also proxied via LetsEncrypt. Make sure this points to 1443, not 8443!
STUN: TCP and UDP 3478 on WAN -> 3478 on Unraid (or changed to suit your needs)
Jitsi: UDP Port 10000 -> 10000 on Unraid
We'll be assuming you used these ports in the rest of the guide, so if you needed to change any, compensate as needed!
Docker Networking:
This is a fairly complex configuration that will use at least 7 docker containers. To make this easier we'll create a custom docker network that these containers will all live on, so that they can communicate between each other without having to worry about exposing unnecessary ports to your LAN:
1. In Unraid, go to Settings->Docker.
2. Disable docker so you can make changes: set `Enable Docker` to `No`
3. Set `Preserve user defined networks` to `Yes`
4. Re-enable Docker
5. Open the Unraid console or SSH in.
6. Create a new Docker network by executing `docker network --subnet 172.20.0.0/24 create sslproxy` or whatever subnet works for you (adjusted below as needed).
We're now done with the pre-install stuff! I'd suggest testing your DNS and that the ports are all open on your FW and are getting directed to the right places. If everything looks good, then lets get some dockers!
LetsEncrypt Install:
Before proceeding, wait for your DNS server to update and make sure you can resolve the 3 subdomains remotely. This is REQUIRED for LetsEncrypt to validate the domains! LetsEncrypt will need listen on port 80 and port 443 of your WAN (public-facing) interface so that it can validate your ownership of the domains.
We're going to use a Docker from the Unraid Community Applications docker. But before we do, we need to enabled user defined networks in our Docker settings. But first,
1. In Community Applications, search for `LetsEncrypt` and install the container from `linuxserver`
2. Set the `Network Type` to `Custom: ssl proxy`
3. Set the `Fixed IP address` to `172.20.0.10` (or whatever works for you)
4. Make sure `Privileged` is set to `On`
5. Set the `http` port to `180` and the `https` port to `1443`
6. Supply an email
7. Enter your domain name, ie `somedomain.gg`
8. Enter your subdomains: `chat,bridge,meet` (and any others you want to encrypt)
9. Optional: set `Only Subdomains` to false if you want the root domain to also have a cert!
The rest of the options should be fine as-is.
If you do NOT have a domain, but use a dynamic dns service, you can still mange but might be limited to a single domain. Make sure `Only Subdomains` is set to `True`, otherwise your install will fail as LetsEncrypt will expect you have be running on your dyndns services web server! The following steps will also require you to do some nginx subdirectory redirection instead of domain proxying. SpaceInvader has a great video that demonstrates this in detail.
Once you've created the docker instance, review the log. It might take a minute or two to generate the certificates. Let it finished and make sure there are no errors. It should say `Server ready` at the end if all goes well!
Try browsing to your newly encrypted page via https://somedomain.gg (your domain) and make sure all looks right. You should see a letsencrypt landing page for now.
If all went well, your LetsEncrypt certificates and proxy configuration files should be available in /mnt/user/appdata/letsencrypt/
LetsEncrypt Proxy Configuration:
LetsEncrypt listens on ports 80 and 443, but we also need it to listen on port 8448 in order for Riot integrations via the public integration server to work property. Integrations let your hosted chatrooms include bots, helper commands (!gif etc), and linking to other chat services (irc, discord, etc). This is optional! If you're happy with vanilla Riot, you can skip this. Also, you can run your own private Integrations server, but I'm not getting into that here. So assuming you want to use the provided integrations, we need to get nginx listening on port 8448. To do that, edit `/mnt/user/appdata/letsencrypt/nginx/site-confs/default` and make the following change:
Original:
New:
Next, we are going to need 3 proxy configurations inside LetsEncrypt's nginx server (one for matrix, riot and jitsi). These live in `/mnt/user/appdata/letsencrypt/mnt/user/appdata/letsencrypt/`. Create the following file:
matrix.subdomain.conf:
riot-web.subdomain.conf:
jitsi.subdomain.conf:
^^^ NOTE!!! Make sure you saw the `CHANGE THIS` part of the `$upstream_app` setting. This should be the LAN IP of your Unraid server!
Done! To test, trying visiting https://<subdomain>.somedomain.gg/ and you should bet a generic gateway error message. This means that the proxy files attempted to route you to their target services, which don't yet exist. If you got the standard LetsEncrypt landing page, then something is wrong!
Matrix
A Matrix container is available from avhost in Community Applications.
1. In Community Applications, search for `Matrix` and install the container from `avhost`
2. Set the `Network Type` to `Custom: ssl proxy`
3. Set the `Fixed IP address` to `172.20.0.30` or whatever works for you
4. Set the `Server Name` to `bridge.somedomain.gg` (your domain)
5. The rest of the settings should be fine, and I suggest not changing the ports if you can get away with it. Create the container and run it.
Now we need to edit our Matrix config.
1. Edit `/mnt/user/appdata/matrix/homeserver.yaml`
2. Change `server_name: "bridge.somedomain.gg"`
3. Change `public_baseurl: https://bridge.somedomain.gg/"`
4. Under `listeners:` and `- port: 8008` change `bind_address: ['0.0.0.0']`
5. Change `enable_registration: true`
6. Change `registration_shared_secret: xxxx` to some random value. It doesn't matter what it is, just don't use the one from the default config!
7. Change `turn_uris` to point to your domain, ie `"turn:bridge.somedomain.gg:3478?transport=udp"`
8. Set a good long random value for `turn_shared_secret`
If you have errors at start-up about your turnserver.pid file or database, you can try editing your /mnt/user/appdata/matrix/turnserver.conf file and adding:
pidfile=/data/turnserver.pid
userdb=/data/turnserver.db
There are a ton of other settings you can play with, but I'd wait until after it working to get too fancy!
Now restart the Matrix container, and check that https://bridge.somedomain.gg/ now shows the Matrix landing page. If not, something's wrong!
Riot Chat
Riot Chat servers as we web front-end chat interface. There's also a great mobile app called RiotIM. For the web interface, there's an Community Applications image for that!
1. Before we start, we need to manually create the config path and pull in the default config. So open a console/SSH to your server.
2. Create the config path by executing `mkdir -p /mnt/user/appdata/riot-web/config`
3. Download the default config by executing `wget -O /mnt/user/appdata/riot-web/config/config.json https://raw.githubusercontent.com/vector-im/riot-web/develop/config.sample.json` (**NOTE**: This is a different URL than the one suggested in the Docker!)
4. In Community Applications, search for `riot web` and install the container from `vectorim`. Watch you, there are two -- use the one with the fancy icon, which doesn't end with an asterisk (`*`)!
5. Set the `Network Type` to `Custom: ssl proxy`
6. Set the `Fixed IP address` to `172.20.0.20` (or whatever)
7. The rest of the settings should be fine. Create the container and run it.
Now lets edit our Riot config. It's a JSON file, so make sure you respect JSON syntax
1. Edit ` /mnt/user/appdata/riot-web/config/config.json`
2. Change `"base_url": "https://bridge.somedomain.gg",`
3. Change `"server_name": "somedomain.gg",`
4. Under the `"Jitsi:"` subsection near the bottom, change `"preferredDomain": "meet.somedomain.gg"`
If all went well, you should see the Riot interface at http://chat.somedomain.gg! If not, figure out why...
Now lets create our first account!
1. From the welcome page, click `Create Account`
2. If the prior config was correct, `Advanced` should already be selected and it should say something like `Create your Matrix account on somedomain.gg`. If the `Free` option is set, then your RiotChat web client is using the public matrix.org service instead of your private instance! Make sure your `base_url` setting in your config.json is correct. Or just click Advanced, and enter `https://bridge.somedomain.gg` in the `Other Servers: Enter your custom homeserver URL` box.
3. Set your username and password
4. Setup encryption by following the prompts (or skip if you don't care). This may require that you whitelist any browser script blockers that you have running.
Done! You now have a privately hosted Discord-alternative! Lets add some voice and video chat so we can stop using Zoom 😛
Jitsi
This part doesn't have a solid Docker image in the Community Application store, so there's a few more steps involved. We're gonna need to clone their docker setup, which uses docker-compose.
1. Open a console/SSH to your server
2. Install docker-compose by executing `curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose`
3. Make it executable: `chmod u+x /usr/local/bin/docker-compose`
4. Move to your appdata folder : `cd /mnt/user/appdata`
5. Make and enter a folder for you docker-compose projctes: `mkdir docker-compose; cd docker-compose`
6. Clone and enter the `docker-jitsi-meet` repo: `git clone https://github.com/jitsi/docker-jitsi-meet ; cd docker-jitsi-meet`
7. Create an install environment: `cp env.example .env`
8. Populate some random secrets in your environment: `./gen-passwords.sh`
9. Edit the install environment (I'm using nano, but edit however you want): nano .env
10. Change `CONFIG=/mnt//mnt/user/appdata/jitsi-meet/`
11. Set TZ to your timezome, ie `TZ=America/Denver`
12. Change `PUBLIC_URL=https://meet.somedomain.gg`
13. Change `DOCKER_HOST_ADDRESS=192.168.0.1` or whatever the LAN address of your Unraid server is
14. Create the CONFIG path that you defined in step 10: `mkdir /mnt//mnt/user/appdata/jitsi-meet/`
15. Create and start the containers: `docker-compose -p jitsi-meet -f docker-compose.yml -f etherpad.yml up -d`
16. This will create 4 Jitsi containers are part of a Docker Stack -- see your list of dockers. You can't edit them, but take note of the `jitsi-meet_web_1` ports, which should be `8000` and `8443`. If you got any errors, it's likely a port conflict somewhere, so find the corresponding setting in your `.env` file and adjust as needed, reflecting any relevant changes in the next step.
When we were setting up our Nginx proxy configs, you'll recall that the Jitsi config `$upstream_app` had to be set manually, rather than relying on the internal DNS. That's because the docker-compose stack names are not 100% predicatble, so it's better to just hard-code it. You might want to double-check that setting if you have in uses from here on.
To test Jitsi, go to https://meet.somedomain.gg/ and hopfully you see the Jitsi page. Try to create a meeting. In the future, it may be wise to enable Authentication on your Jitsi server if you dont want any random person to be able to host conferences on your sever! See the docs (or SpaceInvader's video) for details on that.
Now find a friend and get them to register a Riot account on your server at https://chat.somedomain.gg (or use the mobile app and connect to the custom host). Get in a chat room together, then click the Video icon next to the text input box and make sure it works. It's worth noting that Jitsi works differently when there are only 2 people chatting -- they'll communicate directly. With 3 or more, they'll communicate with the Jitsi server and use the TURN service. So it's a good idea to try to get a 3rd person to join as well, just to test out everything.
Thats it, hope this helps! Enjoy!
To Do:
* Custom Integrations Server
* Etherpad Integration
Edit: While I was making this guide, SpaceInvader came out with a great video covering the Jitsi part! It covers some authentication options that I didn't get into, but would highly suggest. Check it out!