File: README.md
Matrix (An open network for secure, decentralized communication) server setup using Ansible and Docker
🎯 Purpose
This Ansible playbook is meant to help you run your own Matrix homeserver, along with the various services related to that.
That is, it lets you join the Matrix network using your own user ID like @alice:example.com, all hosted on your own server (see prerequisites).
We run all supported services in Docker containers (see the container images we use), which lets us have a predictable and up-to-date setup, across multiple supported distros (see prerequisites) and architectures (x86/amd64 being recommended).
Installation (upgrades) and some maintenance tasks are automated using Ansible (see our Ansible guide).
☁ Self-hosting or Managed / SaaS
This Ansible playbook tries to make self-hosting and maintaining a Matrix server fairly easy (see Getting started). Still, running any service smoothly requires knowledge, time and effort.
If you like the FOSS spirit of this Ansible playbook, but prefer to put the responsibility on someone else, you can also get a managed Matrix server from etke.cc (both hosting and on-premises) - a service built on top of this Ansible playbook but with additional components and services which all help you run a Matrix server with ease. Be advised that etke.cc operates on a subscription-based approach and there is no "just set up my server once and be done with it" option.
🚀 Getting started
We have detailed documentation in the docs/ directory - see the Table of Contents in the documentation README.
While the list of supported services and documentation is very extensive, you don't need to read through everything. We recommend:
Starting with the basics. You can always add/remove or tweak services later on.
Following our installation guide. There are two guides available for beginners and advanced users:
⚡ Quick start (for beginners): this is recommended for those who do not have an existing Matrix server and want to start quickly with "opinionated defaults".
Full installation guide (for advanced users): if you need to import an existing Matrix server's data into the new server or want to learn more while setting up the server, follow this guide by starting with the Prerequisites documentation page.
If you experience an issue on configuring the playbook, setting up your server, maintaining services on it, etc., please take a look at our FAQ. If you cannot find an answer to your question, feel free to ask for help and support.
✔ Supported services
Using this playbook, you can get the following list of services configured on your server. Basically, this playbook aims to get you up-and-running with all the necessities around Matrix, without you having to do anything else.
Notes:
The list below is exhaustive. It includes optional or even some advanced components that you will most likely not need. Sticking with the defaults (which install a subset of the above components) is the best choice, especially for a new installation. You can always re-run the playbook later to add or remove components.
Deprecated or unmaintained services are not listed. You can find documentations for them here.
Homeserver
The homeserver is the backbone of your Matrix system. Choose one from the following list.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| Synapse | ✅ | Storing your data and managing your presence in the Matrix network | Link |
| Conduit | ❌ | Storing your data and managing your presence in the Matrix network. Conduit is a lightweight open-source server implementation of the Matrix Specification with a focus on easy setup and low system requirements | Link |
| continuwuity | ❌ | Storing your data and managing your presence in the Matrix network. | Link |
| Tuwunel | ❌ | Storing your data and managing your presence in the Matrix network. Tuwunel is the official successor to conduwuit. | Link |
| Dendrite | ❌ | Storing your data and managing your presence in the Matrix network. Dendrite is a second-generation Matrix homeserver written in Go, an alternative to Synapse. | Link |
Clients
Web clients for Matrix that you can host on your own domains.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| Element Web | ✅ | Default Matrix web client, configured to connect to your own Synapse server | Link |
| Hydrogen | ❌ | Lightweight Matrix client with legacy and mobile browser support | Link |
| Cinny | ❌ | Simple, elegant and secure web client | Link |
| Sable | ❌ | Simple, elegant and secure web client | Link |
| SchildiChat Web | ❌ | Based on Element Web, with a more traditional instant messaging experience | Link |
| FluffyChat Web | ❌ | The cutest messenger in Matrix | Link |
| Commet | ❌ | Matrix web client | Link |
Server Components
Services that run on the server to make the various parts of your installation work.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| PostgreSQL | ✅ | Database for Synapse. Using an external PostgreSQL server is also possible. | Link |
| Traefik | ✅ | Web server, listening on ports 80, 443 and 8448 - standing in front of all the other services. Using your own webserver is also possible. | Link |
| Let's Encrypt | ✅ | Free SSL certificate, which secures the connection to all components | Link |
| Exim | ✅ | Mail server, through which all Matrix services send outgoing email (can be configured to relay through another SMTP server) | Link |
| coturn | ❌ | STUN/TURN server for WebRTC audio/video calls | Link |
| ddclient | ❌ | Dynamic DNS | Link |
| Matrix RTC stack | ❌ | Supporting components (LiveKit Server and LiveKit JWT Service) for in-app audio/video calls for Matrix clients | Link |
Authentication
Extend and modify how users are authenticated on your homeserver.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| matrix-synapse-rest-auth (advanced) | ❌ | REST authentication password provider module | Link |
| matrix-synapse-shared-secret-auth (advanced) | ❌ | Password provider module | Link |
| matrix-synapse-ldap3 (advanced) | ❌ | LDAP Auth password provider module | Link |
| Matrix User Verification Service | ❌ | Service to verify details of a user based on an Open ID token | Link |
| synapse-simple-antispam (advanced) | ❌ | Spam checker module | Link |
File Storage
Use alternative file storage to the default media_store folder.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| Goofys | ❌ | Amazon S3 (or other S3-compatible object store) storage for Synapse's content repository (media_store) files |
Link |
| synapse-s3-storage-provider | ❌ | Amazon S3 (or other S3-compatible object store) storage for Synapse's content repository (media_store) files |
Link |
| matrix-media-repo | ❌ | Highly customizable multi-domain media repository for Matrix. Intended for medium to large deployments, this media repo de-duplicates media while being fully compliant with the specification. | Link |
Bridges
Bridges can be used to connect your Matrix installation with third-party communication networks.
Bots
Bots provide various additional functionality to your installation.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| baibot | ❌ | Bot that exposes the power of AI / Large Language Models to you | Link |
| matrix-reminder-bot | ❌ | Bot for scheduling one-off & recurring reminders and alarms | Link |
| maubot | ❌ | Plugin-based Matrix bot system | Link |
| Honoroit | ❌ | Helpdesk bot | Link |
| Mjolnir | ❌ | Moderation tool for Matrix | Link |
| Draupnir | ❌ | Moderation tool for Matrix (Fork of Mjolnir) | Link (for appservice mode) |
| Meowlnir | ❌ | Moderation tool for Matrix, running in appservice mode | Link |
| Buscarron | ❌ | Web forms (HTTP POST) to Matrix | Link |
Administration
Services that help you in administrating and monitoring your Matrix installation.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| matrix-alertmanager-receiver | ❌ | Prometheus' Alertmanager client | Link |
| Matrix Authentication Service | ❌ | OAuth 2.0 and OpenID Provider server | Link |
| Ketesa | ❌ | Fully-featured web UI for administrating your Matrix homeserver — users, rooms, media, sessions, and more | Link |
| Metrics and Graphs | ❌ | Consists of the Prometheus time-series database server, the Prometheus node-exporter host metrics exporter, and the Grafana web UI, with prometheus-nginxlog-exporter being available too | Link (for prometheus-nginxlog-exporter) |
| Borg | ❌ | Backups | Link |
| rageshake | ❌ | Bug report server | Link |
| synapse-usage-exporter | ❌ | Export the usage statistics of a Synapse homeserver to be scraped by Prometheus. | Link |
Misc
Various services that don't fit any other categories.
| Name | Default? | Description | Documentation |
|---|---|---|---|
| synapse_auto_compressor | ❌ | Cli tool that automatically compresses state_groups database table in background |
Link |
| Matrix Corporal (advanced) | ❌ | Reconciliator and gateway for a managed Matrix server | Link |
| Matrix.to | ❌ | Simple URL redirection service for the Matrix ecosystem | Link |
| Etherpad | ❌ | Open source collaborative text editor | Link |
| Jitsi | ❌ | Open source video-conferencing platform | Link |
| Cactus Comments | ❌ | Federated comment system built on Matrix | Link |
| Pantalaimon | ❌ | E2EE aware proxy daemon | Link |
| Sygnal | ❌ | Push gateway | Link |
| ntfy | ❌ | Push notifications server | Link |
| Element Call | ❌ | A native Matrix video conferencing application | Link |
🆕 Changes
This playbook evolves over time, sometimes with backward-incompatible changes.
When updating the playbook, refer to the changelog to catch up with what's new.
🆘 Support
Matrix room: #matrix-docker-ansible-deploy:devture.com
IRC channel:
#matrix-docker-ansible-deployon the Libera Chat IRC network (irc.libera.chat:6697)GitHub issues: spantaleev/matrix-docker-ansible-deploy/issues
🌐 Translation
See the i18n/README.md file for more information about translation.
Translations are still work in progress.
🤝 Related
You may also be interested in mash-playbook - another Ansible playbook for self-hosting non-Matrix services (see its List of supported services).
mash-playbook also makes use of Traefik as its reverse-proxy, so with minor interoperability adjustments, you can make matrix-docker-ansible-deploy and mash-playbook co-exist and host Matrix and non-Matrix services on the same server.
File: docs/alternative-architectures.md
Alternative architectures
As stated in the Prerequisites, currently only amd64 (x86_64) is fully supported.
The playbook automatically determines the target server's architecture (the matrix_architecture variable) to be one of the following:
amd64(x86_64)arm32arm64
Some tools and container images can be built on the host or other measures can be used to install on that architecture.
Implementation details
For amd64, prebuilt container images (see the container images we use) are used for all components (except Hydrogen, which goes through self-building).
For other architecture (arm64, arm32), components which have a prebuilt image make use of it. If the component is not available for the specific architecture, self-building will be used. Not all components support self-building though, so your mileage may vary.
File: docs/ansible.md
Using Ansible for the playbook
This playbook is meant to be run using Ansible.
Ansible typically runs on your local computer and carries out tasks on a remote server. If your local computer cannot run Ansible, you can also run Ansible on some server somewhere (including the server you wish to install to).
Supported Ansible versions
To manually check which version of Ansible you're on, run: ansible --version.
For the best experience, we recommend getting the latest version of Ansible available.
We're not sure what's the minimum version of Ansible that can run this playbook successfully. The lowest version that we suspect (on 2025-09-03) to be working fine is: ansible-core (2.15.1).
If your distro ships with an Ansible version older than this, you may run into issues. Consider Upgrading Ansible or using Ansible via Docker.
[!WARNING]
One reason for the version requirement being as such is that the playbook by default installs Docker for you using this Docker role which has a hard requirement on Ansible v2.15.1. If you install Docker yourself another way, you can tell the playbook to skip running this role (by addingmatrix_playbook_docker_installation_enabled: falseto yourvars.ymlconfiguration). It may then be possible to get the playbook running on an older version of Ansible. Still, this is a complication and your mileage may vary. We recommend upgrading Ansible instead of going into uncharted territory.
Upgrading Ansible
Depending on your distribution, you may be able to upgrade Ansible in a few different ways:
by using an additional repository (PPA, etc.), which provides newer Ansible versions. See instructions for CentOS, Debian, or Ubuntu on the Ansible website.
by removing the Ansible package (
yum remove ansibleorapt-get remove ansible) and installing via pip (pip install ansible).
If using the pip method, do note that the ansible-playbook binary may not be on the $PATH (https://linuxconfig.org/linux-path-environment-variable), but in some more special location like /usr/local/bin/ansible-playbook. You may need to invoke it using the full path.
Note: Both of the above methods are a bad way to run system software such as Ansible. If you find yourself needing to resort to such hacks, please consider reporting a bug to your distribution and/or switching to a sane distribution, which provides up-to-date software.
SSH host key and passphrase prompts
If Ansible fails with Host key verification failed (or a similar Data could not be sent to remote host error) without asking you to confirm the SSH host key of your server, you're likely on Ansible 2.21 or later.
Since Ansible 2.21, forked workers call setsid() and thus lose the controlling terminal. SSH cannot open /dev/tty anymore, so it can no longer ask you to confirm an unknown host key or prompt you for the passphrase of an SSH key.
The simplest fix is to connect to the server once (e.g. ssh [email protected]) and confirm the host key. Ansible runs after that will find it in your known_hosts file.
Alternatively, run Ansible with the ANSIBLE_WORKER_SESSION_ISOLATION=False environment variable to get these prompts back (e.g. ANSIBLE_WORKER_SESSION_ISOLATION=False just install-all).
Note: this does not affect you if you're using Ansible via Docker, because our Docker image already disables session isolation for you.
Using Ansible via Docker
Alternatively, you can run Ansible inside a Docker container (powered by the ghcr.io/devture/ansible Docker image).
This ensures that:
- you're using a very recent Ansible version, which is less likely to be incompatible with the playbook
- you also get access to the agru tool for quicker Ansible role installation (when running
just roles) compared toansible-galaxy
You can either run Ansible in a container on the Matrix server itself or run Ansible in a container on another computer (not the Matrix server).
💡 If you use Visual Studio Code or GitHub Codespaces, the playbook also ships a dev container configuration (see the .devcontainer/ directory) based on this same Ansible Docker image, which can prepare such a containerized Ansible environment for you automatically.
Running Ansible in a container on the Matrix server itself
To run Ansible in a (Docker) container on the Matrix server itself, you need to have a working Docker installation. Docker is normally installed by the playbook, so this may be a bit of a chicken and egg problem. To solve it:
- you either need to install Docker manually first. Follow the upstream instructions for your distribution and consider setting
matrix_playbook_docker_installation_enabled: falsein yourvars.ymlfile, to prevent the playbook from installing Docker - or you need to run the playbook in another way (e.g. Running Ansible in a container on another computer (not the Matrix server)) at least the first time around
Once you have a working Docker installation on the server, clone the playbook somewhere on the server and configure it as per usual (inventory/hosts, inventory/host_vars/…, etc.), as described in configuring the playbook.
You would then need to add ansible_connection=community.docker.nsenter to the host line in inventory/hosts. This tells Ansible to connect to the "remote" machine by switching Linux namespaces with nsenter, instead of using SSH.
Alternatively, you can leave your inventory/hosts as is and specify the connection type in each ansible-playbook call you do later, like this: just install-all --connection=community.docker.nsenter (or ansible-playbook --connection=community.docker.nsenter …).
Run this from the playbook's directory:
docker run \
-it \
--rm \
--privileged \
--pid=host \
-w /work \
--mount type=bind,src=`pwd`,dst=/work \
--entrypoint=/bin/sh \
ghcr.io/devture/ansible:14.0.0-r0-2Once you execute the above command, you'll be dropped into a /work directory inside a Docker container. The /work directory contains the playbook's code.
First, consider running git config --global --add safe.directory /work to resolve directory ownership issues.
Finally, you can execute just or ansible-playbook … (e.g. ansible-playbook --connection=community.docker.nsenter …) commands as per normal now.
Running Ansible in a container on another computer (not the Matrix server)
Run this from the playbook's directory:
docker run \
-it \
--rm \
-w /work \
--mount type=bind,src=`pwd`,dst=/work \
--mount type=bind,src=$HOME/.ssh/id_ed25519,dst=/root/.ssh/id_ed25519,ro \
--entrypoint=/bin/sh \
ghcr.io/devture/ansible:14.0.0-r0-2The above command tries to mount an SSH key ($HOME/.ssh/id_ed25519) into the container (at /root/.ssh/id_ed25519). If your SSH key is at a different path (not in $HOME/.ssh/id_ed25519), adjust that part.
Once you execute the above command, you'll be dropped into a /work directory inside a Docker container. The /work directory contains the playbook's code.
First, consider running git config --global --add safe.directory /work to resolve directory ownership issues.
Finally, you execute just or ansible-playbook … commands as per normal now.
If you don't use SSH keys for authentication
If you don't use SSH keys for authentication, simply remove that whole line (--mount type=bind,src$HOME/.ssh/id_ed25519,dst=/root/.ssh/id_ed25519,ro).
To authenticate at your server using a password, you need to add a package. So, when you are in the shell of the ansible docker container (the previously used docker run -it … command), run:
apk add sshpassThen, to be asked for the password whenever running an ansible-playbook command add --ask-pass to the arguments of the command.
Resolve directory ownership issues
Because you're root in the container running Ansible and this likely differs from the owner (your regular user account) of the playbook directory outside of the container, certain playbook features which use git locally may report warnings such as:
fatal: unsafe repository ('/work' is owned by someone else)
To add an exception for this directory, call:
git config --global --add safe.directory /work
These errors can be resolved by making git trust the playbook directory by running git config --global --add safe.directory /work
File: docs/configuring-captcha.md
(Adapted from the upstream project)
Overview
Captcha can be enabled for this home server. This file explains how to do that.
The captcha mechanism used is Google's ReCaptcha. This requires API keys from Google. If your homeserver is Dendrite then hCapcha can be used instead.
If you are using Matrix Authentication Service, captcha is configured there instead (it handles registration), and Cloudflare Turnstile is supported as well. See Matrix Authentication Service below.
ReCaptcha
Getting keys
Requires a site/secret key pair from:
http://www.google.com/recaptcha/admin
Must be a reCAPTCHA v2 key using the "I'm not a robot" Checkbox option
Setting ReCaptcha keys
Once registered as above, add the following configuration to your inventory/host_vars/matrix.example.com/vars.yml file:
# for Synapse
matrix_synapse_enable_registration_captcha: true
matrix_synapse_recaptcha_public_key: 'YOUR_SITE_KEY'
matrix_synapse_recaptcha_private_key: 'YOUR_SECRET_KEY'
# for Dendrite
matrix_dendrite_client_api_enable_registration_captcha: true
matrix_dendrite_client_api_recaptcha_public_key: 'YOUR_SITE_KEY'
matrix_dendrite_client_api_recaptcha_private_key: 'YOUR_SECRET_KEY'hCaptcha
Getting keys
Requires a site/secret key pair from:
https://dashboard.hcaptcha.com/sites/new
Setting hCaptcha keys
matrix_dendrite_client_api_enable_registration_captcha: true
matrix_dendrite_client_api_recaptcha_public_key: 'YOUR_SITE_KEY'
matrix_dendrite_client_api_recaptcha_private_key: 'YOUR_SECRET_KEY'
matrix_dendrite_client_api_recaptcha_siteverify_api: 'https://hcaptcha.com/siteverify'
matrix_dendrite_client_api_recaptcha_api_js_url: 'https://js.hcaptcha.com/1/api.js'
matrix_dendrite_client_api_recaptcha_form_field: 'h-captcha-response'
matrix_dendrite_client_api_recaptcha_sitekey_class: 'h-captcha'Matrix Authentication Service
When Matrix Authentication Service is enabled, registration and other account operations are handled by it, so captcha protection is configured there (the Synapse and Dendrite settings above do not apply).
Matrix Authentication Service supports ReCaptcha v2, Cloudflare Turnstile and hCaptcha. Obtain a site/secret key pair from your chosen service, then add the following configuration to your inventory/host_vars/matrix.example.com/vars.yml file:
# Valid values: recaptcha_v2, cloudflare_turnstile, hcaptcha
matrix_authentication_service_config_captcha_service: recaptcha_v2
matrix_authentication_service_config_captcha_site_key: 'YOUR_SITE_KEY'
matrix_authentication_service_config_captcha_secret_key: 'YOUR_SECRET_KEY'