This is a quick-and-dirty playbook for deploying a self-hosted social space using Matrix.
The intended use case is a private, invite-only community resembling Discord or Slack. It is very performant for the small community sizes tested, but should continue to be relatively resource light for larger communities if federation with other Matrix homeservers remains disabled.
Plenty of excellent guides for self-hosting Matrix already exist. These typically demonstrate deployments that have one or more of the following useful traits, but not all of them:
- Matrix homeserver and reverse proxy communicate over Unix socket instead of TCP. Since they are on the same machine, this can yield a substantial performance improvement.
- MatrixRTC included. This provides out-of-the-box voice and video chat support through LiveKit.
- Web client included. Users can register and connect through a client that you host, too - no need to trust a third-party app or web client.
- Reverse proxy runs in its own Docker container. A surprising number of walkthroughs assume that the homeserver (and optionally LiveKit) run in Docker containers, but the reverse proxy server doesn't!
- Federation disabled. Counterintuitive for most Matrix self-host guides, but useful if the goal is to set up an invite-only, private social space e.g. for friends and family. There are some non-obvious configuration changes required, especially if using MatrixRTC.
- continuwuity: a Matrix homeserver.
- LiveKit: enables voice and video calls, including voice rooms and screen streaming.
- Cinny: a web-based Matrix client with a UI resembling Slack or Discord.
- Caddy: a reverse proxy to properly route requests among the above and handle TLS certificates.
- A host machine available, e.g. a VPS or homelab server, with a static public IP address.
- Docker engine installed on the host machine.
- Firewall for the host machine has open inbound ports:
- 80
- 443
- 8448
- 7880:7881
- 50100:50200 (UDP)
- 8081
- 3478 (UDP)
- 50300:50400 (UDP)
- A domain name registered, e.g.
example.com. - Public DNS records pointing to the registered domain:
| Type | From | To |
|---|---|---|
A |
example.com |
host's public IPv4 address |
AAAA |
example.com |
host's public IPv6 address |
CNAME |
matrix.example.com |
example.com |
CNAME |
social.example.com |
example.com |
CNAME |
livekit.example.com |
example.com |
- Data backups configured as appropriate. Do note that any end-to-end encrypted content may be unrecoverable if the entire docker-compose cluster is stopped and started again; more investigation is needed to determine how this happens.
- Clone this repository on the host machine. Navigate to this directory.
- In all files, replace all references to
mydomain.comwith your domain e.g.example.com. - In
continuwuity.toml, generate a unique token required for registration, and update the value in the lineregistration_token = "your_servers_unique_registration_token"with it. - Generate a unique key/value pair for LiveKit e.g. using
docker run --rm livekit/livekit-server:latest generate-keys. Indocker-compose.ymlandlivekit.yml, replaceMyLiveKitKeywith the key andMyLiveKitKeyValuewith the value. - Update
/etc/docker/daemon.jsonby adding to the fileas this prevents runaway memory usage.{ "userland-proxy": false } - Run
sudo docker compose up -d. - Wait for certificates to be generated.
- Create the first user, which is automatically an admin user, by running
sudo docker exec -it continuwuity users create-user <username> <password>, replacing<username>and<password>with your desired values. Note that if using a username other than "admin", you should change the line instatic/well-known/matrix/supportto reflect the actual admin username. - Test the web client by connecting to
social.example.comwith a web browser and attempting to log in with the admin credentials from the previous step. - When inviting others to the server, share with them the manually specified registration token from step 3 and have them register on
social.example.comor with an alternative Matrix client of their choice.