Browse Source

Merge pull request #1 from spantaleev/master

Get changes from upstream
pull/5582/head
Jean-Benoît Grimaldi 2 weeks ago
committed by GitHub
parent
commit
f1796258c1
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
100 changed files with 3806 additions and 1063 deletions
  1. +1
    -1
      .codespellrc
  2. +13
    -0
      .devcontainer/Dockerfile
  3. +27
    -0
      .devcontainer/devcontainer.json
  4. +3
    -0
      .devcontainer/devcontainer.json.license
  5. +0
    -11
      .github/dependabot.yaml
  6. +201
    -31
      .github/renovate.json
  7. +1
    -1
      .github/workflows/close-stale-issues.yml
  8. +48
    -0
      .github/workflows/i18n.yml
  9. +1
    -1
      .github/workflows/lock-threads.yml
  10. +2
    -2
      .github/workflows/matrix.yml
  11. +161
    -0
      .github/workflows/molecule.yml
  12. +65
    -0
      .github/workflows/renovate-smoke-test.yml
  13. +155
    -0
      .github/workflows/renovate.yml
  14. +6
    -12
      .github/workflows/update-translations.yml
  15. +8
    -2
      .pre-commit-config.yaml
  16. +11
    -0
      .yamllint
  17. +41
    -0
      AGENTS.md
  18. +444
    -0
      CHANGELOG.md
  19. +4
    -1
      Makefile
  20. +12
    -9
      README.md
  21. +120
    -0
      bin/add-inventory-host.sh
  22. +119
    -0
      bin/check-molecule-automerge-list.py
  23. +3
    -0
      bin/check-molecule-automerge-list.py.license
  24. +90
    -0
      bin/molecule-clean.sh
  25. +3
    -0
      bin/molecule-clean.sh.license
  26. +98
    -0
      bin/molecule.sh
  27. +3
    -0
      bin/molecule.sh.license
  28. +0
    -54
      bin/rebuild-mautrix-meta-instagram.sh
  29. +21
    -0
      collections/requirements.yml
  30. +4
    -0
      docs/README.md
  31. +16
    -2
      docs/ansible.md
  32. +15
    -0
      docs/configuring-captcha.md
  33. +1
    -1
      docs/configuring-ipv6.md
  34. +50
    -15
      docs/configuring-playbook-appservice-draupnir-for-all.md
  35. +40
    -4
      docs/configuring-playbook-bot-baibot.md
  36. +1
    -1
      docs/configuring-playbook-bot-buscarron.md
  37. +70
    -12
      docs/configuring-playbook-bot-draupnir.md
  38. +11
    -252
      docs/configuring-playbook-bot-go-neb.md
  39. +1
    -1
      docs/configuring-playbook-bot-honoroit.md
  40. +19
    -88
      docs/configuring-playbook-bot-matrix-registration-bot.md
  41. +1
    -1
      docs/configuring-playbook-bot-matrix-reminder-bot.md
  42. +1
    -1
      docs/configuring-playbook-bot-maubot.md
  43. +409
    -0
      docs/configuring-playbook-bot-meowlnir.md
  44. +4
    -2
      docs/configuring-playbook-bot-mjolnir.md
  45. +8
    -8
      docs/configuring-playbook-bridge-appservice-discord.md
  46. +4
    -4
      docs/configuring-playbook-bridge-appservice-irc.md
  47. +9
    -58
      docs/configuring-playbook-bridge-appservice-kakaotalk.md
  48. +101
    -0
      docs/configuring-playbook-bridge-beeper-line.md
  49. +5
    -3
      docs/configuring-playbook-bridge-beeper-linkedin.md
  50. +6
    -6
      docs/configuring-playbook-bridge-heisenbridge.md
  51. +28
    -25
      docs/configuring-playbook-bridge-hookshot.md
  52. +10
    -10
      docs/configuring-playbook-bridge-matrix-bridge-sms.md
  53. +2
    -2
      docs/configuring-playbook-bridge-mautrix-bluesky.md
  54. +43
    -14
      docs/configuring-playbook-bridge-mautrix-bridges.md
  55. +2
    -2
      docs/configuring-playbook-bridge-mautrix-discord.md
  56. +2
    -2
      docs/configuring-playbook-bridge-mautrix-gmessages.md
  57. +2
    -2
      docs/configuring-playbook-bridge-mautrix-googlechat.md
  58. +73
    -0
      docs/configuring-playbook-bridge-mautrix-gvoice.md
  59. +112
    -0
      docs/configuring-playbook-bridge-mautrix-linkedin.md
  60. +4
    -4
      docs/configuring-playbook-bridge-mautrix-meta-instagram.md
  61. +4
    -4
      docs/configuring-playbook-bridge-mautrix-meta-messenger.md
  62. +3
    -3
      docs/configuring-playbook-bridge-mautrix-signal.md
  63. +2
    -2
      docs/configuring-playbook-bridge-mautrix-slack.md
  64. +13
    -39
      docs/configuring-playbook-bridge-mautrix-telegram.md
  65. +2
    -2
      docs/configuring-playbook-bridge-mautrix-twitter.md
  66. +2
    -2
      docs/configuring-playbook-bridge-mautrix-whatsapp.md
  67. +8
    -8
      docs/configuring-playbook-bridge-mautrix-wsproxy.md
  68. +95
    -0
      docs/configuring-playbook-bridge-meshtastic-relay.md
  69. +1
    -1
      docs/configuring-playbook-bridge-mx-puppet-groupme.md
  70. +1
    -1
      docs/configuring-playbook-bridge-mx-puppet-steam.md
  71. +7
    -7
      docs/configuring-playbook-bridge-postmoogle.md
  72. +100
    -0
      docs/configuring-playbook-bridge-rustpush.md
  73. +4
    -1
      docs/configuring-playbook-bridge-steam.md
  74. +3
    -3
      docs/configuring-playbook-bridge-wechat.md
  75. +93
    -0
      docs/configuring-playbook-client-commet.md
  76. +1
    -1
      docs/configuring-playbook-client-sable.md
  77. +6
    -2
      docs/configuring-playbook-conduwuit.md
  78. +7
    -0
      docs/configuring-playbook-continuwuity.md
  79. +1
    -1
      docs/configuring-playbook-element-admin.md
  80. +1
    -1
      docs/configuring-playbook-email.md
  81. +6
    -4
      docs/configuring-playbook-federation.md
  82. +0
    -47
      docs/configuring-playbook-jwt-service.md
  83. +101
    -0
      docs/configuring-playbook-ketesa.md
  84. +1
    -7
      docs/configuring-playbook-ldap-auth.md
  85. +6
    -0
      docs/configuring-playbook-livekit-server.md
  86. +3
    -1
      docs/configuring-playbook-matrix-authentication-service.md
  87. +20
    -57
      docs/configuring-playbook-matrix-ldap-registration-proxy.md
  88. +22
    -101
      docs/configuring-playbook-matrix-registration.md
  89. +6
    -0
      docs/configuring-playbook-matrix-rtc.md
  90. +3
    -0
      docs/configuring-playbook-prometheus-grafana.md
  91. +0
    -93
      docs/configuring-playbook-synapse-admin.md
  92. +24
    -2
      docs/configuring-playbook-synapse-usage-exporter.md
  93. +3
    -3
      docs/configuring-playbook-synapse.md
  94. +179
    -0
      docs/configuring-playbook-synology.md
  95. +18
    -3
      docs/configuring-playbook-traefik.md
  96. +269
    -0
      docs/configuring-playbook-tuwunel.md
  97. +28
    -12
      docs/configuring-playbook.md
  98. +28
    -1
      docs/configuring-well-known.md
  99. +14
    -9
      docs/container-images.md
  100. +6
    -0
      docs/faq.md

+ 1
- 1
.codespellrc View File

@@ -1,2 +1,2 @@
[codespell]
ignore-words-list = aNULL,brose,doub,Udo,re-use,re-used,registr,shema,commet,Commet
ignore-words-list = aNULL,brose,doub,Udo,re-use,re-used,registr,shema,commet,Commet,Bloks

+ 13
- 0
.devcontainer/Dockerfile View File

@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2025 Jonah Aragon
#
# SPDX-License-Identifier: AGPL-3.0-or-later

FROM ghcr.io/devture/ansible:14.0.0-r0-3

# Install additional packages
RUN apk add --no-cache \
pwgen

# Preserve command history across container restarts
RUN SNIPPET="export HISTFILE=/commandhistory/.ash_history" \
&& echo "$SNIPPET" >> "/root/.profile"

+ 27
- 0
.devcontainer/devcontainer.json View File

@@ -0,0 +1,27 @@
{
"name": "matrix-docker-ansible-deploy",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"postCreateCommand": {
"Fix Volume Permissions": "chown -R $(whoami): /commandhistory"
},
"mounts": [
{
"source": "matrix-docker-ansible-deploy-bashhistory",
"target": "/commandhistory",
"type": "volume"
}
],
"customizations": {
"vscode": {
"extensions": [
"EditorConfig.EditorConfig",
"redhat.ansible",
"redhat.vscode-yaml",
"ms-python.python"
]
}
}
}

+ 3
- 0
.devcontainer/devcontainer.json.license View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2025 Jonah Aragon

SPDX-License-Identifier: AGPL-3.0-or-later

+ 0
- 11
.github/dependabot.yaml View File

@@ -1,11 +0,0 @@
# SPDX-FileCopyrightText: 2022 Marko Weltzer
#
# SPDX-License-Identifier: AGPL-3.0-or-later

---
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily

+ 201
- 31
.github/renovate.json View File

@@ -1,33 +1,203 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"labels": [
"dependencies"
],
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": [
"/defaults/main.yml$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-z-.]+?) depName=(?<depName>[^\\s]+?)(?: (?:lookupName|packageName)=(?<packageName>[^\\s]+?))?(?: versioning=(?<versioning>[a-z-0-9]+?))?\\s+[A-Za-z0-9_]+?(?:_version|_tag)\\s*:\\s*[\"']?(?<currentValue>.+?)[\"']?\\s"
]
}
],
"packageRules": [
{
"ignoreUnstable": false,
"versioning": "loose",
"matchSourceUrls": [
"https://github.com/devture/com.devture.ansible.role{/,}**",
"https://github.com/mother-of-all-self-hosting{/,}**"
]
}
],
"pre-commit": {
"enabled": true
}
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
"helpers:pinGitHubActionDigests"
],
"labels": [
"dependencies"
],
"branchConcurrentLimit": 5,
"prConcurrentLimit": 3,
"hostRules": [
{
"matchHost": "https://mau.dev",
"concurrentRequestLimit": 2,
"maxRequestsPerSecond": 2
},
{
"matchHost": "https://dock.mau.dev",
"concurrentRequestLimit": 4,
"maxRequestsPerSecond": 4
}
],
"customManagers": [
{
"customType": "regex",
"managerFilePatterns": [
"/defaults/main.yml$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-z-.]+?) depName=(?<depName>[^\\s]+?)(?: (?:lookupName|packageName)=(?<packageName>[^\\s]+?))?(?: versioning=(?<versioning>[a-z-0-9]+?))?\\s+[A-Za-z0-9_]+?(?:_version|_tag)\\s*:\\s*[\"']?(?<currentValue>.+?)[\"']?\\s"
]
},
{
"description": "Helper container images used by the Molecule scenarios. They are pinned once in molecule-shared/vars.yml rather than inline in each role's verify.yml, so this manager keeps that single pin current.",
"customType": "regex",
"managerFilePatterns": [
"/^molecule-shared/vars\\.yml$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-z-.]+?) depName=(?<depName>[^\\s]+?)\\s+[A-Za-z0-9_]+?\\s*:\\s*[\"'][^:]+:(?<currentValue>[^\"']+)[\"']"
]
},
{
"customType": "regex",
"description": "Update the self-hosted Renovate runner version",
"managerFilePatterns": [
"/^\\.github\\/workflows\\/renovate\\.yml$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>\\S+) depName=(?<depName>\\S+) packageName=(?<packageName>\\S+)\\s+MATRIX_RENOVATE_VERSION: '(?<currentValue>[^']+)'"
]
}
],
"packageRules": [
{
"ignoreUnstable": false,
"versioning": "loose",
"matchSourceUrls": [
"https://github.com/devture/com.devture.ansible.role{/,}**",
"https://github.com/mother-of-all-self-hosting{/,}**"
]
},
{
"description": "mautrix images are dual-tagged (v0.YYMM.PATCH and vYY.MM[.PATCH]). Stick to the v0 scheme: it matches the git tags (needed for self-building) and has a consistent number of components (the calver tags do not, which makes Renovate stop offering updates).",
"matchPackageNames": [
"dock.mau.dev/mautrix/**"
],
"allowedVersions": "/^v0\\./"
},
{
"description": "Automerge version bumps of roles maintained in the MASH organization and of devture roles (via branch push - no PR)",
"matchManagers": [
"ansible-galaxy"
],
"matchSourceUrls": [
"https://github.com/devture/com.devture.ansible.role{/,}**",
"https://github.com/mother-of-all-self-hosting{/,}**"
],
"automerge": true,
"automergeType": "branch"
},
{
"description": "Housekeeping updates merge via branch push (no PR, no email); a failure on the branch still surfaces as a PR. i18n/requirements.txt bumps are exercised by the Matrix i18n workflow before merging.",
"matchFileNames": [
".github/workflows/close-stale-issues.yml",
".github/workflows/i18n.yml",
".github/workflows/lock-threads.yml",
".github/workflows/matrix.yml",
".github/workflows/renovate-smoke-test.yml",
".github/workflows/renovate.yml",
".github/workflows/update-translations.yml",
"flake.nix",
"flake.lock",
"i18n/requirements.txt",
"mise.toml"
],
"automerge": true,
"automergeType": "branch"
},
{
"description": "Automerge updates of the self-hosted Renovate runner (via branch push - no PR)",
"matchManagers": [
"custom.regex"
],
"matchDepNames": [
"matrix-renovate-runner"
],
"automerge": true,
"automergeType": "branch"
},
{
"description": "Molecule's own dependencies merge via branch push (no PR, no email). Anything under molecule-shared/ - the helper container images, Postgres, and the Python pins - triggers the Molecule workflow, and a change to a shared file makes it run every scenario, so an update only merges once the whole suite has passed on it. A failure surfaces as a PR instead. This is how a new Postgres major reaches us: the bump runs every scenario against it before anything is merged.",
"matchFileNames": [
"molecule-shared/**",
".github/workflows/molecule.yml"
],
"automerge": true,
"automergeType": "branch"
},
{
"description": "Automerge patch bumps of components whose role has a Molecule scenario (via branch push - no PR). A bump touches that role's defaults/main.yml, which makes the Molecule workflow run that role's scenario, so the update only merges once the component has been started on the configuration the role renders. Patch is the baseline for every covered role; explicitly approved roles may also appear in the narrower minor rule below. Keep this list in step with the roles that have a scenario - bin/check-molecule-automerge-list.py (patch rule) enforces that.",
"matchFileNames": [
"roles/custom/matrix-alertmanager-receiver/defaults/main.yml",
"roles/custom/matrix-authentication-service/defaults/main.yml",
"roles/custom/matrix-bot-baibot/defaults/main.yml",
"roles/custom/matrix-bot-draupnir/defaults/main.yml",
"roles/custom/matrix-bot-honoroit/defaults/main.yml",
"roles/custom/matrix-bot-maubot/defaults/main.yml",
"roles/custom/matrix-bot-matrix-reminder-bot/defaults/main.yml",
"roles/custom/matrix-bot-meowlnir/defaults/main.yml",
"roles/custom/matrix-bridge-beeper-line/defaults/main.yml",
"roles/custom/matrix-bridge-heisenbridge/defaults/main.yml",
"roles/custom/matrix-bridge-hookshot/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-bluesky/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-discord/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-gmessages/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-googlechat/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-gvoice/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-linkedin/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-meta-instagram/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-meta-messenger/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-signal/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-slack/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-telegram/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-twitter/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-whatsapp/defaults/main.yml",
"roles/custom/matrix-bridge-postmoogle/defaults/main.yml",
"roles/custom/matrix-bridge-steam/defaults/main.yml",
"roles/custom/matrix-client-element/defaults/main.yml",
"roles/custom/matrix-client-fluffychat/defaults/main.yml",
"roles/custom/matrix-element-admin/defaults/main.yml",
"roles/custom/matrix-element-call/defaults/main.yml",
"roles/custom/matrix-ketesa/defaults/main.yml",
"roles/custom/matrix-livekit-jwt-service/defaults/main.yml",
"roles/custom/matrix-static-files/defaults/main.yml",
"roles/custom/matrix-synapse/defaults/main.yml",
"roles/custom/matrix-synapse-auto-compressor/defaults/main.yml"
],
"matchUpdateTypes": [
"patch"
],
"automerge": true,
"automergeType": "branch"
},
{
"description": "Automerge minor bumps of explicitly approved components with a weight-bearing Molecule scenario (via branch push - no PR). This list is intentionally narrower than the patch rule: the scenario must exercise enough real behavior to be a useful compatibility gate across a minor release. A failure surfaces as a PR instead. Keep every entry backed by a scenario and the patch rule - bin/check-molecule-automerge-list.py (minor rule) enforces that.",
"matchFileNames": [
"roles/custom/matrix-authentication-service/defaults/main.yml",
"roles/custom/matrix-bot-honoroit/defaults/main.yml",
"roles/custom/matrix-bot-meowlnir/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-bluesky/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-gmessages/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-googlechat/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-gvoice/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-linkedin/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-slack/defaults/main.yml",
"roles/custom/matrix-bridge-mautrix-twitter/defaults/main.yml",
"roles/custom/matrix-bridge-steam/defaults/main.yml",
"roles/custom/matrix-client-fluffychat/defaults/main.yml",
"roles/custom/matrix-element-admin/defaults/main.yml",
"roles/custom/matrix-element-call/defaults/main.yml",
"roles/custom/matrix-livekit-jwt-service/defaults/main.yml",
"roles/custom/matrix-static-files/defaults/main.yml",
"roles/custom/matrix-synapse-auto-compressor/defaults/main.yml"
],
"matchUpdateTypes": [
"minor"
],
"automerge": true,
"automergeType": "branch"
}
],
"pre-commit": {
"enabled": true
},
"nix": {
"enabled": true,
"lockFileMaintenance": {
"enabled": true
}
}
}

+ 1
- 1
.github/workflows/close-stale-issues.yml View File

@@ -19,7 +19,7 @@ jobs:
if: github.repository == 'spantaleev/matrix-docker-ansible-deploy'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11
with:
######################################################################
# Issues/PRs


+ 48
- 0
.github/workflows/i18n.yml View File

@@ -0,0 +1,48 @@
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later

---
name: Matrix i18n

# Exercises the translation toolchain whenever something under i18n/ changes,
# so that a dependency bump which breaks Sphinx/Babel fails here - before it
# gets merged - rather than in the next scheduled translations run.
on: # yamllint disable-line rule:truthy
push:
paths:
- "i18n/**"
- ".github/workflows/i18n.yml"
pull_request:
paths:
- "i18n/**"
- ".github/workflows/i18n.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
extract-translation-templates:
name: Extract translation templates
runs-on: ubuntu-24.04

# Same-repository pull requests already run via the push event;
# run pull_request jobs only for pull requests from forks.
if: >-
github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name != github.repository

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.14'

- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1

- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4

- name: Extract translation catalog templates (POT) files
run: just --justfile i18n/justfile extract-translation-templates

+ 1
- 1
.github/workflows/lock-threads.yml View File

@@ -23,7 +23,7 @@ jobs:
if: github.repository == 'spantaleev/matrix-docker-ansible-deploy'
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v6
- uses: dessant/lock-threads@89ae32b08ed1a541efecbab17912962a5e38981c # v6
with:
add-issue-labels: 'outdated'
process-only: 'issues, prs'

+ 2
- 2
.github/workflows/matrix.yml View File

@@ -26,10 +26,10 @@ jobs:
run: pacman -Sy --noconfirm git

- name: Check out
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Restore prek cache
uses: actions/cache@v5
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: var/prek
key: arch-prek-v1-${{ hashFiles('.pre-commit-config.yaml') }}


+ 161
- 0
.github/workflows/molecule.yml View File

@@ -0,0 +1,161 @@
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later

---
name: Molecule

# Unlike the MASH role repositories, where one repository holds one role, every
# role here lives in the same repository. Running every scenario on every push
# would be unaffordable, so a first job works out which roles the push actually
# touched and the matrix is built from that. A push that changes documentation,
# or a role with no scenario yet, runs nothing at all.
on: # yamllint disable-line rule:truthy
push:
paths:
- "roles/custom/**"
- "molecule-shared/**"
- ".github/workflows/molecule.yml"
pull_request:
paths:
- "roles/custom/**"
- "molecule-shared/**"
- ".github/workflows/molecule.yml"
workflow_dispatch:
inputs:
role:
description: "Single role to test (directory name under roles/custom), or empty for all roles that have a scenario"
required: false
type: string

permissions:
contents: read

jobs:
detect:
name: Work out which roles to test
runs-on: ubuntu-latest

# Same rule as the MASH repositories: a pull request from a branch of this
# repository would otherwise run everything twice, once for the push and
# once for the pull request.
if: >-
github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name != github.repository

outputs:
roles: ${{ steps.detect.outputs.roles }}

steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0

- name: Detect roles with a Molecule scenario that this change touches
id: detect
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
BEFORE_SHA: ${{ github.event.before }}
INPUT_ROLE: ${{ inputs.role }}
run: |
set -euo pipefail

have_scenario() {
[ -f "roles/custom/$1/molecule/default/molecule.yml" ]
}

# An explicit request through workflow_dispatch wins over detection.
if [ -n "${INPUT_ROLE}" ]; then
if have_scenario "${INPUT_ROLE}"; then
printf 'roles=["%s"]\n' "${INPUT_ROLE}" >> "$GITHUB_OUTPUT"
else
echo "No scenario at roles/custom/${INPUT_ROLE}/molecule/default" >&2
exit 1
fi
exit 0
fi

# A hand-triggered run with no role named, and any run where the diff
# base is unusable (a new branch, a force push, the very first commit),
# falls back to every role that has a scenario. That is the safe
# direction to fail in: too much testing rather than too little.
base=""
case "${EVENT_NAME}" in
pull_request) base="${BASE_SHA}" ;;
push)
if [ -n "${BEFORE_SHA}" ] && [ "${BEFORE_SHA}" != "0000000000000000000000000000000000000000" ] \
&& git cat-file -e "${BEFORE_SHA}^{commit}" 2>/dev/null; then
base="${BEFORE_SHA}"
fi
;;
esac

# molecule-shared/ is used by every scenario, so a change there means
# every role has to run, not just the ones whose own files moved.
shared_changed=""
if [ -n "${base}" ]; then
shared_changed="$(git diff --name-only "${base}" HEAD -- 'molecule-shared/*' '.github/workflows/molecule.yml' || true)"
fi

if [ -n "${base}" ] && [ -z "${shared_changed}" ]; then
changed="$(git diff --name-only "${base}" HEAD -- 'roles/custom/*' || true)"
candidates="$(printf '%s\n' "${changed}" | awk -F/ 'NF>2 {print $3}' | sort -u)"
echo "Changed roles: ${candidates:-none}"
else
if [ -n "${shared_changed}" ]; then
echo "Shared Molecule files changed; considering every role"
fi
candidates="$(find roles/custom -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort)"
fi

selected=""
for role in ${candidates}; do
if have_scenario "${role}"; then
selected="${selected} ${role}"
fi
done

if [ -z "${selected}" ]; then
echo "Nothing to test"
echo 'roles=[]' >> "$GITHUB_OUTPUT"
exit 0
fi

echo "Testing:${selected}"
json="$(printf '%s\n' ${selected} | jq -R . | jq -c -s .)"
echo "roles=${json}" >> "$GITHUB_OUTPUT"

molecule:
name: "Molecule: ${{ matrix.role }}"
runs-on: ubuntu-latest

needs: detect
if: needs.detect.outputs.roles != '[]'

strategy:
matrix:
role: ${{ fromJson(needs.detect.outputs.roles) }}
fail-fast: false

env:
MOLECULE_DISTRO: ubuntu2604
PY_COLORS: "1"
ANSIBLE_FORCE_COLOR: "1"

steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: "3.x"

- name: Install test dependencies
run: python3 -m pip install -r molecule-shared/requirements.txt

- name: Run Molecule
working-directory: roles/custom/${{ matrix.role }}
run: molecule test --scenario-name default

+ 65
- 0
.github/workflows/renovate-smoke-test.yml View File

@@ -0,0 +1,65 @@
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later

---
name: Renovate smoke test

on: # yamllint disable-line rule:truthy
push:
paths:
- '.github/renovate.json'
- '.github/workflows/renovate-smoke-test.yml'
- '.github/workflows/renovate.yml'
pull_request:
paths:
- '.github/renovate.json'
- '.github/workflows/renovate-smoke-test.yml'
- '.github/workflows/renovate.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
validate:
name: Validate config with the pinned Renovate image
runs-on: ubuntu-latest

# Same-repository pull requests already run via the push event;
# run pull_request jobs only for pull requests from forks.
if: >-
github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name != github.repository

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Resolve the pinned Renovate version
id: renovate_version
shell: bash
run: |
set -euo pipefail

mapfile -t versions < <(
sed -n "s/^ MATRIX_RENOVATE_VERSION: '\([^']*\)'$/\1/p" \
.github/workflows/renovate.yml
)

if (( ${#versions[@]} != 1 )) || [[ -z "${versions[0]}" ]]; then
echo 'Could not resolve exactly one pinned Renovate version' >&2
exit 1
fi

echo "version=${versions[0]}" >> "$GITHUB_OUTPUT"

- name: Validate the Renovate configuration
env:
RENOVATE_VERSION: ${{ steps.renovate_version.outputs.version }}
run: |
docker run --rm \
--volume "$GITHUB_WORKSPACE:/workspace:ro" \
--workdir /workspace \
--entrypoint renovate-config-validator \
"ghcr.io/renovatebot/renovate:$RENOVATE_VERSION" \
--strict

+ 155
- 0
.github/workflows/renovate.yml View File

@@ -0,0 +1,155 @@
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later

---
name: Renovate

on: # yamllint disable-line rule:truthy
schedule:
# Discover new updates hourly. Reactive runs below drain active updates.
- cron: '17 * * * *'
workflow_dispatch:
inputs:
dry_run:
description: 'Run without making changes'
required: false
default: true
type: boolean
log_level:
description: 'Renovate log level'
required: false
default: 'info'
type: choice
options:
- info
- debug
- trace
push:
branches: ['master']
workflow_run:
workflows: ['Matrix CI', 'Matrix i18n', 'Molecule', 'Renovate smoke test']
types: [completed]
branches: ['renovate/**']
issues:
types: [edited]

permissions:
contents: read

env:
# Mend-hosted Renovate must remain disabled while this automation is enabled.
# A manual dry-run remains available if this switch is disabled during migration.
MATRIX_RENOVATE_AUTOMATION_ENABLED: 'true'

# renovate: datasource=docker depName=matrix-renovate-runner packageName=ghcr.io/renovatebot/renovate
MATRIX_RENOVATE_VERSION: '44.64.0'

jobs:
preflight:
name: Decide whether to run Renovate
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.decision.outputs.should_run }}

steps:
- name: Evaluate trigger
id: decision
shell: bash
env:
GH_TOKEN: ${{ github.token }}
EVENT_NAME: ${{ github.event_name }}
EVENT_REF: ${{ github.ref }}
MANUAL_DRY_RUN: ${{ inputs.dry_run }}
WORKFLOW_RUN_CONCLUSION: ${{ github.event.workflow_run.conclusion }}
WORKFLOW_RUN_EVENT: ${{ github.event.workflow_run.event }}
ISSUE_TITLE: ${{ github.event.issue.title }}
SENDER_TYPE: ${{ github.event.sender.type }}
run: |
set -euo pipefail

should_run=false
reason='Automatic Renovate processing is disabled during migration'

if [[ "$EVENT_NAME" == 'workflow_dispatch' ]]; then
if [[ "$EVENT_REF" != 'refs/heads/master' ]]; then
reason='Manual runs must use the master branch'
elif [[ "$MANUAL_DRY_RUN" == 'true' || "$MATRIX_RENOVATE_AUTOMATION_ENABLED" == 'true' ]]; then
should_run=true
reason='Running manually requested Renovate job'
else
reason='Enable automatic processing before requesting a write run'
fi
elif [[ "$MATRIX_RENOVATE_AUTOMATION_ENABLED" == 'true' ]]; then
case "$EVENT_NAME" in
schedule)
should_run=true
reason='Running scheduled update discovery'
;;
workflow_run)
if [[ "$WORKFLOW_RUN_CONCLUSION" == 'success' && "$WORKFLOW_RUN_EVENT" == 'push' ]]; then
should_run=true
reason='A Renovate branch passed one of its status-check workflows'
else
reason='The completed check was not a successful Renovate branch push'
fi
;;
issues)
if [[ "$ISSUE_TITLE" == 'Dependency Dashboard' && "$SENDER_TYPE" == 'User' ]]; then
should_run=true
reason='A user edited the Dependency Dashboard'
else
reason='The issue edit was not a user editing the Dependency Dashboard'
fi
;;
push)
renovate_branch_count="$(
gh api \
"repos/$GITHUB_REPOSITORY/git/matching-refs/heads/renovate" \
--jq 'length'
)"
if (( renovate_branch_count > 0 )); then
should_run=true
reason="master changed while ${renovate_branch_count} Renovate branch(es) exist"
else
reason='master changed, but there are no Renovate branches to process'
fi
;;
esac
fi

echo "should_run=$should_run" >> "$GITHUB_OUTPUT"
echo "$reason"

renovate:
name: Renovate
needs: preflight
if: needs.preflight.outputs.should_run == 'true'
runs-on: ubuntu-latest
environment: main
concurrency:
group: renovate
cancel-in-progress: false

steps:
- name: Create Renovate App token
id: renovate_token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.GH_APP_RENOVATE_CLIENT_ID }}
private-key: ${{ secrets.GH_APP_RENOVATE_PRIVATE_KEY }}

- name: Run Renovate
uses: renovatebot/github-action@39b914146caeff8cd512e61c8992f1d5913af85c # v46.2.5
with:
token: ${{ steps.renovate_token.outputs.token }}
renovate-version: ${{ env.MATRIX_RENOVATE_VERSION }}
env:
LOG_LEVEL: ${{ inputs.log_level || 'info' }}
RENOVATE_DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run && 'full' || '' }}
# Permit the self-hosted App to adopt branches created by the Mend-hosted App.
RENOVATE_GIT_IGNORED_AUTHORS: '["29139614+renovate[bot]@users.noreply.github.com"]'
RENOVATE_IGNORE_PR_AUTHOR: 'true'
RENOVATE_PLATFORM: github
RENOVATE_PLATFORM_COMMIT: enabled
RENOVATE_REPOSITORIES: ${{ github.repository }}

+ 6
- 12
.github/workflows/update-translations.yml View File

@@ -6,13 +6,7 @@
name: Update translations

on: # yamllint disable-line rule:truthy
push:
branches:
- master
paths: # See include_patterns on conf.py
- 'docs/*.md'
- 'i18n/README.md'
- '*.md'
workflow_dispatch:

permissions:
contents: write
@@ -24,23 +18,23 @@ jobs:
name: Update translations
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- uses: actions/setup-python@v6
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: '3.14'

# Setting up recommended prerequisites
# See: i18n/README.md
- uses: astral-sh/setup-uv@v7
- uses: extractions/setup-just@v3
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
- uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4

# TODO: optimize when we start publishing translations and integrate a Weblate instance
- name: Update translation catalog templates (POT) files
run: just --justfile i18n/justfile extract-translation-templates

- name: Create Pull Request
uses: peter-evans/create-pull-request@v8.1.0
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> # Same as committer
body: This is an automatic pull request to update translation files.


+ 8
- 2
.pre-commit-config.yaml View File

@@ -15,7 +15,7 @@ repos:
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: https://github.com/codespell-project/codespell
rev: v2.4.2
rev: v2.4.3
hooks:
- id: codespell
args: ["--skip=*.po,*.pot,i18n/"]
@@ -24,7 +24,7 @@ repos:
hooks:
- id: reuse
- repo: https://github.com/ansible/ansible-lint
rev: v26.3.0
rev: v26.8.0
hooks:
- id: ansible-lint
files: '^roles/custom/'
@@ -38,3 +38,9 @@ repos:
language: script
files: '(examples/vars\.yml|roles/custom/matrix_playbook_migration/defaults/main\.yml)'
pass_filenames: false
- id: check-molecule-automerge-list
name: Check the Molecule automerge rules match the roles that have a scenario
entry: bin/check-molecule-automerge-list.py
language: script
files: '(\.github/renovate\.json|bin/check-molecule-automerge-list\.py|roles/custom/[^/]+/molecule/default/molecule\.yml)'
pass_filenames: false

+ 11
- 0
.yamllint View File

@@ -1,5 +1,16 @@
---
extends: default

# Keep this custom configuration compatible with ansible-lint's `yaml` rule.
# See https://docs.ansible.com/projects/lint/rules/yaml/#yamllint-configuration
rules:
braces:
min-spaces-inside: 0
max-spaces-inside: 1
comments:
min-spaces-from-content: 1
comments-indentation: false
line-length: disable
octal-values:
forbid-explicit-octal: true
forbid-implicit-octal: true

+ 41
- 0
AGENTS.md View File

@@ -0,0 +1,41 @@
<!--
SPDX-FileCopyrightText: 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Guidance for AI agents

This file gives AI coding agents the minimum context for working on this repository. Human contributors may find it a useful summary too.

## What this is

An Ansible playbook that installs and manages a Matrix homeserver and dozens of related services, each running as a Docker container wrapped in a systemd service.

## Layout

- `setup.yml`: the main playbook, listing all roles.
- `roles/custom/`: roles maintained in this repository.
- `roles/galaxy/`: external roles, downloaded according to `requirements.yml` via [agru](https://github.com/etkecc/agru) (preferred) or `ansible-galaxy`. Run `just roles` to install them (or `just update` to also pull the playbook itself). Editing these roles locally is fine while preparing or testing a fix, but the changes get wiped on the next roles update, so they must be synced back to the role's upstream repository, followed by a version pin update in `requirements.yml`.
- `group_vars/matrix_servers`: wires roles together (feeding one role's variables into another). Values a role can construct by itself belong in the role's `defaults/main.yml`, not here.
- `docs/`: user-facing documentation, one page per component.
- `molecule-shared/`: files shared by the roles' Molecule scenarios (Python and Ansible dependencies, pinned helper container images).
- `i18n/`: translation infrastructure. Do not edit locale files by hand; they are managed by automation.
- `CHANGELOG.md`: user-facing announcements, newest first.

## Conventions

Follow the [style guide for playbook developers](docs/style-guide.md). In particular:

- Variable prefixes match the role directory name.
- Playbook-extensible list variables use the `_auto` + `_custom` split; `_custom` is reserved for users.
- Renamed or removed variables get a validation entry, so stale user configuration produces an error instead of being silently ignored. Each role deprecates its own variables in its `validate_config.yml`; the `matrix_playbook_migration` role covers eliminated roles and very-early validation, and also gates breaking changes via `matrix_playbook_migration_expected_version` (see the style guide).
- Every file carries SPDX license headers ([REUSE](https://reuse.software/) specification).
- Roles may carry a Molecule scenario, proving the component starts and does not choke on the configuration the role rendered. Run one with `just molecule <role>` (no argument lists the roles that have one); CI runs only the scenarios of roles a push touched. See [Molecule testing for roles](docs/molecule-testing.md) before writing one - roles here need context a standalone role does not.
- New components must be registered in `setup.yml`, `group_vars/matrix_servers`, `docs/README.md`, `README.md`, `docs/container-images.md`, and get a `CHANGELOG.md` entry.

## Other notes

- Documentation examples use `example.com`, `@alice:example.com`, and the other placeholder values listed in the style guide.
- Write role tasks concurrency-safe: use `ansible.builtin.tempfile` for temporary files (removed in an `always` block), never fixed shared paths.
- One logical change per commit.

+ 444
- 0
CHANGELOG.md View File

@@ -1,3 +1,447 @@
# 2026-08-20

## MatrixRTC transports are advertised in the client well-known again

This only affects you if you have the [Matrix RTC stack](docs/configuring-playbook-matrix-rtc.md) or [Element Call](docs/configuring-playbook-element-call.md) enabled.

Yesterday's changelog entry announced that the `org.matrix.msc4143.rtc_foci` property was gone from the `/.well-known/matrix/client` file. That turned out to be premature and has been reverted, so the property is published again as it always was.

The property is indeed dropped from [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143) and [Element Call v0.24.0](https://github.com/element-hq/element-call/releases/tag/v0.24.0) no longer reads it, but Element Web (and likely other clients who move slowly or are otherwise outdated) does not ship that version of Element Call yet. Element Web v1.12.26 bundles Element Call v0.22.0, which still discovers your transport through the well-known property. It cannot use the homeserver's `/_matrix/client/unstable/org.matrix.msc4143/rtc/transports` API instead, because Element Call runs as a widget there and a widget holds no access token, while that API requires authentication. Newer Element Call versions ask their host client for the transports over the widget API ([MSC4515](https://github.com/matrix-org/matrix-spec-proposals/pull/4515)), which is what will eventually make the property unnecessary.

Dropping the property therefore broke Element Call for Element Web and Element Desktop users, with a `MISSING_MATRIX_RTC_TRANSPORT` error when starting a call. Re-running the playbook (`just install-all`) brings the property back and fixes calls.

If you worked around this by publishing the property yourself via `matrix_static_files_file_matrix_client_configuration_extension_json`, you can drop that from your `vars.yml` file now. The `matrix_static_files_file_matrix_client_property_org_matrix_msc4143_rtc_foci_custom` variable and its companions are back as well.

# 2026-08-13

## The homeserver root path redirects to clients other than Element Web

Visiting `https://matrix.example.com/` used to redirect you to [Element Web](docs/configuring-playbook-client-element-web.md), but only if Element Web was the client installed by the playbook. With any of the other web clients (Cinny, Commet, FluffyChat, Hydrogen, SchildiChat, Sable), you would land on a bare Synapse page.

The redirection now follows whichever of these clients you have enabled. When several are enabled, Element Web wins, followed by the others in the order that [`group_vars/matrix_servers`](group_vars/matrix_servers) lists them.

To send people somewhere else (or nowhere at all), define `matrix_playbook_public_client_root_redirection_url` in your `vars.yml` file. An empty value disables the redirection.

## Support for Meowlnir

The playbook can now install [Meowlnir](https://github.com/maunium/meowlnir), an opinionated Matrix moderation bot, optimized for Synapse.

Meowlnir joins [Draupnir](docs/configuring-playbook-bot-draupnir.md) and [Mjolnir](docs/configuring-playbook-bot-mjolnir.md) as a 3rd moderation option, speaking the same [policy list](https://the-draupnir-project.github.io/draupnir-documentation/concepts/policy-lists) protocol so that it can subscribe to the same community ban lists. Unlike the others, it can override individual policies coming from lists you do not control (by way of an unban policy in a list of your own which is ordered ahead of other policy lists).

You can run it alongside Draupnir while evaluating it — see the documentation for the caveats, the main one being that both want the [synapse-http-antispam](https://github.com/maunium/synapse-http-antispam) module, which only reports to a single consumer.

To get started, see the [Setting up Meowlnir](docs/configuring-playbook-bot-meowlnir.md) documentation page.


# 2026-08-06

## (Backward Compatibility Break) Jitsi no longer uses Colibri WebSockets

This only affects you if you have [Jitsi](docs/configuring-playbook-jitsi.md) enabled.

Jitsi has been updated to `stable-11146-1`, which [removes Colibri WebSocket support](https://github.com/jitsi/docker-jitsi-meet/pull/2285) in favour of SCTP data channels. The Jitsi Video Bridge no longer serves HTTP at all, so a few `jitsi_jvb_*` variables are gone. The playbook will tell you which ones, if your configuration still sets them.

If you run [additional JVBs on other hosts](https://github.com/mother-of-all-self-hosting/ansible-role-jitsi/blob/main/docs/configuring-jitsi.md#set-up-additional-jvbs-for-more-video-conferences-optional), the Traefik configuration which routed `/colibri-ws/<server-id>/` to them is now dead and can be removed. Nothing will warn you about that one, as it lives in a free-form `traefik_provider_configuration_extension_yaml` block.

# 2026-07-28

## (Backward Compatibility Break) ntfy users are now declared with hashed passwords

This only affects you if you have enabled authentication for [ntfy](docs/configuring-playbook-ntfy.md) via `ntfy_credentials`.

The ntfy role used to create users by invoking `ntfy user` commands against the running container. Since v2.14.0, ntfy can provision users and access-control entries from its own configuration file, so the role now does that instead. Besides being a lot simpler, this fixes passwords containing spaces never arriving intact.

Replace `ntfy_credentials` with `ntfy_auth_users_custom`, which takes bcrypt password hashes rather than plaintext passwords:

```yaml
ntfy_auth_users_custom:
- username: alice
password_hash: $2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C
role: admin
```

Generate a hash for each of your passwords by running the following command on any machine which has Docker installed. It asks for the password and prints its hash:

```sh
docker run --rm -it docker.io/binwiederhier/ntfy:latest user hash
```

The playbook will let you know if your configuration still uses `ntfy_credentials`.

Your existing ntfy users are left alone and keep working until you declare them again this way. Note that ntfy manages declared users and access-control entries declaratively, so removing one from your configuration later deletes it from ntfy's user database.

Users with the `admin` role get access to all topics. Others start with no access at all, and can be granted access to specific topics via `ntfy_auth_access_custom`. It is also now possible to control what unauthenticated visitors may do (`ntfy_auth_default_access`) and whether users may log in at all (`ntfy_enable_login`, which follows your authentication setup by default). See the role's [documentation on access control](https://github.com/mother-of-all-self-hosting/ansible-role-ntfy/blob/main/docs/configuring-ntfy.md#enable-access-control-with-authentication-optional) for details.

## Support for bridging to LinkedIn via mautrix-linkedin

Thanks to [Aine](https://gitlab.com/etke.cc) of [etke.cc](https://etke.cc/), the playbook now supports bridging to [LinkedIn](https://www.linkedin.com/) via [mautrix-linkedin](https://github.com/mautrix/linkedin).

Logging in requires copying a request out of your browser's developer tools, and only works with Chrome or another Chrome-based browser. To learn more, see our [Setting up Mautrix LinkedIn bridging](./docs/configuring-playbook-bridge-mautrix-linkedin.md) documentation page.

This bridge supersedes [beeper-linkedin](./docs/configuring-playbook-bridge-beeper-linkedin.md), which is now considered unmaintained (its [upstream repository](https://github.com/beeper/linkedin) has been archived). The old bridge remains installable, but you may wish to switch. Both bridges claim the same appservice namespaces, so the playbook refuses to install mautrix-linkedin while beeper-linkedin is still enabled.

## Support for bridging to LINE via beeper-line

Thanks to [Co van Leeuwen](https://github.com/c00), the playbook can now bridge [LINE](https://line.me/) via [beeper-line](https://github.com/beeper/line), a bridge based on the modern mautrix bridge framework. It supports LINE accounts with Letter Sealing enabled or disabled and bridges messages, media, reactions, replies, receipts, and other common chat features.

The bridge identifies itself as a LINE Chrome Extension client, so it cannot be used at the same time as the real LINE Chrome Extension. See [Setting up Beeper LINE bridging](docs/configuring-playbook-bridge-beeper-line.md) to get started.


# 2026-07-19

## Tuwunel now exposes its administration and /_tuwunel API paths

The [Tuwunel](docs/configuring-playbook-tuwunel.md) role previously routed only the `/_matrix` path through the reverse proxy. It now also exposes the two other API paths that Tuwunel serves.

The Synapse-compatible administration API (`/_synapse/admin`) powers administration dashboards and moderation bots. As with Synapse and Dendrite, the playbook now exposes it automatically when such a tool is installed: publicly for [Ketesa](docs/configuring-playbook-ketesa.md) or [Element Admin](docs/configuring-playbook-element-admin.md), and on the internal entrypoint for [Draupnir](docs/configuring-playbook-bot-draupnir.md). To expose it yourself, set `matrix_tuwunel_container_labels_public_client_synapse_admin_api_enabled: true` (or the `internal_` variant).

Tuwunel also serves first-party routes under `/_tuwunel`, including its native OpenID Connect provider endpoints, which the reverse proxy must route for OIDC login to work. This path is now routed on the public entrypoint by default. To keep it off the public entrypoint, set `matrix_tuwunel_container_labels_public_tuwunel_api_enabled: false`.


# 2026-07-18

## LiveKit Server port configuration must be unambiguous now

This only affects you if you have configured a LiveKit Server RTC port range (`livekit_server_config_rtc_port_range_start` and `livekit_server_config_rtc_port_range_end`).

LiveKit only uses one of the two port configuration mechanisms: when a port range is defined, the multiplexed UDP port (`livekit_server_config_rtc_udp_port`) is ignored entirely. Previously, the role would silently render its default UDP port (7882) into the configuration alongside your port range, misleadingly suggesting that both are in effect.

The role now asks you to make the choice explicit: if you define a port range, unset the UDP port by adding `livekit_server_config_rtc_udp_port: ''` to your `vars.yml` file. A validation error will guide you, if your configuration is affected.


# 2026-07-17

## prometheus-nginxlog-exporter metric names have changed

If you have enabled [metrics for nginx logs](docs/configuring-playbook-prometheus-grafana.md) (`prometheus_nginxlog_exporter_enabled: true`), note that the exporter's metric names have changed.

The exporter's configuration used to ship a leftover `myprefix` placeholder as the metric name prefix, producing metrics like `myprefix_http_response_count_total`. The bundled Grafana dashboard queries unprefixed metric names (`http_response_count_total`), so it could never show any data (reported in [#3380](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/3380)).

Metric names are now unprefixed, matching the bundled dashboard, which should start working. Each metric carries a `namespace` label, whose value is now `nginx` (previously `matrix`); it is configurable via `prometheus_nginxlog_exporter_config_namespace_name`. If you have built custom dashboards or alerts on top of the old `myprefix_*` metric names, adjust them accordingly, or restore the old behavior by setting `prometheus_nginxlog_exporter_config_namespace_metrics_prefix: myprefix` in your `vars.yml` file.


# 2026-07-16

## (Backward Compatibility Break) Bridge variables have been renamed

All bridge roles (`roles/custom/matrix-bridge-*`) now use a uniform variable naming scheme, where the variable prefix matches the role directory name. This adopts the naming policy proposed in [#4705](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/4705) and requested in [#5096](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/5096).

Previously, bridge variable prefixes were all over the place (`matrix_mautrix_telegram_*`, `matrix_heisenbridge_*`, `matrix_steam_bridge_*`, etc.). Now, they all follow the same pattern that bot roles (`matrix_bot_<name>_*`) have been using for years: the `matrix-bridge-mautrix-telegram` role uses `matrix_bridge_mautrix_telegram_*` variables, the `matrix-bridge-steam` role uses `matrix_bridge_steam_*` variables, and so on.

Only Ansible variables were renamed. Systemd service names, container names, `/matrix/*` directories, database names and usernames, and appservice registration contents (tokens, bot usernames) all remain the same. No data migration is necessary and bridges keep working as before, once you rename the variables in your `vars.yml` configuration file.

The playbook will let you know if your configuration still uses old-style variable names.

Here is the full rename map:

| Old variable prefix | New variable prefix |
|---------------------|---------------------|
| `matrix_appservice_discord_` | `matrix_bridge_appservice_discord_` |
| `matrix_appservice_irc_` | `matrix_bridge_appservice_irc_` |
| `matrix_beeper_linkedin_` | `matrix_bridge_beeper_linkedin_` |
| `matrix_heisenbridge_` | `matrix_bridge_heisenbridge_` |
| `matrix_hookshot_` | `matrix_bridge_hookshot_` |
| `matrix_mautrix_androidsms_` | `matrix_bridge_mautrix_wsproxy_androidsms_` |
| `matrix_mautrix_bluesky_` | `matrix_bridge_mautrix_bluesky_` |
| `matrix_mautrix_discord_` | `matrix_bridge_mautrix_discord_` |
| `matrix_mautrix_gmessages_` | `matrix_bridge_mautrix_gmessages_` |
| `matrix_mautrix_googlechat_` | `matrix_bridge_mautrix_googlechat_` |
| `matrix_mautrix_gvoice_` | `matrix_bridge_mautrix_gvoice_` |
| `matrix_mautrix_imessage_` | `matrix_bridge_mautrix_wsproxy_imessage_` |
| `matrix_mautrix_meta_instagram_` | `matrix_bridge_mautrix_meta_instagram_` |
| `matrix_mautrix_meta_messenger_` | `matrix_bridge_mautrix_meta_messenger_` |
| `matrix_mautrix_signal_` | `matrix_bridge_mautrix_signal_` |
| `matrix_mautrix_slack_` | `matrix_bridge_mautrix_slack_` |
| `matrix_mautrix_telegram_` | `matrix_bridge_mautrix_telegram_` |
| `matrix_mautrix_twitter_` | `matrix_bridge_mautrix_twitter_` |
| `matrix_mautrix_whatsapp_` | `matrix_bridge_mautrix_whatsapp_` |
| `matrix_mautrix_wsproxy_` | `matrix_bridge_mautrix_wsproxy_` |
| `matrix_meshtastic_relay_` | `matrix_bridge_meshtastic_relay_` |
| `matrix_mx_puppet_groupme_` | `matrix_bridge_mx_puppet_groupme_` |
| `matrix_mx_puppet_steam_` | `matrix_bridge_mx_puppet_steam_` |
| `matrix_postmoogle_` | `matrix_bridge_postmoogle_` |
| `matrix_rustpush_bridge_` | `matrix_bridge_rustpush_` |
| `matrix_sms_bridge_` | `matrix_bridge_sms_` |
| `matrix_steam_bridge_` | `matrix_bridge_steam_` |
| `matrix_wechat_` | `matrix_bridge_wechat_` |

A few special cases beyond the prefix map:

- `matrix_mautrix_signal_wsproxy_syncproxy_connection_string` (a variable of the mautrix-wsproxy role, despite its name) is now `matrix_bridge_mautrix_wsproxy_syncproxy_connection_string`
- `matrix_playbook_migration_matrix_postmoogle_migration_validation_enabled` is now `matrix_playbook_migration_matrix_bridge_postmoogle_migration_validation_enabled`

You can update your `vars.yml` file automatically with this `sed` command (on macOS, use `sed -i ''` instead of `sed -i`):

```sh
sed -i \
-e 's/matrix_appservice_discord_/matrix_bridge_appservice_discord_/g' \
-e 's/matrix_appservice_irc_/matrix_bridge_appservice_irc_/g' \
-e 's/matrix_beeper_linkedin_/matrix_bridge_beeper_linkedin_/g' \
-e 's/matrix_heisenbridge_/matrix_bridge_heisenbridge_/g' \
-e 's/matrix_hookshot_/matrix_bridge_hookshot_/g' \
-e 's/matrix_mautrix_androidsms_/matrix_bridge_mautrix_wsproxy_androidsms_/g' \
-e 's/matrix_mautrix_bluesky_/matrix_bridge_mautrix_bluesky_/g' \
-e 's/matrix_mautrix_discord_/matrix_bridge_mautrix_discord_/g' \
-e 's/matrix_mautrix_gmessages_/matrix_bridge_mautrix_gmessages_/g' \
-e 's/matrix_mautrix_googlechat_/matrix_bridge_mautrix_googlechat_/g' \
-e 's/matrix_mautrix_gvoice_/matrix_bridge_mautrix_gvoice_/g' \
-e 's/matrix_mautrix_imessage_/matrix_bridge_mautrix_wsproxy_imessage_/g' \
-e 's/matrix_mautrix_meta_instagram_/matrix_bridge_mautrix_meta_instagram_/g' \
-e 's/matrix_mautrix_meta_messenger_/matrix_bridge_mautrix_meta_messenger_/g' \
-e 's/matrix_mautrix_signal_wsproxy_syncproxy_connection_string/matrix_bridge_mautrix_wsproxy_syncproxy_connection_string/g' \
-e 's/matrix_mautrix_signal_/matrix_bridge_mautrix_signal_/g' \
-e 's/matrix_mautrix_slack_/matrix_bridge_mautrix_slack_/g' \
-e 's/matrix_mautrix_telegram_/matrix_bridge_mautrix_telegram_/g' \
-e 's/matrix_mautrix_twitter_/matrix_bridge_mautrix_twitter_/g' \
-e 's/matrix_mautrix_whatsapp_/matrix_bridge_mautrix_whatsapp_/g' \
-e 's/matrix_mautrix_wsproxy_/matrix_bridge_mautrix_wsproxy_/g' \
-e 's/matrix_meshtastic_relay_/matrix_bridge_meshtastic_relay_/g' \
-e 's/matrix_mx_puppet_groupme_/matrix_bridge_mx_puppet_groupme_/g' \
-e 's/matrix_mx_puppet_steam_/matrix_bridge_mx_puppet_steam_/g' \
-e 's/matrix_postmoogle_/matrix_bridge_postmoogle_/g' \
-e 's/matrix_rustpush_bridge_/matrix_bridge_rustpush_/g' \
-e 's/matrix_sms_bridge_/matrix_bridge_sms_/g' \
-e 's/matrix_steam_bridge_/matrix_bridge_steam_/g' \
-e 's/matrix_wechat_/matrix_bridge_wechat_/g' \
-e 's/matrix_playbook_migration_matrix_postmoogle_migration_validation_enabled/matrix_playbook_migration_matrix_bridge_postmoogle_migration_validation_enabled/g' \
vars.yml
```

The `sed` command only replaces prefixes followed by an underscore, so values that intentionally match old prefixes (like the default database names, e.g. `matrix_mautrix_telegram`) are not affected.

**Note**: if you have defined your own custom variables whose names embed an old prefix (e.g. `vault_matrix_postmoogle_password` referencing a secret in an Ansible Vault file), the `sed` command renames such references too. Either rename your custom variables to match (including their definitions in encrypted vault files, which `sed` cannot reach), or revert those spots manually.

# 2026-07-15

## Google Voice bridging

The playbook can now bridge [Google Voice](https://voice.google.com/) via the [mautrix-gvoice](https://github.com/mautrix/gvoice) bridge. Text and media flow both ways, and portal rooms build themselves for your recent conversations.

Login is by cookie, not a paired phone: you copy the cookies from a browser signed in to voice.google.com and hand them to the bot. Google expires them on its own schedule, so expect to log in again every so often. See [Setting up Mautrix Google Voice bridging](./docs/configuring-playbook-bridge-mautrix-gvoice.md) to get started.

## matrix-appservice-kakaotalk has been removed from the playbook

The [matrix-appservice-kakaotalk](./docs/configuring-playbook-bridge-appservice-kakaotalk.md) bridge has been removed from the playbook. This component could only be installed by self-building its source code, and its upstream repository has become unreachable, which makes installation impossible. The bridge was also based on the unmaintained node-kakao library, and there have been reports that using it may get KakaoTalk accounts banned.

The playbook will let you know if you're using any `matrix_appservice_kakaotalk_*` variables. You'll need to remove them from `vars.yml` and potentially [uninstall the component manually](./docs/configuring-playbook-bridge-appservice-kakaotalk.md#uninstalling-the-component-manually).

## Dedicated CAPTCHA variables for Matrix Authentication Service

[Matrix Authentication Service](./docs/configuring-playbook-matrix-authentication-service.md) can now be protected with CAPTCHA (ReCaptcha v2, Cloudflare Turnstile, or hCaptcha) via dedicated variables, instead of going through `matrix_authentication_service_configuration_extension_yaml`. See the [captcha documentation](./docs/configuring-captcha.md#matrix-authentication-service) for details.

# 2026-07-14

## The playbook no longer ships a custom welcome page for Element Web

Element Web [redesigned its welcome page](https://github.com/element-hq/element-web/pull/33211) (the screen shown at `/#/welcome` before logging in) into a built-in component and no longer loads a custom `welcome.html` file by default. Since the playbook upgraded to an Element Web version containing that change (spring 2026), the custom welcome page the playbook installed (and the variables customizing it) had silently stopped having any effect.

The playbook now embraces the new upstream behavior and no longer ships its own `welcome.html`. The following variables have been removed and the playbook will let you know if you're still using them: `matrix_client_element_welcome_headline`, `matrix_client_element_welcome_text`, `matrix_client_element_welcome_logo_link` and `matrix_client_element_page_template_welcome_path`.

Most welcome page customizations keep working, because they go through Element Web's branding configuration, which the new welcome page still honors:

- a custom logo, via `matrix_client_element_welcome_logo` (or `matrix_client_element_branding_auth_header_logo_url`)
- a custom background, via `matrix_client_element_branding_welcome_background_url`

If you need a fully custom welcome page, you can self-host an HTML page and point Element Web at it, like this:

```yaml
matrix_client_element_configuration_extension_json: |
{
"embedded_pages": {
"welcome_url": "https://example.com/my-welcome.html"
}
}
```

## BorgBackup now includes Synapse's local thumbnails

For Synapse servers, the built-in [BorgBackup](./docs/configuring-playbook-backup-borg.md) integration no longer excludes the media store's `local_thumbnails` directory from backups.

Synapse only generates thumbnails of local media at upload time (unless `dynamic_thumbnails` is enabled, which the playbook does not do), and there is no tooling to regenerate them. Restoring a backup made with the previous exclusion list therefore left all previously uploaded local images without thumbnails. The [official Synapse backup guide](https://element-hq.github.io/synapse/latest/usage/administration/backups.html) recommends backing this directory up, and the playbook now follows that recommendation.

Expect your backups to grow somewhat, depending on how much image media your local users have uploaded. If you prefer the old behavior, you can redefine `backup_borg_location_exclude_patterns` in your `vars.yml`.

# 2026-07-12

## matrix-registration-bot has been removed from the playbook

The [matrix-registration-bot](./docs/configuring-playbook-bot-matrix-registration-bot.md) service has been removed from the playbook, as it has been unmaintained.

The playbook will let you know if you're using any `matrix_bot_matrix_registration_bot_*` variables. You'll need to remove them from `vars.yml` and potentially [uninstall the component manually](./docs/configuring-playbook-bot-matrix-registration-bot.md#uninstalling-the-component-manually).

## Continuwuity v26 no longer supports LDAP

The playbook now installs [Continuwuity](./docs/configuring-playbook-continuwuity.md) v26, a major upgrade from the v0.5.x series which **removes LDAP authentication support** (see the [v26.6.0 release notes](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v26.6.0)).

The playbook never exposed dedicated variables for Continuwuity's LDAP support, so most people are unaffected. However, if you had enabled LDAP via `matrix_continuwuity_environment_variables_extension` or a custom configuration template, you'll need to migrate to another authentication method, such as the newly introduced [OpenID Connect support](https://continuwuity.org/guides/oidc).

# 2026-06-29

## Support for running on Synology DSM

Thanks to [cksit](https://github.com/cksit), the playbook can now run on [Synology DSM](https://www.synology.com/dsm) 7 and later.

Synology hosts are detected automatically (via `/etc/synoinfo.conf`), so other systems are unaffected. On DSM, the playbook uses the platform's native user management (`synouser`/`synogroup`), works around a Docker SDK incompatibility, and installs a small boot-fix service that handles a few DSM-specific boot quirks.

To get started, see the new [Configuring Synology DSM](./docs/configuring-playbook-synology.md) documentation page.

## Mautrix bridges now expose their API (for Mautrix Manager and similar tools)

The playbook now exposes the HTTP API of each [mautrix](https://github.com/mautrix) bridge, so tools like [Mautrix Manager](https://github.com/mautrix/manager) can help you log into them. This is especially useful for [mautrix-gmessages](./docs/configuring-playbook-bridge-mautrix-gmessages.md): Google has removed its QR-code login, leaving a [manual cookie-extraction flow](https://docs.mau.fi/bridges/go/gmessages/authentication.html) that tools like Mautrix Manager can streamline.

The API is exposed at `https://matrix.example.com/bridges/SERVICENAME` (for example, `https://matrix.example.com/bridges/gmessages`) and is advertised via a new `/.well-known/matrix/mautrix` file, so compatible tools can discover your bridges automatically. Such tools authenticate with your own Matrix access token, so no bridge secret needs to be shared with them.

This affects all mautrix bridges based on the new bridge framework (bluesky, gmessages, meta-instagram, meta-messenger, signal, slack, telegram, twitter and whatsapp) and is enabled by default.

To learn more (including how to turn it off), see the [Expose the bridge's API](./docs/configuring-playbook-bridge-mautrix-bridges.md#expose-the-bridges-api-for-mautrix-manager-and-similar-tools) section on our common mautrix bridges documentation page.

# 2026-06-28

## baibot now supports Venice, our recommended provider

[baibot](./docs/configuring-playbook-bot-baibot.md) now ships a preset for the [Venice](./docs/configuring-playbook-bot-baibot.md#venice) provider, and it's the one we recommend. It's the most capable provider baibot supports (text generation with vision, file inputs and web search, speech-to-text, text-to-speech, and image generation and editing), and the only one that runs inference with no logging and no training on your data.

Enabling it takes a preset toggle and an API key:

```yaml
matrix_bot_baibot_config_agents_static_definitions_venice_enabled: true

matrix_bot_baibot_config_agents_static_definitions_venice_config_api_key: "YOUR_API_KEY_HERE"
```

[OpenAI](https://openai.com/) and baibot's other providers remain fully supported. To get started, see the [Setting up baibot](./docs/configuring-playbook-bot-baibot.md#venice) documentation page.

# 2026-06-24

## Support for bridging to iMessage via RustPush

Thanks to [jasonlaguidice](https://github.com/jasonlaguidice), the playbook now supports bridging to [iMessage](https://support.apple.com/messages) via a new [RustPush](https://github.com/OpenBubbles/rustpush)-based bridge ([jasonlaguidice/imessage](https://github.com/jasonlaguidice/imessage)).

Unlike the existing [mautrix-wsproxy](./docs/configuring-playbook-bridge-mautrix-wsproxy.md) iMessage bridge, this one talks directly to Apple's push notification service, so it needs neither a running Mac nor a wsproxy on the homeserver. Each user supplies a hardware key extracted from a Mac through the bridge bot's login flow.

To learn more, see our [Setting up RustPush (iMessage) bridging](./docs/configuring-playbook-bridge-rustpush.md) documentation page.

# 2026-05-24

## matrix-ldap-registration-proxy has been removed from the playbook

The [matrix-ldap-registration-proxy](./docs/configuring-playbook-matrix-ldap-registration-proxy.md) service has been removed from the playbook, as the source code and the container image have become unavailable.

The playbook will let you know if you're using any `matrix_ldap_registration_proxy_*` variables. You'll need to remove them from `vars.yml` and potentially [uninstall the component manually](./docs/configuring-playbook-matrix-ldap-registration-proxy.md#uninstalling-the-component-manually).

# 2026-05-23

## Go-NEB has been removed from the playbook

[Go-NEB](./docs/configuring-playbook-bot-go-neb.md) has been removed from the playbook, as it has been discontinued since June 2023.

The playbook will let you know if you're using any `matrix_bot_go_neb_*` variables. You'll need to remove them from `vars.yml` and potentially [uninstall the bot manually](./docs/configuring-playbook-bot-go-neb.md#uninstalling-go-neb-manually).

# 2026-05-19

## matrix-registration has been removed from the playbook

The [matrix-registration](./docs/configuring-playbook-matrix-registration.md) service has been removed from the playbook, as it has been unmaintained (archived) since November, 2025.

The playbook will let you know if you're using any `matrix_registration_*` variables. You'll need to remove them from `vars.yml` and potentially [uninstall the component manually](./docs/configuring-playbook-matrix-registration.md#uninstalling-the-component-manually).

# 2026-05-18

## LiveKit Server has been upgraded to v1.12.0

The playbook now ships [LiveKit Server](./docs/configuring-playbook-livekit-server.md) v1.12.0. See the [upstream release notes](https://github.com/livekit/livekit/releases/tag/v1.12.0) for details.

This release tightens TURN security:

- **TURN credentials now carry a TTL** (default: 300 seconds), exposed via `livekit_server_config_turn_ttl_seconds`.
- **TURN no longer relays traffic to restricted peer CIDRs** (loopback, link-local, multicast, private, unspecified) by default. If your setup legitimately requires it, list the ranges in `livekit_server_config_turn_allow_restricted_peer_cidrs`.

For example, to allow TURN to reach the common [RFC1918](https://www.rfc-editor.org/rfc/rfc1918) private ranges, add to your `vars.yml`:
```yaml
livekit_server_config_turn_allow_restricted_peer_cidrs:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
```

Adjust the ranges to match your network. To deny specific CIDRs (taking precedence over the allow list above), use `livekit_server_config_turn_deny_peer_cidrs` in the same shape.


# 2026-05-07

## Tuwunel support

Thanks to [Jason Volk](https://github.com/jevolk), the playbook now supports the [Tuwunel](./docs/configuring-playbook-tuwunel.md) homeserver as an optional alternative to Synapse.

Tuwunel is a fork of [conduwuit](./docs/configuring-playbook-conduwuit.md) written in Rust. The former conduwuit maintainer [endorses Tuwunel as conduwuit's successor](https://github.com/spantaleev/matrix-docker-ansible-deploy/pull/5200#issuecomment-4396211185). Like [Continuwuity](./docs/configuring-playbook-continuwuity.md), Tuwunel continues development on top of conduwuit's database format.

Existing installations do **not** need to be updated. **Synapse is still the default homeserver implementation** installed by the playbook.

People that used to run conduwuit may wish to [migrate from conduwuit to Tuwunel](./docs/configuring-playbook-tuwunel.md#migrating-from-conduwuit) via the new `tuwunel-migrate-from-conduwuit` tag, which performs an in-place binary-swap migration that reads the conduwuit database directly.

**The homeserver implementation of an existing server cannot be changed** (e.g. from Synapse/Conduit/Dendrite/Continuwuity to Tuwunel) without data loss. The exception is conduwuit, due to the shared database format.


# 2026-04-24

## Support for bridging to Meshtastic via meshtastic-matrix-relay

Thanks to [luschmar](https://github.com/luschmar), the playbook now supports bridging to [Meshtastic](https://meshtastic.org/) mesh networks via [meshtastic-matrix-relay](https://github.com/jeremiah-k/meshtastic-matrix-relay) (mmrelay).

To learn more, see our [Setting up a Matrix <-> Meshtastic bridge](./docs/configuring-playbook-bridge-meshtastic-relay.md) documentation page.

## (BC Break) mautrix-telegram has been rewritten in Go (bridgev2)

The [mautrix-telegram](./docs/configuring-playbook-bridge-mautrix-telegram.md) bridge has been [rewritten in Go](https://mau.fi/blog/2026-04-mautrix-release/) on top of the [bridgev2](https://docs.mau.fi/bridges/go/) architecture. See the [upstream v26.04 release notes](https://github.com/mautrix/telegram/releases/tag/v0.2604.0) for what changed in the bridge itself (shared-portal behavior, management-room state, new features, etc.).

**Most users won't have to do anything.** If you use the playbook's integrated Postgres (the default) and haven't customized telegram-bridge variables beyond `matrix_mautrix_telegram_api_id` and `matrix_mautrix_telegram_api_hash`, just re-run the playbook; the bridge will migrate itself on first start. Taking a backup beforehand is still a good idea.

⚠️ **SQLite users: do not upgrade yet.** Upstream v0.2604.0 has a [known bug in the legacy SQLite migration](https://github.com/mautrix/telegram/releases/tag/v0.2604.0) that can corrupt your data. The playbook detects this case and will refuse to proceed. Either switch to Postgres first (set `matrix_mautrix_telegram_database_engine: postgres`; the playbook handles the pgloader migration), or wait for the next upstream release.

Playbook-specific things to know. The playbook will fail loudly if you're affected:

- Many `matrix_mautrix_telegram_*` variables have been **removed** (web-login endpoint, lottieconverter, username/alias/displayname templates, filter-mode, bot-token relaybot, Shared-Secret-Auth map). The deprecation check will tell you exactly what to rename or drop when you run the playbook.
- **Old-style relaybot users** (`matrix_mautrix_telegram_bot_token`): switch to the common [mautrix bridge relay mode](./docs/configuring-playbook-bridge-mautrix-bridges.md#enable-relay-mode-optional) via `matrix_mautrix_telegram_bridge_relay_enabled: true`.
- **Shared-Secret-Auth double-puppeting users**: switch to [Appservice Double Puppet](./docs/configuring-playbook-appservice-double-puppet.md); the playbook wires it up automatically.
- **Custom `matrix_mautrix_telegram_bridge_permissions`**: map `relaybot` to `relay`, `puppeting` to `user`, `full` to `user`. Validated at playbook time.

# 2026-04-03

## (BC Break) Synapse Admin (fork by etke.cc) is now Ketesa

Synapse Admin has been rebranded to **[Ketesa](https://github.com/etkecc/ketesa)** — a landmark release that introduces a new identity, a full UI redesign, mobile-first layout, and deep Matrix Authentication Service (MAS) integration. For the full story behind the rename and a tour of what's new, see the [Ketesa v1.0.0 announcement](https://etke.cc/blog/introducing-ketesa/).

Ketesa is a zero-configuration drop-in replacement for Synapse Admin: no server-side changes required, just update the role variables.

The `matrix-synapse-admin` role has been **renamed** to `matrix-ketesa`. All `matrix_synapse_admin_*` variables must be **renamed** to `matrix_ketesa_*` in your `vars.yml`.

Additionally, the **Docker image** changed from `ghcr.io/etkecc/synapse-admin` to `ghcr.io/etkecc/ketesa`. The default path prefix remains `/synapse-admin` for backward compatibility — updating to `/ketesa` is recommended but not required.

The playbook will automatically detect leftover `matrix_synapse_admin_*` variables and fail with a helpful message listing what needs to be renamed.

The playbook handles reverse-proxy routing for subpath deployments (e.g. `/ketesa`), including MAS-enabled setups — though OIDC auth flows on real servers still have some rough edges. Feedback is appreciated in [#ketesa:etke.cc](https://matrix.to/#/#ketesa:etke.cc).

See the [Ketesa documentation](docs/configuring-playbook-ketesa.md) for details.

# 2026-04-02

## (BC Break) Draupnir for all Self Service Provisioning is now disabled by default

💡 If you don't use [Draupnir for all](./docs/configuring-playbook-appservice-draupnir-for-all.md), then this breaking change does not concern you..

[Draupnir for all](./docs/configuring-playbook-appservice-draupnir-for-all.md) now ships with `allowSelfServiceProvisioning: false` as default upstream and in this playbook.

This means users can no longer provision Draupnir instances by inviting the appservice bot unless you explicitly opt in.

Manual provisioning by administrators is now the recommended approach. You do not want to enable Self Service Provisioning unless you have additional custom safeguards like those used by asgard.chat in place.

If you want to enable Self Service Provisioning, add the following to your `vars.yml`:

```yaml
matrix_appservice_draupnir_for_all_configuration_extension_yaml: |
allowSelfServiceProvisioning: true
```

# 2026-03-23

## Migration validation system introduced


+ 4
- 1
Makefile View File

@@ -2,11 +2,14 @@
#
# SPDX-License-Identifier: AGPL-3.0-or-later

.PHONY: roles lint
.PHONY: roles lint add-inventory-host

help: ## Show this help.
@grep -F -h "##" $(MAKEFILE_LIST) | grep -v grep | sed -e 's/\\$$//' | sed -e 's/##//'

add-inventory-host: ## Adds a new host to the inventory, creating the inventory files if necessary (e.g. `make add-inventory-host domain=example.com ip=1.2.3.4`)
@./bin/add-inventory-host.sh "$(domain)" "$(ip)"

roles: ## Pull roles
rm -rf roles/galaxy
ansible-galaxy install -r requirements.yml -p roles/galaxy/ --force


+ 12
- 9
README.md View File

@@ -4,7 +4,7 @@

## 🎯 Purpose

This [Ansible](https://www.ansible.com/) playbook is meant to help you run your own [Matrix](http://matrix.org/) homeserver, along with the [various services](#supported-services) related to that.
This [Ansible](https://www.ansible.com/) playbook is meant to help you run your own [Matrix](http://matrix.org/) homeserver, along with the [various services](#-supported-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](docs/prerequisites.md)).

@@ -53,6 +53,7 @@ The homeserver is the backbone of your Matrix system. Choose one from the follow
| [Synapse](https://github.com/element-hq/synapse) | ✅ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network | [Link](docs/configuring-playbook-synapse.md) |
| [Conduit](https://conduit.rs) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. Conduit is a lightweight open-source server implementation of the Matrix Specification with a focus on easy setup and low system requirements | [Link](docs/configuring-playbook-conduit.md) |
| [continuwuity](https://continuwuity.org) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. | [Link](docs/configuring-playbook-continuwuity.md) |
| [Tuwunel](https://matrix-construct.github.io/tuwunel/) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. Tuwunel is the official successor to conduwuit. | [Link](docs/configuring-playbook-tuwunel.md) |
| [Dendrite](https://github.com/element-hq/dendrite) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. Dendrite is a second-generation Matrix homeserver written in Go, an alternative to Synapse. | [Link](docs/configuring-playbook-dendrite.md) |

### Clients
@@ -64,9 +65,10 @@ Web clients for Matrix that you can host on your own domains.
| [Element Web](https://github.com/element-hq/element-web) | ✅ | Default Matrix web client, configured to connect to your own Synapse server | [Link](docs/configuring-playbook-client-element-web.md) |
| [Hydrogen](https://github.com/element-hq/hydrogen-web) | ❌ | Lightweight Matrix client with legacy and mobile browser support | [Link](docs/configuring-playbook-client-hydrogen.md) |
| [Cinny](https://github.com/ajbura/cinny) | ❌ | Simple, elegant and secure web client | [Link](docs/configuring-playbook-client-cinny.md) |
| [Sable](https://github.com/7w1/sable) | ❌ | Simple, elegant and secure web client | [Link](docs/configuring-playbook-client-sable.md) |
| [Sable](https://github.com/SableClient/Sable) | ❌ | Simple, elegant and secure web client | [Link](docs/configuring-playbook-client-sable.md) |
| [SchildiChat Web](https://schildi.chat/) | ❌ | Based on Element Web, with a more traditional instant messaging experience | [Link](docs/configuring-playbook-client-schildichat-web.md) |
| [FluffyChat Web](https://fluffychat.im/) | ❌ | The cutest messenger in Matrix | [Link](docs/configuring-playbook-client-fluffychat-web.md) |
| [Commet](https://github.com/commetchat/commet) | ❌ | Matrix web client | [Link](docs/configuring-playbook-client-commet.md) |

### Server Components

@@ -91,8 +93,6 @@ Extend and modify how users are authenticated on your homeserver.
| [matrix-synapse-rest-auth](https://github.com/ma1uta/matrix-synapse-rest-password-provider) (advanced) | ❌ | REST authentication password provider module | [Link](docs/configuring-playbook-rest-auth.md) |
|[matrix-synapse-shared-secret-auth](https://github.com/devture/matrix-synapse-shared-secret-auth) (advanced) | ❌ | Password provider module | [Link](docs/configuring-playbook-shared-secret-auth.md) |
| [matrix-synapse-ldap3](https://github.com/matrix-org/matrix-synapse-ldap3) (advanced) | ❌ | LDAP Auth password provider module | [Link](docs/configuring-playbook-ldap-auth.md) |
| [matrix-ldap-registration-proxy](https://gitlab.com/activism.international/matrix_ldap_registration_proxy) (advanced) | ❌ | Proxy that handles Matrix registration requests and forwards them to LDAP | [Link](docs/configuring-playbook-matrix-ldap-registration-proxy.md) |
| [matrix-registration](https://github.com/ZerataX/matrix-registration) | ❌ | Simple python application to have a token based Matrix registration | [Link](docs/configuring-playbook-matrix-registration.md) |
| [Matrix User Verification Service](https://github.com/matrix-org/matrix-user-verification-service) | ❌ | Service to verify details of a user based on an Open ID token | [Link](docs/configuring-playbook-user-verification-service.md) |
| [synapse-simple-antispam](https://github.com/t2bot/synapse-simple-antispam) (advanced) | ❌ | Spam checker module | [Link](docs/configuring-playbook-synapse-simple-antispam.md) |

@@ -116,22 +116,25 @@ Bridges can be used to connect your Matrix installation with third-party communi
| [mautrix-slack](https://github.com/mautrix/slack) | ❌ | Bridge to [Slack](https://slack.com/) | [Link](docs/configuring-playbook-bridge-mautrix-slack.md) |
| [mautrix-telegram](https://github.com/mautrix/telegram) | ❌ | Bridge to [Telegram](https://telegram.org/) | [Link](docs/configuring-playbook-bridge-mautrix-telegram.md) |
| [mautrix-gmessages](https://github.com/mautrix/gmessages) | ❌ | Bridge to [Google Messages](https://messages.google.com/) | [Link](docs/configuring-playbook-bridge-mautrix-gmessages.md) |
| [mautrix-gvoice](https://github.com/mautrix/gvoice) | ❌ | Bridge to [Google Voice](https://voice.google.com/) | [Link](docs/configuring-playbook-bridge-mautrix-gvoice.md) |
| [mautrix-linkedin](https://github.com/mautrix/linkedin) | ❌ | Bridge to [LinkedIn](https://www.linkedin.com/) | [Link](docs/configuring-playbook-bridge-mautrix-linkedin.md) |
| [mautrix-whatsapp](https://github.com/mautrix/whatsapp) | ❌ | Bridge to [WhatsApp](https://www.whatsapp.com/) | [Link](docs/configuring-playbook-bridge-mautrix-whatsapp.md) |
| [mautrix-wsproxy](https://github.com/mautrix/wsproxy) | ❌ | Bridge to Android SMS or Apple iMessage | [Link](docs/configuring-playbook-bridge-mautrix-wsproxy.md) |
| [matrix-rustpush-bridge](https://github.com/jasonlaguidice/imessage) | ❌ | Bridge to [iMessage](https://support.apple.com/messages) via Apple Push Notification service | [Link](docs/configuring-playbook-bridge-rustpush.md) |
| [mautrix-bluesky](https://github.com/mautrix/bluesky) | ❌ | Bridge to [Bluesky](https://bsky.social/) | [Link](docs/configuring-playbook-bridge-mautrix-bluesky.md) |
| [mautrix-twitter](https://github.com/mautrix/twitter) | ❌ | Bridge to [Twitter](https://twitter.com/) | [Link](docs/configuring-playbook-bridge-mautrix-twitter.md) |
| [mautrix-googlechat](https://github.com/mautrix/googlechat) | ❌ | Bridge to [Google Chat](https://en.wikipedia.org/wiki/Google_Chat) | [Link](docs/configuring-playbook-bridge-mautrix-googlechat.md) |
| [mautrix-meta](https://github.com/mautrix/instagram) | ❌ | Bridge to [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/) | Link for [Messenger](docs/configuring-playbook-bridge-mautrix-meta-messenger.md) / [Instagram](docs/configuring-playbook-bridge-mautrix-meta-instagram.md) |
| [mautrix-meta](https://github.com/mautrix/meta) | ❌ | Bridge to [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/) | Link for [Messenger](docs/configuring-playbook-bridge-mautrix-meta-messenger.md) / [Instagram](docs/configuring-playbook-bridge-mautrix-meta-instagram.md) |
| [mautrix-signal](https://github.com/mautrix/signal) | ❌ | Bridge to [Signal](https://www.signal.org/) | [Link](docs/configuring-playbook-bridge-mautrix-signal.md) |
| [beeper-linkedin](https://github.com/beeper/linkedin) | ❌ | Bridge to [LinkedIn](https://www.linkedin.com/) | [Link](docs/configuring-playbook-bridge-beeper-linkedin.md) |
| [beeper-line](https://github.com/beeper/line) | ❌ | Bridge to [LINE](https://line.me/) | [Link](docs/configuring-playbook-bridge-beeper-line.md) |
| [matrix-appservice-irc](https://github.com/matrix-org/matrix-appservice-irc) | ❌ | Bridge to [IRC](https://wikipedia.org/wiki/Internet_Relay_Chat) | [Link](docs/configuring-playbook-bridge-appservice-irc.md) |
| [matrix-appservice-kakaotalk](https://src.miscworks.net/fair/matrix-appservice-kakaotalk) | ❌ | Bridge to [Kakaotalk](https://www.kakaocorp.com/page/service/service/KakaoTalk?lang=ENG) | [Link](docs/configuring-playbook-bridge-appservice-kakaotalk.md) |
| [matrix-appservice-discord](https://github.com/matrix-org/matrix-appservice-discord) | ❌ | Bridge to [Discord](https://discordapp.com/) | [Link](docs/configuring-playbook-bridge-appservice-discord.md) |
| [matrix-hookshot](https://github.com/matrix-org/matrix-hookshot) | ❌ | Bridge for generic webhooks and multiple project management services, such as GitHub, GitLab, Figma, and Jira in particular | [Link](docs/configuring-playbook-bridge-hookshot.md) |
| [matrix-sms-bridge](https://github.com/benkuly/matrix-sms-bridge) | ❌ | Bridge to SMS | [Link](docs/configuring-playbook-bridge-matrix-bridge-sms.md) |
| [matrix-steam-bridge](https://github.com/jasonlaguidice/matrix-steam-bridge) | ❌ | Bridge to [Steam](https://steampowered.com/) | [Link](docs/configuring-playbook-bridge-steam.md) |
| [matrix-wechat](https://github.com/duo/matrix-wechat) | ❌ | Bridge to [WeChat](https://www.wechat.com/) | [Link](docs/configuring-playbook-bridge-wechat.md) |
| [Heisenbridge](https://github.com/hifi/heisenbridge) | ❌ | Bouncer-style bridge to [IRC](https://wikipedia.org/wiki/Internet_Relay_Chat) | [Link](docs/configuring-playbook-bridge-heisenbridge.md) |
| [meshtastic-matrix-relay](https://github.com/jeremiah-k/meshtastic-matrix-relay) | ❌ | Bridge to [Meshtastic](https://meshtastic.org/) mesh networks | [Link](docs/configuring-playbook-bridge-meshtastic-relay.md) |
| [mx-puppet-groupme](https://gitlab.com/xangelix-pub/matrix/mx-puppet-groupme) | ❌ | Bridge to [GroupMe](https://groupme.com/) | [Link](docs/configuring-playbook-bridge-mx-puppet-groupme.md) |
| [mx-puppet-steam](https://codeberg.org/icewind/mx-puppet-steam) | ❌ | Bridge to [Steam](https://steamapp.com/) | [Link](docs/configuring-playbook-bridge-mx-puppet-steam.md) |
| [Postmoogle](https://github.com/etkecc/postmoogle) | ❌ | Email to Matrix bridge | [Link](docs/configuring-playbook-bridge-postmoogle.md) |
@@ -144,11 +147,11 @@ Bots provide various additional functionality to your installation.
| ---- | -------- | ----------- | ------------- |
| [baibot](https://github.com/etkecc/baibot) | ❌ | Bot that exposes the power of [AI](https://en.wikipedia.org/wiki/Artificial_intelligence) / [Large Language Models](https://en.wikipedia.org/wiki/Large_language_model) to you | [Link](docs/configuring-playbook-bot-baibot.md) |
| [matrix-reminder-bot](https://github.com/anoadragon453/matrix-reminder-bot) | ❌ | Bot for scheduling one-off & recurring reminders and alarms | [Link](docs/configuring-playbook-bot-matrix-reminder-bot.md) |
| [matrix-registration-bot](https://github.com/moan0s/matrix-registration-bot) | ❌ | Bot for invitations by creating and managing registration tokens | [Link](docs/configuring-playbook-bot-matrix-registration-bot.md) |
| [maubot](https://github.com/maubot/maubot) | ❌ | Plugin-based Matrix bot system | [Link](docs/configuring-playbook-bot-maubot.md) |
| [Honoroit](https://github.com/etkecc/honoroit) | ❌ | Helpdesk bot | [Link](docs/configuring-playbook-bot-honoroit.md) |
| [Mjolnir](https://github.com/matrix-org/mjolnir) | ❌ | Moderation tool for Matrix | [Link](docs/configuring-playbook-bot-mjolnir.md) |
| [Draupnir](https://github.com/the-draupnir-project/Draupnir) | ❌ | Moderation tool for Matrix (Fork of Mjolnir) | [Link](docs/configuring-playbook-bot-draupnir.md) (for [appservice mode](docs/configuring-playbook-appservice-draupnir-for-all.md))|
| [Meowlnir](https://github.com/maunium/meowlnir) | ❌ | Moderation tool for Matrix, running in appservice mode | [Link](docs/configuring-playbook-bot-meowlnir.md) |
| [Buscarron](https://github.com/etkecc/buscarron) | ❌ | Web forms (HTTP POST) to Matrix | [Link](docs/configuring-playbook-bot-buscarron.md) |

### Administration
@@ -159,7 +162,7 @@ Services that help you in administrating and monitoring your Matrix installation
| ---- | -------- | ----------- | ------------- |
| [matrix-alertmanager-receiver](https://github.com/metio/matrix-alertmanager-receiver) | ❌ | Prometheus' [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) client | [Link](docs/configuring-playbook-alertmanager-receiver.md) |
| [Matrix Authentication Service](https://github.com/element-hq/matrix-authentication-service/) | ❌ | OAuth 2.0 and OpenID Provider server | [Link](docs/configuring-playbook-matrix-authentication-service.md) |
| [synapse-admin](https://github.com/etkecc/synapse-admin) | ❌ | Web UI tool for administrating users and rooms on your Matrix server | [Link](docs/configuring-playbook-synapse-admin.md) |
| [Ketesa](https://github.com/etkecc/ketesa) | ❌ | Fully-featured web UI for administrating your Matrix homeserver — users, rooms, media, sessions, and more | [Link](docs/configuring-playbook-ketesa.md) |
| Metrics and Graphs | ❌ | Consists of the [Prometheus](https://prometheus.io) time-series database server, the Prometheus [node-exporter](https://prometheus.io/docs/guides/node-exporter/) host metrics exporter, and the [Grafana](https://grafana.com/) web UI, with [prometheus-nginxlog-exporter](https://github.com/martin-helmich/prometheus-nginxlog-exporter/) being available too | [Link](docs/configuring-playbook-prometheus-grafana.md) (for [prometheus-nginxlog-exporter](docs/configuring-playbook-prometheus-grafana.md#enable-metrics-and-graphs-for-nginx-logs-optional)) |
| [Borg](https://borgbackup.org) | ❌ | Backups | [Link](docs/configuring-playbook-backup-borg.md) |
| [rageshake](https://github.com/matrix-org/rageshake) | ❌ | Bug report server | [Link](docs/configuring-playbook-rageshake.md) |


+ 120
- 0
bin/add-inventory-host.sh View File

@@ -0,0 +1,120 @@
#!/usr/bin/env bash

# SPDX-FileCopyrightText: 2026 MDAD project contributors
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later

# Adds a new host to the inventory, based on the example files in `examples/`:
# - creates `inventory/hosts` (or adds the host to it, if it already exists)
# - creates `inventory/host_vars/matrix.DOMAIN/vars.yml` with strong secrets generated automatically
#
# Existing configuration for the same host is never overwritten - the script refuses to run instead.
#
# Usage: bin/add-inventory-host.sh <base-domain> <server-address>
#
# - <base-domain> is the base domain (`example.com`), not the Matrix server hostname (`matrix.example.com`)
# - <server-address> is the server's external IP address or domain name

set -euo pipefail

base_path="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

if [ $# -ne 2 ]; then
echo "Usage: $0 <base-domain> <server-address>" >&2
echo "Example: $0 example.com 1.2.3.4" >&2
exit 1
fi

domain="$1"
server_address="$2"

if ! printf '%s' "${domain}" | grep -Eq '^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+$'; then
echo "Error: '${domain}' does not look like a valid domain name" >&2
exit 1
fi

if ! printf '%s' "${server_address}" | grep -Eq '^[A-Za-z0-9.:_-]+$'; then
echo "Error: '${server_address}' does not look like a valid server address (IP address or domain name)" >&2
exit 1
fi

case "${domain}" in
matrix.*)
echo "Warning: you likely need to pass your base domain (example.com), not the Matrix server hostname (matrix.example.com)." >&2
echo "Proceeding anyway. Your Matrix server hostname will be: matrix.${domain}" >&2
;;
esac

matrix_hostname="matrix.${domain}"
hosts_file="${base_path}/inventory/hosts"
vars_dir="${base_path}/inventory/host_vars/${matrix_hostname}"
vars_file="${vars_dir}/vars.yml"
hosts_entry="${matrix_hostname} ansible_host=${server_address} ansible_ssh_user=root"

if [ -e "${vars_dir}" ]; then
echo "Error: ${vars_dir} already exists. Refusing to overwrite it." >&2
exit 1
fi

if [ -f "${hosts_file}" ]; then
if ! grep -q '^\[matrix_servers\]' "${hosts_file}"; then
echo "Error: ${hosts_file} exists, but does not contain a [matrix_servers] section." >&2
echo "Unrecognized inventory format. Add the host to it manually:" >&2
echo "${hosts_entry}" >&2
exit 1
fi

matrix_hostname_pattern="$(printf '%s' "${matrix_hostname}" | sed 's|\.|\\.|g')"
if grep -Eq "^${matrix_hostname_pattern}([[:space:]]|$)" "${hosts_file}"; then
echo "Error: ${hosts_file} already contains an entry for ${matrix_hostname}. Refusing to modify it." >&2
exit 1
fi
fi

generate_secret() {
if command -v pwgen >/dev/null 2>&1; then
pwgen -s 64 1
elif command -v openssl >/dev/null 2>&1; then
openssl rand -base64 192 | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 64
else
head -c 4096 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 64
fi
}

generic_secret_key="$(generate_secret)"
postgres_password="$(generate_secret)"

for secret in "${generic_secret_key}" "${postgres_password}"; do
if [ "${#secret}" -lt 64 ]; then
echo "Error: failed to generate a secret" >&2
exit 1
fi
done

mkdir -p "${vars_dir}"

sed \
-e "s|^matrix_domain:.*|matrix_domain: ${domain}|" \
-e "s|^matrix_homeserver_generic_secret_key:.*|matrix_homeserver_generic_secret_key: '${generic_secret_key}'|" \
-e "s|^postgres_connection_password:.*|postgres_connection_password: '${postgres_password}'|" \
"${base_path}/examples/vars.yml" > "${vars_file}"

if [ -f "${hosts_file}" ]; then
# Insert the new host right after the [matrix_servers] section header.
hosts_file_tmp="$(mktemp "${hosts_file}.XXXXXX")"
awk -v entry="${hosts_entry}" '{print} $0 ~ /^\[matrix_servers\]/ && !done {print entry; done=1}' \
"${hosts_file}" > "${hosts_file_tmp}"
mv "${hosts_file_tmp}" "${hosts_file}"
else
sed \
-e "s|^matrix\.example\.com .*|${hosts_entry}|" \
"${base_path}/examples/hosts" > "${hosts_file}"
fi

echo "Added host ${matrix_hostname} to the inventory:"
echo "- ${hosts_file}"
echo "- ${vars_file}"
echo ""
echo "Secrets were generated automatically for matrix_homeserver_generic_secret_key and postgres_connection_password."
echo "Review and adjust these files before installing."

+ 119
- 0
bin/check-molecule-automerge-list.py View File

@@ -0,0 +1,119 @@
#!/usr/bin/env python3
"""Keeps Molecule-backed automerge rules in step with the available scenarios.

.github/renovate.json automerges patch bumps for every role with a scenario. A narrower list of
explicitly approved roles also automerges minor bumps. In both cases, the bump runs that role's
Molecule scenario before merging, so the reasoning only holds while the role actually has one.

The patch list must exactly match the scenarios. The minor list must be a subset of it: omission is
an explicit policy choice, while an extra entry would merge a minor bump without the required gate.
"""

import json
import pathlib
import sys

REPO = pathlib.Path(__file__).resolve().parent.parent
RENOVATE = REPO / ".github" / "renovate.json"
PATCH_RULE_MARKER = "bin/check-molecule-automerge-list.py (patch rule)"
MINOR_RULE_MARKER = "bin/check-molecule-automerge-list.py (minor rule)"


def find_rule(config: dict, marker: str) -> dict | None:
rules = [r for r in config.get("packageRules", []) if marker in r.get("description", "")]
if len(rules) != 1:
print(f"Expected exactly one rule mentioning {marker}, found {len(rules)}.", file=sys.stderr)
return None
return rules[0]


def listed_roles(rule: dict, label: str) -> set[str] | None:
listed = set()
for name in rule.get("matchFileNames", []):
parts = pathlib.PurePosixPath(name).parts
if parts[:2] == ("roles", "custom") and parts[3:] == ("defaults", "main.yml"):
listed.add(parts[2])
else:
print(f"Unexpected entry in the Molecule {label} automerge rule: {name}", file=sys.stderr)
return None
return listed


def main() -> int:
with_scenario = {
p.parts[-4] for p in (REPO / "roles" / "custom").glob("*/molecule/default/molecule.yml")
}

config = json.loads(RENOVATE.read_text())
patch_rule = find_rule(config, PATCH_RULE_MARKER)
minor_rule = find_rule(config, MINOR_RULE_MARKER)
if patch_rule is None or minor_rule is None:
return 1

patch_roles = listed_roles(patch_rule, "patch")
minor_roles = listed_roles(minor_rule, "minor")
if patch_roles is None or minor_roles is None:
return 1

errors = False
if set(patch_rule.get("matchUpdateTypes", [])) != {"patch"}:
print("The Molecule patch automerge rule must match only patch updates.", file=sys.stderr)
errors = True
if set(minor_rule.get("matchUpdateTypes", [])) != {"minor"}:
print("The Molecule minor automerge rule must match only minor updates.", file=sys.stderr)
errors = True

automerged_without_scenario = sorted(patch_roles - with_scenario)
scenario_without_automerge = sorted(with_scenario - patch_roles)

if automerged_without_scenario:
print(
"These roles automerge patch bumps but have no Molecule scenario, so nothing would\n"
"exercise the bump before it merges. Remove them from the rule in\n"
".github/renovate.json, or give them a scenario:",
file=sys.stderr,
)
for role in automerged_without_scenario:
print(f" {role}", file=sys.stderr)

if scenario_without_automerge:
print(
"These roles have a Molecule scenario but are not in the automerge rule in\n"
".github/renovate.json, so their patch bumps still need a button press:",
file=sys.stderr,
)
for role in scenario_without_automerge:
print(f" {role}", file=sys.stderr)

minor_without_scenario = sorted(minor_roles - with_scenario)
minor_without_patch = sorted(minor_roles - patch_roles)

if minor_without_scenario:
print(
"These roles automerge minor bumps but have no Molecule scenario:",
file=sys.stderr,
)
for role in minor_without_scenario:
print(f" {role}", file=sys.stderr)

if minor_without_patch:
print(
"These roles automerge minor bumps but are missing from the patch rule:",
file=sys.stderr,
)
for role in minor_without_patch:
print(f" {role}", file=sys.stderr)

return 1 if any(
[
errors,
automerged_without_scenario,
scenario_without_automerge,
minor_without_scenario,
minor_without_patch,
]
) else 0


if __name__ == "__main__":
sys.exit(main())

+ 3
- 0
bin/check-molecule-automerge-list.py.license View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later

+ 90
- 0
bin/molecule-clean.sh View File

@@ -0,0 +1,90 @@
#!/bin/bash
# Removes what `just molecule` leaves under var/.
#
# Called through `just molecule-clean [--idle-days N]`.
#
# Two things accumulate. The per-role Ansible homes are ~7 MB each and are
# rewritten on every run rather than growing, so they are bounded by the number
# of roles that have a scenario. The shared virtualenv is the bulk of it (over
# 500 MB) and is recreated on the next run, which costs a pip install.
#
# Usage:
# just molecule-clean # everything, after showing what and how much
# just molecule-clean --idle-days 14 # only what has not been touched in 14 days
# just molecule-clean --yes # skip the confirmation
#
# --idle-days is what makes this safe to run unattended: a scenario you ran this
# morning keeps its cache, and only roles you have not touched in a while lose
# theirs.

set -euo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
var_dir="${repo_dir}/var"

idle_days=""
assume_yes="false"

while [ $# -gt 0 ]; do
case "$1" in
--idle-days)
idle_days="${2:-}"
if ! [[ "${idle_days}" =~ ^[0-9]+$ ]]; then
echo "--idle-days needs a whole number of days" >&2
exit 1
fi
shift 2
;;
--yes|-y)
assume_yes="true"
shift
;;
*)
echo "Unknown argument: $1" >&2
echo "Usage: just molecule-clean [--idle-days N] [--yes]" >&2
exit 1
;;
esac
done

# Only ever the two directories bin/molecule.sh creates, named explicitly. `var/`
# holds other things and must never be removed wholesale.
targets=()
for candidate in "${var_dir}/molecule-ansible-home" "${var_dir}/molecule-venv"; do
[ -d "${candidate}" ] || continue

if [ -n "${idle_days}" ] && [ -z "$(find "${candidate}" -maxdepth 0 -mtime "+${idle_days}")" ]; then
continue
fi

targets+=("${candidate}")
done

if [ ${#targets[@]} -eq 0 ]; then
if [ -n "${idle_days}" ]; then
echo "Nothing idle for more than ${idle_days} day(s)."
else
echo "Nothing to clean."
fi
exit 0
fi

echo "Would remove:"
for target in "${targets[@]}"; do
printf ' %s %s\n' "$(du -sh "${target}" | cut -f1)" "${target/#$HOME/\~}"
done

if [ "${assume_yes}" != "true" ]; then
read -r -p "Remove these? [y/N] " reply
case "${reply}" in
y|Y|yes|YES) ;;
*) echo "Left alone."; exit 0 ;;
esac
fi

for target in "${targets[@]}"; do
rm -rf "${target}"
echo "Removed ${target/#$HOME/\~}"
done

echo "The virtualenv is recreated on the next \`just molecule\` run."

+ 3
- 0
bin/molecule-clean.sh.license View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later

+ 98
- 0
bin/molecule.sh View File

@@ -0,0 +1,98 @@
#!/bin/bash
# Runs a role's Molecule scenario locally.
#
# Called through `just molecule [role] [args...]`. With no role, lists the roles
# that have a scenario.
#
# The same scenarios run in CI (.github/workflows/molecule.yml), but running one
# here is the faster loop while writing or fixing a role: CI only tells you after
# a push, and only about the roles that push touched.
#
# Deliberately NOT wired into prek. A run takes minutes, pulls container images
# and needs a working Docker - which is fine when you ask for it, and not fine on
# every commit.
#
# Usage:
# just molecule # list roles that have a scenario
# just molecule matrix-alertmanager-receiver
# just molecule matrix-alertmanager-receiver converge # any molecule subcommand
#
# Environment:
# MOLECULE_DISTRO base image to test on (default: ubuntu2604)

set -euo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
roles_dir="${repo_dir}/roles/custom"
venv_dir="${repo_dir}/var/molecule-venv"

list_roles() {
find "${roles_dir}" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' \
| while read -r candidate; do
if [ -f "${roles_dir}/${candidate}/molecule/default/molecule.yml" ]; then
echo "${candidate}"
fi
done \
| sort
}

role="${1:-}"

if [ -z "${role}" ]; then
echo "Roles with a Molecule scenario:"
found="$(list_roles)"
if [ -z "${found}" ]; then
echo " (none yet)"
else
printf ' %s\n' ${found}
fi
echo
echo "Run one with: just molecule <role>"
exit 0
fi

shift || true

if [ ! -f "${roles_dir}/${role}/molecule/default/molecule.yml" ]; then
echo "No Molecule scenario at roles/custom/${role}/molecule/default" >&2
echo >&2
echo "Roles that have one:" >&2
list_roles | sed 's/^/ /' >&2
exit 1
fi

# The virtualenv lives under var/, which is gitignored, and is shared by every
# role - the dependencies are the same for all of them.
if [ ! -x "${venv_dir}/bin/molecule" ]; then
echo "Creating the Molecule virtualenv in ${venv_dir/#$HOME/\~} ..."
python3 -m venv "${venv_dir}"
"${venv_dir}/bin/pip" install --quiet --upgrade pip
"${venv_dir}/bin/pip" install --quiet -r "${repo_dir}/molecule-shared/requirements.txt"
fi

# Galaxy content is installed with `force: true` on every run, so two scenarios
# running at once will re-extract collections and roles into the same directory
# and pull them out from under each other mid-play. It shows up as a collection
# that was working moments earlier going missing:
#
# the connection plugin 'community.docker.docker' was not found
#
# ANSIBLE_HOME relocates both `collections/` and `roles/`, so one variable is
# enough to give each role its own. The scenarios' ANSIBLE_ROLES_PATH follows it.
#
# Unset in CI, where it falls back to ~/.ansible - each role runs in its own job
# there, so there is nothing to collide with and nothing to gain from isolation.
export ANSIBLE_HOME="${ANSIBLE_HOME:-${repo_dir}/var/molecule-ansible-home/${role}}"

export MOLECULE_DISTRO="${MOLECULE_DISTRO:-ubuntu2604}"
export PY_COLORS="${PY_COLORS:-1}"
export ANSIBLE_FORCE_COLOR="${ANSIBLE_FORCE_COLOR:-1}"

echo "Running Molecule for ${role} on ${MOLECULE_DISTRO} ..."
cd "${roles_dir}/${role}"

if [ $# -eq 0 ]; then
exec "${venv_dir}/bin/molecule" test --scenario-name default
fi

exec "${venv_dir}/bin/molecule" "$@" --scenario-name default

+ 3
- 0
bin/molecule.sh.license View File

@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later

+ 0
- 54
bin/rebuild-mautrix-meta-instagram.sh View File

@@ -1,54 +0,0 @@
#!/bin/bash

# SPDX-FileCopyrightText: 2024 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later

set -euxo pipefail

# This script rebuilds the mautrix-meta-instagram Ansible role, using the mautrix-meta-messenger role as a source.

if [ $# -eq 0 ]; then
echo "Error: No argument supplied. Please provide the path to the roles/custom directory."
exit 1
fi

roles_path=$1

messenger_role_path=$roles_path/matrix-bridge-mautrix-meta-messenger
instagram_role_path=$roles_path/matrix-bridge-mautrix-meta-instagram

if [ ! -d $messenger_role_path ]; then
echo "Cannot find: $messenger_role_path"
exit 1
fi

if [ -d $instagram_role_path ]; then
rm -rf $instagram_role_path
fi

cp -ar $messenger_role_path $instagram_role_path

find "$instagram_role_path" -type f | while read -r file; do
sed --in-place 's/matrix_mautrix_meta_messenger_/matrix_mautrix_meta_instagram_/g' "$file"
sed --in-place 's/mautrix-meta-messenger/mautrix-meta-instagram/g' "$file"
done

sed --in-place 's/matrix_mautrix_meta_instagram_meta_mode: \(.*\)/matrix_mautrix_meta_instagram_meta_mode: instagram/g' $instagram_role_path/defaults/main.yml
sed --in-place 's/matrix_mautrix_meta_instagram_identifier: \(.*\)/matrix_mautrix_meta_instagram_identifier: matrix-mautrix-meta-instagram/g' $instagram_role_path/defaults/main.yml

# Create the README.md file with the license header
cat > $instagram_role_path/README.md << 'EOF'
<!--
SPDX-FileCopyrightText: 2024 - 2025 MDAD Contributors

SPDX-License-Identifier: AGPL-3.0-or-later
-->
EOF

echo "" >> $instagram_role_path/README.md
echo "# matrix-mautrix-meta-instagram" >> $instagram_role_path/README.md
echo "" >> $instagram_role_path/README.md
echo "This bridge role is derived from the matrix-mautrix-meta-messenger Ansible role via automatic changes (see \`just rebuild-mautrix-meta-instagram\` or \`bin/rebuild-mautrix-meta-instagram.sh\`)." >> $instagram_role_path/README.md
echo "" >> $instagram_role_path/README.md
echo "If you'd like to make a change to this role, consider making it to the \`matrix-mautrix-meta-messenger\` role instead." >> $instagram_role_path/README.md

+ 21
- 0
collections/requirements.yml View File

@@ -1,4 +1,25 @@
---
# This file is not used by the playbook's standard CLI installation flow.
# Roles are pulled via `make roles` / `just roles`, which call
# `ansible-galaxy install -r requirements.yml -p roles/galaxy/`.
# Collections are not installed by that command, and the playbook relies
# on whatever `community.*` collections ship with the user's `ansible`
# package (which has been recent enough for years).
#
# This file exists for AWX / Ansible Automation Platform users, which
# auto-detect `collections/requirements.yml` during project sync and
# install the listed collections. See:
# https://github.com/spantaleev/matrix-docker-ansible-deploy/commit/87a2240dc
#
# CLI users do not need to install anything from this file. If you are
# using AWX and a collection version below the floor declared here is
# present, AWX will upgrade it.

collections:
- name: community.general
- name: community.docker
# `community.docker.docker_image_pull` and `community.docker.docker_image_build`
# are used by some roles (e.g. matrix-bot-draupnir,
# matrix-appservice-draupnir-for-all) and are first available in
# community.docker 3.6.0 (Jan 2024 / Ansible 9.2.0).
version: ">=3.6.0"

+ 4
- 0
docs/README.md View File

@@ -76,6 +76,8 @@ If your server and services experience issues, feel free to come to [our support

- [Alternative architectures](alternative-architectures.md)

- [Configuring Synology DSM](configuring-playbook-synology.md)

- [Container images used by the playbook](container-images.md)

- [Obtaining an Access Token](obtaining-access-tokens.md)
@@ -88,6 +90,8 @@ If your server and services experience issues, feel free to come to [our support

- [Self-building](self-building.md)

- [Style guide for playbook developers](style-guide.md)

- [Uninstalling](uninstalling.md)

- [Updating users passwords](updating-users-passwords.md)


+ 16
- 2
docs/ansible.md View File

@@ -39,6 +39,18 @@ If using the `pip` method, do note that the `ansible-playbook` binary may not be

**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.

To fix host key errors, connect to the server once (e.g. `ssh root@matrix.example.com`) and confirm the host key. Ansible runs after that will find it in your `known_hosts` file.

If your SSH key is protected by a passphrase, load it into an [ssh-agent](https://man.openbsd.org/ssh-agent) (e.g. `ssh-add ~/.ssh/id_ed25519`), so that SSH does not need to prompt for the passphrase.

**Note**: if you're [using Ansible via Docker](#using-ansible-via-docker), host keys of previously unknown hosts are accepted automatically, so only the passphrase advice above applies to you. For the agent to be reachable inside the container, share its socket by adding `--mount type=bind,src=$SSH_AUTH_SOCK,dst=/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent` to `docker run`. If the key is already loaded into the agent, you do not need to mount the SSH key file into the container at all.

## Using Ansible via Docker

Alternatively, you can run Ansible inside a Docker container (powered by the [ghcr.io/devture/ansible](https://github.com/devture/docker-ansible/pkgs/container/ansible) Docker image).
@@ -50,6 +62,8 @@ This ensures that:

You can either [run Ansible in a container on the Matrix server itself](#running-ansible-in-a-container-on-the-matrix-server-itself) or [run Ansible in a container on another computer (not the Matrix server)](#running-ansible-in-a-container-on-another-computer-not-the-matrix-server).

💡 If you use [Visual Studio Code](https://code.visualstudio.com/) or [GitHub Codespaces](https://github.com/features/codespaces), the playbook also ships a [dev container](https://containers.dev/) 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:
@@ -74,7 +88,7 @@ docker run \
-w /work \
--mount type=bind,src=`pwd`,dst=/work \
--entrypoint=/bin/sh \
ghcr.io/devture/ansible:11.6.0-r0-0
ghcr.io/devture/ansible:14.0.0-r0-3
```

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.
@@ -95,7 +109,7 @@ docker run \
--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:11.6.0-r0-0
ghcr.io/devture/ansible:14.0.0-r0-3
```

The 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.


+ 15
- 0
docs/configuring-captcha.md View File

@@ -15,6 +15,8 @@ Captcha can be enabled for this home server. This file explains how to do that.

The captcha mechanism used is Google's [ReCaptcha](https://www.google.com/recaptcha/). This requires API keys from Google. If your homeserver is Dendrite then [hCapcha](https://www.hcaptcha.com) can be used instead.

If you are using [Matrix Authentication Service](configuring-playbook-matrix-authentication-service.md), captcha is configured there instead (it handles registration), and [Cloudflare Turnstile](https://www.cloudflare.com/application-services/products/turnstile/) is supported as well. See [Matrix Authentication Service](#matrix-authentication-service) below.

## ReCaptcha

### Getting keys
@@ -61,3 +63,16 @@ matrix_dendrite_client_api_recaptcha_api_js_url: 'https://js.hcaptcha.com/1/api.
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](configuring-playbook-matrix-authentication-service.md) 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](http://www.google.com/recaptcha/admin), [Cloudflare Turnstile](https://www.cloudflare.com/application-services/products/turnstile/) and [hCaptcha](https://dashboard.hcaptcha.com/sites/new). 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:

```yaml
# 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'
```

+ 1
- 1
docs/configuring-ipv6.md View File

@@ -109,7 +109,7 @@ If you do have an IPv6 address, it's still worth [using curl](#with-curl) to con
The `devture_systemd_docker_base_ipv6_enabled` setting controls whether container networks will be created with IPv6 support.

Changing this setting subsequently requires manual work (deleting all container networks).
See [I've changed the `devture_systemd_docker_base_ipv6_enabled` setting, but it doesn't seem to have any effect](#i-ve-changed-the-devture_systemd_docker_base_ipv6_enabled-setting-but-it-doesn-t-seem-to-have-any-effect).
See [I've changed the `devture_systemd_docker_base_ipv6_enabled` setting, but it doesn't seem to have any effect](#ive-changed-the-devture_systemd_docker_base_ipv6_enabled-setting-but-it-doesnt-seem-to-have-any-effect).

#### I've changed the `devture_systemd_docker_base_ipv6_enabled` setting, but it doesn't seem to have any effect.



+ 50
- 15
docs/configuring-playbook-appservice-draupnir-for-all.md View File

@@ -1,4 +1,5 @@
<!--
SPDX-FileCopyrightText: 2024 - 2026 Catalan Lover <catalanlover@protonmail.com>
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2024 MDAD project contributors

@@ -13,34 +14,54 @@ Appservice mode can be used together with the regular [Draupnir bot](configuring

## Draupnir Appservice mode compared to Draupnir bot mode

The administrative functions for managing the appservice are alpha quality and very limited. However, the experience of using an appservice-provisioned Draupnir is on par with the experience of using Draupnir from bot mode except in the case of avatar customisation as described later on in this document.
The administrative functions for managing the appservice are alpha quality and very limited. However, the experience of using an appservice-provisioned Draupnir is on par with the experience of using Draupnir from bot mode.

Draupnir for all is the way to go if you need more than 1 Draupnir instance, but you don't need access to Synapse Admin features as they are not accessible through Draupnir for All (Even though the commands do show up in help).
Draupnir for all is the way to go if you need more than 1 Draupnir instance, but you don't need access to Synapse Admin features as they are not accessible through Draupnir for All.

Draupnir for all in the playbook is rate-limit-exempt automatically as its appservice configuration file does not specify any rate limits.

Normal Draupnir does come with the benefit of access to Synapse Admin features. You are also able to more easily customise your normal Draupnir than D4A as D4A even on the branch with the Avatar command (To be Upstreamed to Mainline Draupnir) that command is clunky as it requires the use of things like Element Web devtools. In normal Draupnir this is a quick operation where you login to Draupnir with a normal client and set Avatar and Display name normally.
Normal Draupnir does come with the benefit of access to Synapse Admin features. You are also able to more easily customise your normal Draupnir than D4A as the avatar command is clunky as it requires the use of things like Element Web devtools. In normal Draupnir this can be done while logged in to the Draupnir account with a normal client and set Avatar and Display name normally.

Draupnir for all does not support external tooling like [MRU](https://mru.rory.gay) as it can't access Draupnir's user account.
Draupnir for all only has limited support for external tooling like [MRU](https://mru.rory.gay) as it can't access Draupnir's user account.

## Prerequisites

### Create a main management room
### Prerequisites for Zero Touch Deployment (recommended)

The playbook does not create a management room for your Main Draupnir. You **need to create the room manually** before setting up the bot.
As of Draupnir 3.1.0, Zero Touch Deployment of Draupnir Appservice Mode (Draupnir for all) requires you to supply the following:

- MXID of the first person who gets invited to the admin room that the bot creates for you.

That is all. The appservice manages everything on its own after you provide it with an MXID to invite.

If proceeding with Zero Touch Deployment, skip ahead to [Adjusting the playbook configuration](#adjusting-the-playbook-configuration).

### Create an admin room (optional)

The playbook does not create an admin room for your Draupnir, but the appservice itself can do this for you. Alternatively, you **can create the room manually** before setting up the bot.

Note that the room must be unencrypted.

The management room has to be given an alias, and your bot has to be invited to the room.
The admin room has to be given an alias, and your bot has to be invited to the room.

This management room is used to control who has access to your D4A deployment. The room stores this data inside of the control room state so your bot must have sufficient powerlevel to send custom state events. This is default 50 or moderator as Element clients call this powerlevel.
This admin room is used to control who has access to your D4A deployment. The room stores this data in the control room state, so your bot must have sufficient power level to send custom state events. This is `50` by default (moderator, as Element clients call this power level).

> [!WARNING]
> Anyone in this room can control the bot so it is important that you only invite trusted users to this room.

## Adjusting the playbook configuration

Add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file. Make sure to replace `MANAGEMENT_ROOM_ALIAS_HERE`.
When using Zero Touch Deployment, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file. Make sure to replace `INITIAL_MANAGER_MXID_HERE` with the MXID of the user who should be invited to the admin room first.

```yaml
matrix_appservice_draupnir_for_all_enabled: true

matrix_appservice_draupnir_for_all_zero_touch_deploy: true

matrix_appservice_draupnir_for_all_config_initialManager: "INITIAL_MANAGER_MXID_HERE"
```

If opting out of Zero Touch Deployment, use the following configuration block instead. Make sure to replace `MANAGEMENT_ROOM_ALIAS_HERE` with the alias of the admin room you have created earlier.

```yaml
matrix_appservice_draupnir_for_all_enabled: true
@@ -48,6 +69,14 @@ matrix_appservice_draupnir_for_all_enabled: true
matrix_appservice_draupnir_for_all_config_adminRoom: "MANAGEMENT_ROOM_ALIAS_HERE"
```

### Running both bot mode and appservice mode

When running both [bot mode](./configuring-playbook-bot-draupnir.md) and appservice mode, the playbook will force-restart
the bot if running a non-release tag like `latest` or `main` or a development build.
This is due to the conditional restart logic not being able to reliably tell when an update happened.

Conditional restarts work correctly for all tags when running only one of these two operating modes.

### Extending the configuration

There are some additional things you may wish to configure about the component.
@@ -95,20 +124,26 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start

## Usage

If you made it through all the steps above and your main control room was joined by a user called `@draupnir-main:example.com` you have successfully installed Draupnir for All and can now start using it.
If you made it through all the steps above and your main control room was joined by a user called `@draupnir-main:example.com`, you have successfully installed Draupnir for All and can now start using it.

If using Zero Touch Deployment, the flow is reversed and the success signal is the initial manager account being invited to the admin room.

The installation of Draupnir for all in this playbook is very much Alpha quality. Usage-wise, Draupnir for all is almost identical to Draupnir bot mode.
Draupnir for all installation via this playbook is very much Alpha quality. Usage-wise, Draupnir for all is almost identical to Draupnir bot mode, except that protections requiring homeserver admin access are not available, and the config file is shared between all bots so legacy protections like wordlist share a single global config.

### Granting Users the ability to use D4A

Draupnir for all includes several security measures like that it only allows users that are on its allow list to ask for a bot. To add a user to this list we have 2 primary options. Using the chat to tell Draupnir to do this for us or if you want to automatically do it by sending `m.policy.rule.user` events that target the subject you want to allow provisioning for with the `org.matrix.mjolnir.allow` recommendation. Using the chat is recommended.

The bot requires a powerlevel of 50 in the management room to control who is allowed to use the bot. The bot does currently not say anything if this is true or false. (This is considered a bug and is documented in issue [#297](https://github.com/the-draupnir-project/Draupnir/issues/297))
The bot requires a power level of 50 in the management room to control who is allowed to use the bot. The bot does currently not say anything if this is true or false. (This is considered a bug and is documented in issue [#297](https://github.com/the-draupnir-project/Draupnir/issues/297).) This issue is largely mitigated by the Zero Touch Deployment workflows introduced in Draupnir 3.1.0.

To allow users or whole homeservers you type /plain !admin allow `target` and target can be either a MXID or a wildcard like `@*:example.com` to allow all users on example.com to register. We use /plain to force the client to not attempt to mess with this command as it can break Wildcard commands especially.
To allow users or whole homeservers you type /plain !admin allow `target` and target can be either a MXID or a wildcard like `@*:example.com` to allow all users on example.com to provision a bot. We use /plain to force the client to not attempt to mess with this command as it can break Wildcard commands especially.

### How to provision a D4A once you are allowed to

To provision a D4A, you need to start a chat with `@draupnir-main:example.com`. The bot will reject this invite and you will shortly get invited to the Draupnir control room for your newly provisioned Draupnir. From here its just a normal Draupnir experience.
Once someone is allowed to provision a bot, simply provision them one with `!admin provision MXID`.

Self-service provisioning is disabled as a security measure because it is currently bugged. Force-provisioning (with `!admin provision`) bypasses this disabled status.

Note that you should always make sure there is an allow entry matching whoever is provisioned, because once self-service is fixed, the bot of anyone who is not allowed to provision a bot will refuse to start.

Congratulations if you made it all the way here because you now have a fully working Draupnir for all deployment.
Congratulations if you made it all the way here, because you now have a fully working Draupnir for all deployment.

+ 40
- 4
docs/configuring-playbook-bot-baibot.md View File

@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later

🤖 [baibot](https://github.com/etkecc/baibot) (pronounced bye-bot) is a [Matrix](https://matrix.org/) bot developed by [etke.cc](https://etke.cc/) that exposes the power of [AI](https://en.wikipedia.org/wiki/Artificial_intelligence) / [Large Language Models](https://en.wikipedia.org/wiki/Large_language_model) to you. 🤖

It supports [OpenAI](https://openai.com/)'s [ChatGPT](https://openai.com/blog/chatgpt/) models, as many well as other [☁️ providers](https://github.com/etkecc/baibot/blob/main/docs/providers.md).
It supports many [☁️ providers](https://github.com/etkecc/baibot/blob/main/docs/providers.md), including the privacy-first [Venice](#venice) we recommend, [OpenAI](https://openai.com/)'s [ChatGPT](https://openai.com/blog/chatgpt/) models, and more.

It's designed as a more private and [✨ featureful](https://github.com/etkecc/baibot/?tab=readme-ov-file#-features) alternative to [matrix-chatgpt-bot](./configuring-playbook-bot-chatgpt.md). See the [baibot](https://github.com/etkecc/baibot) project and its documentation for more information.

@@ -159,7 +159,38 @@ Agents defined statically and those created dynamically (via chat) are named dif

Depending on your propensity for [GitOps](https://en.wikipedia.org/wiki/DevOps#GitOps), you may prefer to define agents statically via Ansible, or you may wish to do it dynamically via chat.

Before proceeding, we recommend reading the upstream documentation on [How to choose a provider](https://github.com/etkecc/baibot/blob/main/docs/providers.md#how-to-choose-a-provider). In short, it's probably best to go with [OpenAI](#openai).
Before proceeding, we recommend reading the upstream documentation on [How to choose a provider](https://github.com/etkecc/baibot/blob/main/docs/providers.md#how-to-choose-a-provider) for a side-by-side of what each one can do. In short: we recommend [Venice](#venice), the most capable provider baibot supports and the only one that keeps no logs and trains on nothing. If you'd rather start with the most widely-used option, [OpenAI](#openai) is a solid, well-supported choice too.

#### Venice

[Venice](https://venice.ai/chat?ref=kpXDe6) _(ref link with a $10 bonus for you)_ is the provider we recommend. It's the most capable one baibot supports, and the only one that pairs that full feature set with real privacy: inference runs on Venice's own GPUs or on zero-data-retention partner hardware, so your prompts and replies are stored nowhere and never used for training. It serves both frontier proprietary models and the latest open-source ones.

Venice also leaves the content policy to you instead of imposing its own. Its models answer without the reflexive refusals some hosted services apply, and both text and image generation can handle adult or otherwise sensitive subjects when you need them to. Image generation ships a `safe_mode` that blurs adult content by default; you can turn it off (see the sample config). This pairs naturally with the privacy above: a bot you can speak to candidly, that keeps nothing.

Unlike the [OpenAI Compatible](#openai-compatible) provider (which can also point at Venice, but drops images and can't reach its audio or native image endpoints), this is a first-class integration that exposes Venice's full parameter set: text-generation with vision, file inputs, prompt caching and native web search, plus speech-to-text, text-to-speech, and image generation and editing.

You can statically-define a single [🤖 agent](https://github.com/etkecc/baibot/blob/main/docs/agents.md) instance powered by the [Venice provider](https://github.com/etkecc/baibot/blob/main/docs/providers.md#venice) with the help of the playbook's preset variables.

Here's an example **addition** to your `vars.yml` file:

```yaml
matrix_bot_baibot_config_agents_static_definitions_venice_enabled: true

matrix_bot_baibot_config_agents_static_definitions_venice_config_api_key: "YOUR_API_KEY_HERE"

# The preset ships sensible defaults for every purpose, so changing only the API key above is enough
# to get going. Uncomment and adjust any of these if you'd like to use different models:
# matrix_bot_baibot_config_agents_static_definitions_venice_config_text_generation_model_id: kimi-k2-5
# matrix_bot_baibot_config_agents_static_definitions_venice_config_image_generation_model_id: chroma
```

Because this is a [statically](https://github.com/etkecc/baibot/blob/main/docs/configuration/README.md#static-configuration)-defined agent, it will be given a `static/` ID prefix and will be named `static/venice`.

Every Venice knob (sampling, caching, reasoning, web-search behavior, voice and image controls) has a matching `matrix_bot_baibot_config_agents_static_definitions_venice_config_*` variable. The [fully-commented sample config](https://github.com/etkecc/baibot/blob/main/docs/sample-provider-configs/venice.yml) explains every one of them.

If you'd like to use more than one model, take a look at the [Configuring additional agents (without a preset)](#configuring-additional-agents-without-a-preset) section below.

💡 You may also wish to use this new agent for [🤝 Configuring initial default handlers](#-configuring-initial-default-handlers).

#### Anthropic

@@ -268,6 +299,11 @@ matrix_bot_baibot_config_agents_static_definitions_openai_config_api_key: "YOUR_
# See: https://github.com/etkecc/baibot/blob/61d18b2/docs/features.md#%EF%B8%8F-built-in-tools-openai-only
# matrix_bot_baibot_config_agents_static_definitions_openai_config_text_generation_tools_web_search: true
# matrix_bot_baibot_config_agents_static_definitions_openai_config_text_generation_tools_code_interpreter: true

# Image generation and editing use GPT Image 2.5 Sunburst by default.
# matrix_bot_baibot_config_agents_static_definitions_openai_config_image_generation_model_id: gpt-image-2.5-sunburst
# Quality options: low, medium, high, xhigh, max, auto. null uses the model default.
# matrix_bot_baibot_config_agents_static_definitions_openai_config_image_generation_quality: null
```

Because this is a [statically](https://github.com/etkecc/baibot/blob/main/docs/configuration/README.md#static-configuration)-defined agent, it will be given a `static/` ID prefix and will be named `static/openai`.
@@ -374,7 +410,7 @@ Example **additional** `vars.yml` configuration:
# As such, changing any of these values subsequently has no effect on the bot's behavior.
# Once initially configured, the global configuration is managed via bot commands, not via Ansible.

matrix_bot_baibot_config_initial_global_config_handler_catch_all: static/openai
matrix_bot_baibot_config_initial_global_config_handler_catch_all: static/venice

# In this example, there's no need to define any of these below.
# Configuring the catch-all purpose handler is enough.
@@ -414,7 +450,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_baibot_config_user_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_baibot_config_user_password` to let the bot know its new password. (This note applies to password authentication mode.)
- If you change the bot password (`matrix_bot_baibot_config_user_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_baibot_config_user_password` to let the bot know its new password. (This note applies to password authentication mode.)

## Usage



+ 1
- 1
docs/configuring-playbook-bot-buscarron.md View File

@@ -89,7 +89,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_buscarron_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_buscarron_password` to let the bot know its new password.
- If you change the bot password (`matrix_bot_buscarron_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_buscarron_password` to let the bot know its new password.

## Usage



+ 70
- 12
docs/configuring-playbook-bot-draupnir.md View File

@@ -1,4 +1,5 @@
<!--
SPDX-FileCopyrightText: 2023 - 2026 Catalan Lover <catalanlover@protonmail.com>
SPDX-FileCopyrightText: 2023 - 2025 MDAD project contributors
SPDX-FileCopyrightText: 2023 Kim Brose
SPDX-FileCopyrightText: 2024 - 2025 Slavi Pantaleev
@@ -15,19 +16,35 @@ See the project's [documentation](https://the-draupnir-project.github.io/draupni

This documentation page is about installing Draupnir in bot mode. As an alternative, you can run a multi-instance Draupnir deployment by installing [Draupnir in appservice mode](./configuring-playbook-appservice-draupnir-for-all.md) (called Draupnir-for-all) instead.

If your migrating from [Mjolnir](configuring-playbook-bot-mjolnir.md), skip to [this section](#migrating-from-mjolnir-only-required-if-migrating).
**Note**: you can also use the [Meowlnir](configuring-playbook-bot-meowlnir.md) or [Mjolnir](configuring-playbook-bot-mjolnir.md) bots, which speak the same [policy list](https://the-draupnir-project.github.io/draupnir-documentation/concepts/policy-lists) protocol.

When migrating from [Mjolnir](configuring-playbook-bot-mjolnir.md), skip to [this section](#migrating-from-mjolnir-only-required-if-migrating).

## Prerequisites

### Create a management room
### Prerequisites for Zero Touch Deployment (recommended)

As of Draupnir 3.1.0, Zero Touch Deployment of Draupnir bot mode requires you to supply the following:

- MXID of the first person who gets invited to the management room that the bot creates for you.
- A permanent access token for authentication. Instructions for obtaining one can be found at [obtain an access token via curl](obtaining-access-tokens.md#obtain-an-access-token-via-curl).
- A user account for Draupnir.

Zero Touch Deployment is the officially preferred installation method for new deployments of Draupnir as of 3.1.0.

### Create a management room (optional)

Using your own account, create a new invite only room that you will use to manage the bot. This is the room where you will see the status of the bot and where you will send commands to the bot, such as the command to ban a user from another room.

> [!WARNING]
> Anyone in this room can control the bot so it is important that you only invite trusted users to this room.

The bot also needs at least a Moderator power level (50) in this room. This power level is granted in a [later step](#create-and-invite-the-bot-to-the-management-room-only-when-using-native-login-without-zero-touch-deployment), after the bot gets invited to the room.

It is possible to make the management room encrypted (E2EE). If doing so, then you need to enable the native E2EE support (see [below](#native-e2ee-support)).

E2EE support for the management room is mutually exclusive with Zero Touch Deployment of Draupnir.

Once you have created the room you need to copy the room ID so you can specify it on your `inventory/host_vars/matrix.example.com/vars.yml` file. In Element Web you can check the ID by going to the room's settings and clicking "Advanced". The room ID will look something like `!qporfwt:example.com`.

## End-to-End Encryption support
@@ -63,7 +80,25 @@ matrix_bot_draupnir_config_accessToken: "CLEAN_ACCESS_TOKEN_HERE"

## Adjusting the playbook configuration

To enable the bot, add the following configuration to your `vars.yml` file. Make sure to replace `MANAGEMENT_ROOM_ID_HERE` with the one of the room which you have created earlier.
### Configuration for Zero Touch Deployment (recommended)

To enable the bot using Zero Touch Deployment, add the following configuration to your `vars.yml` file. Make sure to replace `INITIAL_MANAGER_MXID_HERE` with the MXID of the user who should be invited to the management room first, and `CLEAN_ACCESS_TOKEN_HERE` with the access token you obtained.

```yaml
# Enable Draupnir
matrix_bot_draupnir_enabled: true

matrix_bot_draupnir_zero_touch_deploy: true

matrix_bot_draupnir_config_initialManager: "INITIAL_MANAGER_MXID_HERE"

# Access token which the bot will use for logging in.
matrix_bot_draupnir_config_accessToken: "CLEAN_ACCESS_TOKEN_HERE"
```

### Configuration without Zero Touch Deployment

If you'd prefer to have the bot manage its own login at the cost of having to create the management room manually, you can use native login with the configuration block below. Make sure to replace `MANAGEMENT_ROOM_ID_HERE` with the ID of the management room you have created earlier.

```yaml
# Enable Draupnir
@@ -82,7 +117,15 @@ matrix_bot_draupnir_login_native: true
matrix_bot_draupnir_config_managementRoom: "MANAGEMENT_ROOM_ID_HERE"
```

### Create and invite the bot to the management room
### Running both bot mode and appservice mode

When running both bot mode and [appservice mode (Draupnir for all)](./configuring-playbook-appservice-draupnir-for-all.md), the
playbook will force-restart the bot if running a non-release tag like `latest` or `main` or a development build.
This is due to the conditional restart logic not being able to reliably tell when an update happened.

Conditional restarts work correctly for all tags when running only one of these two operating modes.

### Create and invite the bot to the management room (only when using native login without Zero Touch Deployment)

Before proceeding to the next step, run the playbook with the following command to create the bot user.

@@ -94,6 +137,19 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

Then, invite the bot (`@bot.draupnir:example.com`) to its management room which you have created earlier.

After the bot joins, give it at least a Moderator power level (50) in the management room.

> [!WARNING]
> Draupnir stores each protection's settings as custom state events in the management room, and sending those requires a power level of 50 by default. A bot without this power level cannot save any protection settings. The failure is easy to miss and has nasty consequences: the `PolicyChangeNotification` protection, unable to remember its notifications room, will create a brand new one on every restart of the bot (and the playbook restarts it on every installation run), littering your server with abandoned rooms.

This is not a concern for Zero Touch Deployment, where the bot creates the management room itself and has full control over it.

### Creating a user account for the bot (when using Zero Touch Deployment)

Since Zero Touch Deployment is not validated with native login, you will need to create the user account manually.

Refer to [registering users](registering-users.md) for documentation on how to configure the user account.

### Make sure the account is free from rate limiting (optional, recommended)

If your homeserver's implementation is Synapse, you will need to prevent it from rate limiting the bot's account. **This is a highly recommended step. If you do not configure it, Draupnir performance will be degraded.**
@@ -102,11 +158,11 @@ This can be done using Synapse's [Admin APIs](https://element-hq.github.io/synap

**Note**: access to the APIs is restricted with a valid access token, so exposing them publicly should not be a real security concern. Still, doing so is not recommended for additional security. See [official Synapse reverse-proxying recommendations](https://element-hq.github.io/synapse/latest/reverse_proxy.html#synapse-administration-endpoints).

The APIs can also be accessed via [Synapse Admin](https://github.com/etkecc/synapse-admin), a web UI tool you can use to administrate users, rooms, media, etc. on your Matrix server. The playbook can install and configure Synapse Admin for you. For details about it, see [this page](configuring-playbook-synapse-admin.md).
The APIs can also be accessed via [Ketesa](https://github.com/etkecc/ketesa), a web UI tool you can use to administrate users, rooms, media, etc. on your Matrix server. The playbook can install and configure Ketesa for you. For details about it, see [this page](configuring-playbook-ketesa.md).

#### Add the configuration

To expose the APIs publicly, add the following configuration to your `vars.yml` file:
This is automatically done if Ketesa is enabled. Otherwise, to expose the APIs publicly, add the following configuration to your `vars.yml` file:

```yaml
matrix_synapse_container_labels_public_client_synapse_admin_api_enabled: true
@@ -132,6 +188,7 @@ curl --header "Authorization: Bearer ADMIN_ACCESS_TOKEN_HERE" -X POST https://ma
```

**Notes**:

- This does not work on outdated Windows 10 as curl is not available there.
- Even if the APIs are not exposed to the internet, you should still be able to run the command on the homeserver locally.

@@ -157,13 +214,14 @@ matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled: true
matrix_bot_draupnir_admin_api_enabled: true
```

These protections need to be manually activated and consulting the [enabling protections](#enabling-built-in-protections) guide can be helpful or consulting upstream documentation.
These protections need to be manually activated. Consulting the [enabling protections](#enabling-built-in-protections) guide and/or upstream documentation can be helpful.

<!--
NOTE: this is unsupported by the playbook due to the admin API being inaccessible from containers currently.
The other method polls a Synapse Admin API endpoint, hence it is available only if using Synapse and if the Draupnir user is an admin. To enable it, set `pollReports: true` in your `vars.yml` file as below:

The other method polls an Synapse Admin API endpoint, hence it is available only if using Synapse and if the Draupnir user is an admin (see [above](#register-the-bot-account)). To enable it, set `pollReports: true` on `vars.yml` file as below.
-->
```yaml
matrix_bot_draupnir_configuration_extension_yaml: |
pollReports: true
```

### Extending the configuration

@@ -212,7 +270,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_draupnir_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_draupnir_password` to let the bot know its new password.
- If you change the bot password (`matrix_bot_draupnir_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_draupnir_password` to let the bot know its new password.

## Usage



+ 11
- 252
docs/configuring-playbook-bot-go-neb.md View File

@@ -1,267 +1,26 @@
<!--
SPDX-FileCopyrightText: 2021 - 2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2019-2025 Slavi Pantaleev
SPDX-FileCopyrightText: 2021 Yannick Goossens
SPDX-FileCopyrightText: 2022 Dennis Ciba
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2025 MDAD project contributors
SPDX-FileCopyrightText: 2022 Nikita Chernyi
SPDX-FileCopyrightText: 2023-2025 MDAD project contributors
SPDX-FileCopyrightText: 2024-2026 Suguru Hirahara

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Go-NEB (optional, unmaintained)
# Setting up Go-NEB (optional, removed)

**Note**: [Go-NEB](https://github.com/matrix-org/go-neb) is now an archived (**unmaintained**) project. We recommend not bothering with installing it. While not a 1:1 replacement, the bridge's author suggests taking a look at [matrix-hookshot](https://github.com/matrix-org/matrix-hookshot) as a replacement, which can also be [installed using this playbook](configuring-playbook-bridge-hookshot.md). Consider using that bot instead of this one.
🪦 The playbook used to be able to install and configure [Go-NEB](https://github.com/matrix-org/go-neb), but no longer includes this component as it has been discontinued.

The playbook can install and configure [Go-NEB](https://github.com/matrix-org/go-neb) for you.
While not a 1:1 replacement, the bot's author suggests taking a look at [matrix-hookshot](https://github.com/matrix-org/matrix-hookshot) as a replacement, which can also be [installed using this playbook](configuring-playbook-bridge-hookshot.md).

Go-NEB is a Matrix bot written in Go. It is the successor to Matrix-NEB, the original Matrix bot written in Python.
## Uninstalling Go-NEB manually

See the project's [documentation](https://github.com/matrix-org/go-neb/blob/master/README.md) to learn what it does and why it might be useful to you.

## Prerequisites

### Register the bot account

The playbook does not automatically create users for you. You **need to register the bot user manually** before setting up the bot.

Generate a strong password for the bot. You can create one with a command like `pwgen -s 64 1`.

You can use the playbook to [register a new user](registering-users.md):
If you still have the Go-NEB component installed on your Matrix server, the playbook can no longer help you uninstall it and you will need to do it manually. To uninstall manually, run these commands on the server:

```sh
ansible-playbook -i inventory/hosts setup.yml --extra-vars='username=bot.go-neb password=PASSWORD_FOR_THE_BOT admin=no' --tags=register-user
```

### Obtain an access token

The bot requires an access token to be able to connect to your homeserver. Refer to the documentation on [how to obtain an access token](obtaining-access-tokens.md).

> [!WARNING]
> Access tokens are sensitive information. Do not include them in any bug reports, messages, or logs. Do not share the access token with anyone.

## Adjusting DNS records

By default, this playbook installs Go-NEB on the `goneb.` subdomain (`goneb.example.com`) and requires you to create a CNAME record for `goneb`, which targets `matrix.example.com`.

When setting, replace `example.com` with your own.

## Adjusting the playbook configuration

To enable the bot, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file. Make sure to replace `ACCESS_TOKEN_FOR_GONEB_HERE` and `ACCESS_TOKEN_FOR_ANOTHER_GONEB_HERE` with the ones created [above](#obtain-an-access-token).

```yaml
matrix_bot_go_neb_enabled: true

# You need at least 1 client.
# Use the access token you obtained in the step above.
matrix_bot_go_neb_clients:
- UserID: "@goneb:{{ matrix_domain }}"
AccessToken: "ACCESS_TOKEN_FOR_GONEB_HERE"
DeviceID: "DEVICE1"
HomeserverURL: "{{ matrix_addons_homeserver_client_api_url }}"
Sync: true
AutoJoinRooms: true
DisplayName: "Go-NEB!"
AcceptVerificationFromUsers: [":{{ matrix_domain }}"]

- UserID: "@another_goneb:{{ matrix_domain }}"
AccessToken: "ACCESS_TOKEN_FOR_ANOTHER_GONEB_HERE"
DeviceID: "DEVICE2"
HomeserverURL: "{{ matrix_addons_homeserver_client_api_url }}"
Sync: false
AutoJoinRooms: false
DisplayName: "Go-NEB!"
AcceptVerificationFromUsers: ["^@admin:{{ matrix_domain }}"]

# Optional, for use with the github_cmd, github_webhooks or jira services
matrix_bot_go_neb_realms:
- ID: "github_realm"
Type: "github"
Config: {} # No need for client ID or Secret as Go-NEB isn't generating OAuth URLs

# Optional. The list of *authenticated* sessions which Go-NEB is aware of.
matrix_bot_go_neb_sessions:
- SessionID: "your_github_session"
RealmID: "github_realm"
UserID: "@alice:{{ matrix_domain }}" # This needs to be the username of the person that's allowed to use the !github commands
Config:
# Populate these fields by generating a "Personal Access Token" on github.com
AccessToken: "YOUR_GITHUB_ACCESS_TOKEN"
Scopes: "admin:org_hook,admin:repo_hook,repo,user"

# The list of services which Go-NEB is aware of.
# Delete or modify this list as appropriate.
# See the docs for /configureService for the full list of options:
# https://matrix-org.github.io/go-neb/pkg/github.com/matrix-org/go-neb/api/index.html#ConfigureServiceRequest
# You need at least 1 service.
matrix_bot_go_neb_services:
- ID: "echo_service"
Type: "echo"
UserID: "@goneb:{{ matrix_domain }}"
Config: {}

# Can be obtained from https://developers.giphy.com/dashboard/
- ID: "giphy_service"
Type: "giphy"
UserID: "@goneb:{{ matrix_domain }}" # requires a Syncing client
Config:
api_key: "qwg4672vsuyfsfe"
use_downsized: false

# This service has been dead for over a year :/
- ID: "guggy_service"
Type: "guggy"
UserID: "@goneb:{{ matrix_domain }}" # requires a Syncing client
Config:
api_key: "2356saaqfhgfe"

# API Key via https://developers.google.com/custom-search/v1/introduction
# CX via http://www.google.com/cse/manage/all
# https://stackoverflow.com/questions/6562125/getting-a-cx-id-for-custom-search-google-api-python
# 'Search the entire web' and 'Image search' enabled for best results
- ID: "google_service"
Type: "google"
UserID: "@goneb:{{ matrix_domain }}" # requires a Syncing client
Config:
api_key: "AIzaSyA4FD39m9"
cx: "AIASDFWSRRtrtr"

# Obtain a key via https://api.imgur.com/oauth2/addclient
# Select "oauth2 without callback url"
- ID: "imgur_service"
Type: "imgur"
UserID: "@imgur:{{ matrix_domain }}" # requires a Syncing client
Config:
client_id: "AIzaSyA4FD39m9"
client_secret: "somesecret"

- ID: "wikipedia_service"
Type: "wikipedia"
UserID: "@goneb:{{ matrix_domain }}" # requires a Syncing client
Config:

- ID: "rss_service"
Type: "rssbot"
UserID: "@another_goneb:{{ matrix_domain }}"
Config:
feeds:
"http://lorem-rss.herokuapp.com/feed?unit=second&interval=60":
rooms: ["!qporfwt:{{ matrix_domain }}"]
must_include:
author:
- author1
description:
- lorem
- ipsum
must_not_include:
title:
- Lorem
- Ipsum

- ID: "github_cmd_service"
Type: "github"
UserID: "@goneb:{{ matrix_domain }}" # requires a Syncing client
Config:
RealmID: "github_realm"

# Make sure your BASE_URL can be accessed by Github!
- ID: "github_webhook_service"
Type: "github-webhook"
UserID: "@another_goneb:{{ matrix_domain }}"
Config:
RealmID: "github_realm"
ClientUserID: "@alice:{{ matrix_domain }}" # needs to be an authenticated user so Go-NEB can create webhooks. Check the UserID field in the github_realm in matrix_bot_go_neb_sessions.
Rooms:
"!qporfwt:example.com":
Repos:
"element-hq/synapse":
Events: ["push", "issues"]
"matrix-org/dendron":
Events: ["pull_request"]
"!aaabaa:example.com":
Repos:
"element-hq/synapse":
Events: ["push", "issues"]
"matrix-org/dendron":
Events: ["pull_request"]
systemctl disable --now matrix-bot-go-neb.service

- ID: "slackapi_service"
Type: "slackapi"
UserID: "@slackapi:{{ matrix_domain }}"
Config:
Hooks:
"hook1":
RoomID: "!qporfwt:example.com"
MessageType: "m.text" # default is m.text

- ID: "alertmanager_service"
Type: "alertmanager"
UserID: "@alertmanager:{{ matrix_domain }}"
Config:
# This is for information purposes only. It should point to Go-NEB path as follows:
# `/services/hooks/<base64 encoded service ID>`
# Where in this case "service ID" is "alertmanager_service"
# Make sure your BASE_URL can be accessed by the Alertmanager instance!
webhook_url: "http://localhost/services/hooks/YWxlcnRtYW5hZ2VyX3NlcnZpY2U"
# Each room will get the notification with the alert rendered with the given template
rooms:
"!qporfwt:example.com":
text_template: "{% raw %}{{range .Alerts -}} [{{ .Status }}] {{index .Labels \"alertname\" }}: {{index .Annotations \"description\"}} {{ end -}}{% endraw %}"
html_template: "{% raw %}{{range .Alerts -}} {{ $severity := index .Labels \"severity\" }} {{ if eq .Status \"firing\" }} {{ if eq $severity \"critical\"}} <font color='red'><b>[FIRING - CRITICAL]</b></font> {{ else if eq $severity \"warning\"}} <font color='orange'><b>[FIRING - WARNING]</b></font> {{ else }} <b>[FIRING - {{ $severity }}]</b> {{ end }} {{ else }} <font color='green'><b>[RESOLVED]</b></font> {{ end }} {{ index .Labels \"alertname\"}} : {{ index .Annotations \"description\"}} <a href=\"{{ .GeneratorURL }}\">source</a><br/>{{end -}}{% endraw %}"
msg_type: "m.text" # Must be either `m.text` or `m.notice`
```

### Adjusting the Go-NEB URL (optional)

By tweaking the `matrix_bot_go_neb_hostname` and `matrix_bot_go_neb_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.

Example additional configuration for your `vars.yml` file:

```yaml
# Switch to the domain used for Matrix services (`matrix.example.com`),
# so we won't need to add additional DNS records for Go-NEB.
matrix_bot_go_neb_hostname: "{{ matrix_server_fqn_matrix }}"

# Expose under the /go-neb subpath
matrix_bot_go_neb_path_prefix: /go-neb
rm -rf /matrix/go-neb
```

After changing the domain, **you may need to adjust your DNS** records to point the Go-NEB domain to the Matrix server.

If you've decided to reuse the `matrix.` domain, you won't need to do any extra DNS configuration.

### Extending the configuration

There are some additional things you may wish to configure about the bot.

Take a look at:

- `roles/custom/matrix-bot-go-neb/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bot-go-neb/templates/config.yaml.j2` for the bot's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bot_go_neb_configuration_extension_yaml` variable

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records), run the playbook with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

To use the bot, invite it to any existing Matrix room (`/invite @bot.go-neb:example.com` where `example.com` is your base domain, not the `matrix.` domain). Make sure you are granted with the sufficient permission if you are not the room owner.

Basic usage is like this: `!echo hi` or `!imgur puppies` or `!giphy matrix`

If you enabled the github_cmd service, send `!github help` to the bot in the room to see the available commands.

You can also refer to the upstream [Documentation](https://github.com/matrix-org/go-neb).

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-bot-go-neb`.

+ 1
- 1
docs/configuring-playbook-bot-honoroit.md View File

@@ -78,7 +78,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_honoroit_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_honoroit_password` to let the bot know its new password.
- If you change the bot password (`matrix_bot_honoroit_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_honoroit_password` to let the bot know its new password.

## Usage



+ 19
- 88
docs/configuring-playbook-bot-matrix-registration-bot.md View File

@@ -1,103 +1,34 @@
<!--
SPDX-FileCopyrightText: 2022 - 2023 Julian-Samuel Gebühr
SPDX-FileCopyrightText: 2022 - 2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2019 Edgars Voroboks
SPDX-FileCopyrightText: 2019 Eduardo Beltrame
SPDX-FileCopyrightText: 2019-2025 MDAD project contributors
SPDX-FileCopyrightText: 2019-2025 Slavi Pantaleev
SPDX-FileCopyrightText: 2020 Chris van Dijk
SPDX-FileCopyrightText: 2020 Tulir Asokan
SPDX-FileCopyrightText: 2020 jens quade
SPDX-FileCopyrightText: 2022 Dennis Ciba
SPDX-FileCopyrightText: 2022 Erick Wibben
SPDX-FileCopyrightText: 2022 Kim Brose
SPDX-FileCopyrightText: 2022 Kolja Lampe
SPDX-FileCopyrightText: 2023 - 2024 MDAD project contributors
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2022 Travis Ralston
SPDX-FileCopyrightText: 2022 Vladimir Panteleev
SPDX-FileCopyrightText: 2022 Yan Minagawa
SPDX-FileCopyrightText: 2022, 2023 Julian-Samuel Gebühr
SPDX-FileCopyrightText: 2024-2026 Suguru Hirahara

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up matrix-registration-bot (optional)
# Setting up matrix-registration-bot (optional, removed)

The playbook can install and configure [matrix-registration-bot](https://github.com/moan0s/matrix-registration-bot) for you.
🪦 The playbook used to be able to install and configure [matrix-registration-bot](https://github.com/moan0s/matrix-registration-bot), but no longer includes this component, as it has been unmaintained.

The bot allows you to easily **create and manage registration tokens** aka. invitation codes. It can be used for an invitation-based server, where you invite someone by sending them a registration token (tokens look like this: `rbalQ0zkaDSRQCOp`). They can register as per normal but have to provide a valid registration token in the final step of the registration process.
## Uninstalling the component manually

See the project's [documentation](https://github.com/moan0s/matrix-registration-bot/blob/master/README.md) to learn what it does and why it might be useful to you.
If you still have matrix-registration-bot installed on your Matrix server, the playbook can no longer help you uninstall it and you will need to do it manually. To uninstall manually, run these commands on the server:

## Adjusting the playbook configuration

To enable the bot, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bot_matrix_registration_bot_enabled: true

# By default, the playbook will set use the bot with a username like this: `@bot.matrix-registration-bot:example.com`.
# Uncomment and adjust this part if you'd like to use a username different than the default
# matrix_bot_matrix_registration_bot_matrix_user_id_localpart: bot.matrix-registration-bot

# Generate a strong password for the bot. You can create one with a command like `pwgen -s 64 1`.
matrix_bot_matrix_registration_bot_bot_password: PASSWORD_FOR_THE_BOT

# Enables registration
matrix_synapse_enable_registration: true

# Restrict registration to users with a token
matrix_synapse_registration_requires_token: true

# Set an optional command prefix for the bot. This can be any arbitrary string, including whitespace.
# Example: "!regbot "
matrix_bot_matrix_registration_bot_bot_prefix: ""
```

The bot account will be created automatically.

### Extending the configuration

There are some additional things you may wish to configure about the bot.

Take a look at:

- `roles/custom/matrix-bot-matrix-registration-bot/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bot-matrix-registration-bot/templates/config.yaml.j2` for the bridge's default configuration

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-users-created,start
```

**Notes**:

- The `ensure-matrix-users-created` playbook tag makes the playbook automatically create the bot's user account.

- The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_matrix_registration_bot_bot_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_matrix_registration_bot_bot_password` to let the bot know its new password.

## Usage

To use the bot, start a chat with `@bot.matrix-registration-bot:example.com` (where `example.com` is your base domain, not the `matrix.` domain).

Send `help` to the bot to see the available commands.

You can also refer to the upstream [Usage documentation](https://github.com/moan0s/matrix-registration-bot#supported-commands).

If you have any questions, or if you need help setting it up, read the [troubleshooting guide](https://github.com/moan0s/matrix-registration-bot/blob/main/docs/troubleshooting.md) or join [#matrix-registration-bot:hyteck.de](https://matrix.to/#/#matrix-registration-bot:hyteck.de).

To clean the cache (session & encryption data) after you changed the bot's username, changed the login method from access_token to password etc… you can use:

```sh
just run-tags bot-matrix-registration-bot-clean-cache
```

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-bot-matrix-registration-bot`.

### Increase logging verbosity

The default logging level for this component is `INFO`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:
systemctl disable --now matrix-bot-matrix-registration-bot.service

```yaml
# Valid values: ERROR, INFO, DEBUG
matrix_bot_matrix_registration_bot_logging_level: DEBUG
rm -rf /matrix/matrix-registration-bot
```

+ 1
- 1
docs/configuring-playbook-bot-matrix-reminder-bot.md View File

@@ -57,7 +57,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_matrix_reminder_bot_matrix_user_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_matrix_reminder_bot_matrix_user_password` to let the bot know its new password.
- If you change the bot password (`matrix_bot_matrix_reminder_bot_matrix_user_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_matrix_reminder_bot_matrix_user_password` to let the bot know its new password.

## Usage



+ 1
- 1
docs/configuring-playbook-bot-maubot.md View File

@@ -103,7 +103,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bot password (`matrix_bot_maubot_initial_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_maubot_initial_password` to let the bot know its new password.
- If you change the bot password (`matrix_bot_maubot_initial_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_maubot_initial_password` to let the bot know its new password.

## Usage



+ 409
- 0
docs/configuring-playbook-bot-meowlnir.md View File

@@ -0,0 +1,409 @@
<!--
SPDX-FileCopyrightText: 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Meowlnir (optional)

The playbook can install and configure the [Meowlnir](https://github.com/maunium/meowlnir) moderation bot for you.

See the project's [documentation](https://docs.mau.fi/meowlnir/) to learn what it does and why it might be useful to you.

Meowlnir is an alternative to [Draupnir](configuring-playbook-bot-draupnir.md) and [Mjolnir](configuring-playbook-bot-mjolnir.md). It speaks the same [policy list](https://the-draupnir-project.github.io/draupnir-documentation/concepts/policy-lists) protocol, so it can subscribe to the same community ban lists, but it differs from them in a few ways that may matter to you:

- It runs as an **appservice** and hosts **multiple bots**, each with its own management room. They live in Meowlnir's database, not its configuration file, but you still [declare them in your `vars.yml` file](#declaring-bots).
- It can **override a policy coming from a list you do not control**, via unban policies combined with the ordering of your watched lists. See [Overriding a policy from someone else's list](#overriding-a-policy-from-someone-elses-list).
- It is written in Go and is optimized for Synapse, using its database and admin APIs directly.

Meowlnir and Draupnir can run side by side, but not usefully in the *same* room: whichever bot you are migrating away from still watches the same community lists, so it re-applies the very bans your unban policies remove. Migrate room by room. See [Trialling Meowlnir alongside another bot](#trialling-meowlnir-alongside-another-bot).

## Prerequisites

### Postgres

Meowlnir stores its state in a Postgres database. The playbook creates one for you automatically when using the integrated Postgres server.

### Adjusting DNS records

**No DNS changes are necessary.** Meowlnir is reached by the homeserver over the container network, and the paths it optionally serves publicly (abuse reports and the policy server) are routed on your existing `matrix.example.com` domain.

## Adjusting the playbook configuration

To enable Meowlnir, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bot_meowlnir_enabled: true
```

### Declaring bots

That gets the service running, but Meowlnir does nothing until it has at least one bot. Declare the ones you want and the playbook creates them for you:

```yaml
matrix_bot_meowlnir_bots_custom:
- username: meowlnir_bot
displayname: Meowlnir
avatar_url: ""
management_room_auto_create: true
management_rooms: []
# Left out, the initial managers default to `matrix_bot_meowlnir_initial_managers`,
# which is defined in terms of `matrix_admin`.
# Uncomment to override that for this bot, or if neither variable is set.
# initial_managers:
# - "@alice:example.com"
# - "@bob:example.com"
```

| Field | Required | Notes |
|---|---|---|
| `username` | yes | The localpart of the bot's Matrix user. Awkward to change later, so choose it carefully. |
| `displayname` | yes | The name shown in rooms. Safe to change at any time. |
| `avatar_url` | yes | An `mxc://` URI, or `""` for no avatar. |
| `management_room_auto_create` | yes | Whether the playbook creates the bot's management room. Mutually exclusive with a non-empty `management_rooms`. |
| `management_rooms` | yes | Rooms you have created yourself, `[]` when auto-creating. See [Supplying your own management room](#supplying-your-own-management-room). |
| `initial_managers` | no | Who to invite to an auto-created room. Defaults to the instance-wide list below. |

Usernames have to start with `meowlnir_` (the value of `matrix_bot_meowlnir_user_prefix`), so that bots fall inside the user namespace the homeserver lets Meowlnir operate.

Changing `displayname` or `avatar_url` and re-running updates the bot in place. The comparison is against Meowlnir's own record, so profile edits made directly from a Matrix client are not reverted.

#### Initial managers

With `management_room_auto_create: true`, the playbook creates each bot's management room and invites its initial managers to it. You only need to accept the room invitation.

`matrix_admin` is a single playbook variable which affects all bridges and bots, so setting it is usually a better move than setting anything specific to this role — **if it is already configured in your `vars.yml` file, there is nothing to do here**. If neither `matrix_admin` nor `matrix_bot_meowlnir_initial_managers` are set, the playbook would tell you about it.

A per-bot `initial_managers` replaces the instance-wide list. Declaring it empty means nobody, which fails the run for a bot relying on `management_room_auto_create`.

The list is consulted only while the room is being created. Adding a name to it later invites nobody, because the room already exists — invite and promote further moderators from inside the room instead, as described in [Who can command a bot](#who-can-command-a-bot).

#### Rooms the playbook creates

The bot creates the room with the `trusted_private_chat` preset, which gives every invitee the standing to command it. This is an additional room creator on room versions supporting [MSC4289](https://github.com/matrix-org/matrix-spec-proposals/pull/4289) (like v12) and power level 100 on older room versions. Creator status cannot be revoked subsequently.

The room's encryption follows `matrix_bot_meowlnir_config_encryption_enable`, and its name and topic come from `matrix_bot_meowlnir_management_room_name` and `matrix_bot_meowlnir_management_room_topic`.

### Supplying your own management room

If you would rather own the room outright, create it yourself and declare it instead. The bot is then merely an administrator in a room you created:

```yaml
matrix_bot_meowlnir_bots_custom:
- username: meowlnir_bot
displayname: Meowlnir
avatar_url: ""
management_room_auto_create: false
management_rooms:
- id: "!qporfwt:example.com"
encrypted: false
```

An empty, invite-only room is fine. The order matters, because **each step depends on the one before it**:

1. Declare the room and run the playbook. Do not invite the bot beforehand.
2. The playbook creates the bot and tells Meowlnir about the room. Meowlnir would try to join right away, but will fail for invite-only rooms (a harmless error in the log).
3. Invite the bot. It accepts the invitation, because the room is already marked as a management room for it.
4. Give it power level 50 or more (ideally 100), so that it can store its protected rooms and watched lists there.

Meowlnir supports several management rooms per bot, and `encrypted` is set per room. Marking a room encrypted only means something when [End-to-End Encryption support](#end-to-end-encryption-support) is switched on, which it is not by default.

### Several management rooms for one bot

Protected rooms, watched policy lists, protection settings and who may command the bot are properties of **a management room**, not of the bot. A room can be protected from exactly one management room, so moving a room means `!rooms unprotect` in the old room and `!rooms protect` in the new one, with its settings and subscriptions set up again there.

That is how you hand one room to another moderator without giving them power over everything else the bot moderates: a second management room, the room moved into it, and power level 50 for them there. That last part is revocable, unlike the creator status everyone invited at creation time receives.

Splitting rooms up this way does not split two other things:

- The variables which name a single management room (`matrix_bot_meowlnir_synapse_http_antispam_management_room_id`, `matrix_bot_meowlnir_config_meowlnir_report_room`, `matrix_bot_meowlnir_config_meowlnir_room_ban_room`) keep pointing at the room you named there.
- A policy list can be written to from any management room watching it, and its policies apply in every room those management rooms protect. Give a delegated management room a list of its own with `!lists create`.

Create the room with `meowlnir-create-management-room` (see [Inspecting and driving Meowlnir directly](#inspecting-and-driving-meowlnir-directly)), then add its ID to `management_rooms` and re-run the playbook, which is what registers it with Meowlnir.

#### Switching a bot from an auto-created room to declared ones

Auto-creation makes exactly one room, and since it is not declared anywhere, [pruning](#bots-which-are-no-longer-declared) leaves such a bot's rooms alone. Declaring a second room means taking over the declaration of all of them: list what Meowlnir knows about with `/matrix/meowlnir/bin/meowlnir-bots`, set `management_room_auto_create: false`, put **every** one of those rooms under `management_rooms`, and re-run the playbook.

> [!WARNING]
> A room left out of that list is unregistered on the next run. Nothing is destroyed, but the bot stops taking commands there and stops protecting the rooms attached to it, until you declare the room again.

### Who can command a bot

**Management room membership alone is not enough**, which is different from what [Draupnir](configuring-playbook-bot-draupnir.md) does, where everyone in the management room can issue commands.

Meowlnir decides who may drive a bot from power levels in its management room: anyone who can send the `fi.mau.meowlnir.watched_lists` state event (power level 50 by default), plus the room's creators.

### Bots which are no longer declared

The bot list (`matrix_bot_meowlnir_bots_custom`) is authoritative. Removing entries from there will make the playbook unregister them with the Meowlnir instance.

Removal only adjusts Meowlnir's own records. A removed bot's Matrix user remains activated and stays in the rooms it had joined. A removed management room leaves the room and the bot's membership in it intact - it's just that Meowlnir stops taking commands there.

Removal happens under the same `ensure-matrix-users-created` tag that creates bots. It's one Ansible tag for "synchronizing the bots state" (creation, changes, and removal).

To turn removal off entirely, set `matrix_bot_meowlnir_bots_pruning_enabled: false`. As a safety measure, the playbook refuses to prune when *no* bots are declared at all; override that with `matrix_bot_meowlnir_bots_pruning_on_empty_roster_enabled: true`.

### Trialling Meowlnir alongside another bot

Meowlnir has a dry-run mode in which it does everything except take moderation actions:

```yaml
matrix_bot_meowlnir_config_meowlnir_dry_run: true
```

> [!WARNING]
> Dry run does not cover the [synapse-http-antispam](#enabling-synapse-http-antispam-support) integration. It suppresses actions Meowlnir takes itself (bans, server ACLs, rejecting pending invites), but the verdicts it hands back to Synapse still block invites and joins. Leave that integration off while trialling.

Do not expect dry run to preview what Meowlnir would do in rooms another policy-list bot already moderates. Meowlnir only acts on users who are *in* a room, and the other bot has already removed everyone its lists match, so the preview comes out empty. Dry run also skips the power level check described under [Protecting a room](#protecting-a-room), so it will not surface a permissions problem either.

### Abuse reports

Meowlnir can intercept the report endpoints of the client-server API, so that abuse reports are delivered to a management room. This requires integration with the reverse proxy in front of the homeserver, which the playbook sets up for you when using Traefik:

```yaml
matrix_bot_meowlnir_config_reporting_enabled: true

# The management room that receives the reports.
matrix_bot_meowlnir_config_meowlnir_report_room: "!qporfwt:example.com"
```

Only the `v3` report endpoints are routed to Meowlnir. Requests to the legacy `r0` endpoints continue to reach the homeserver, because Meowlnir does not serve them.

### Enabling synapse-http-antispam support

Meowlnir can block invites and joins before they happen. This requires the [synapse-http-antispam](https://github.com/maunium/synapse-http-antispam) module, which the playbook can enable for you:

```yaml
matrix_bot_meowlnir_synapse_http_antispam_enabled: true

# The management room whose policies the module consults.
matrix_bot_meowlnir_synapse_http_antispam_management_room_id: "!qporfwt:example.com"
```

> [!WARNING]
> The playbook wires the module up to a single consumer, so this cannot be enabled at the same time as `matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled`. The playbook fails the run if both are enabled.

With the module in place, you can also block invitations to specific users outright, which is useful for accounts that attract spam:

```yaml
matrix_bot_meowlnir_config_antispam_block_invites_to_custom:
- "@alice:example.com"
```

Such an invitation can still be let through case by case with the `!allow-invite` command.

### End-to-End Encryption support

To let Meowlnir's bots participate in encrypted rooms:

```yaml
matrix_bot_meowlnir_config_encryption_enable: true
```

When using Synapse, the playbook turns on the experimental features this depends on (`msc2409_to_device_messages_enabled` and `msc3202_transaction_extensions`) for you.

### Policy server (MSC4284)

Meowlnir can act as a [policy server](https://github.com/matrix-org/matrix-spec-proposals/pull/4284), letting rooms ask it to vet events before they are accepted:

```yaml
matrix_bot_meowlnir_policy_server_enabled: true
```

This exposes `/_matrix/policy` on your Matrix federation endpoint, so that other servers participating in a room can reach it.

That only stands the policy server up, though — no room is put behind it until you say so from the management room:

```
!policyserver enable !qporfwt:example.com
```

Given no room, `enable` applies to every protected room. Rooms which are not protected are skipped, with `Skipped ... as it is not a protected room`, so [protect a room](#protecting-a-room) before enabling it here. `!policyserver` on its own reports whether the policy server is available and prints its public key, and `!policyserver disable` reverses the change.

The playbook derives a stable signing key for you from `matrix_homeserver_generic_secret_key`. If you would rather use an independently generated one, produce it with the command below and set it as `matrix_bot_meowlnir_config_policy_server_signing_key`:

```sh
python3 -c "import os, base64; print('ed25519 policy_server ' + base64.b64encode(os.urandom(32)).decode().rstrip('='))"
```

### Synapse admin API access (optional)

A few of Meowlnir's features go through Synapse's admin API, not the client-server API — suspending or deactivating users, and deleting rooms during a takedown. Those calls require the caller to be a Synapse **server admin**, which bots are not by default, so they come back as `M_FORBIDDEN` ("You are not a server admin"). Nothing else is affected: bans, server ACLs, protecting rooms and watching policy lists all go through the client-server API, where a sufficient power level is the only requirement.

To grant that access, point each bot at a token belonging to a server admin:

```yaml
matrix_bot_meowlnir_config_meowlnir_admin_tokens:
"@meowlnir_bot:example.com": "ADMIN_TOKEN_HERE"
```

The key is the bot the token is used for; the token itself belongs to an administrator account, not to the bot.

If you have more than one management room, note that room bans are only processed in the one named by `matrix_bot_meowlnir_config_meowlnir_room_ban_room`, and ignored elsewhere.

Where the token comes from depends on how your homeserver authenticates. Ordinarily you [obtain an access token](obtaining-access-tokens.md) for an account which is a Synapse server admin. When [Matrix Authentication Service](configuring-playbook-matrix-authentication-service.md) is enabled, Synapse no longer decides who is an admin, so the token has to be issued by MAS with admin privileges:

```sh
/matrix/matrix-authentication-service/bin/mas-cli manage issue-compatibility-token --yes-i-want-to-grant-synapse-admin-privileges alice
```

Note that bot users are created by the appservice and are not known to Matrix Authentication Service, so the token cannot be issued for the bot itself — use an administrator account.

### Access to the Synapse database (optional)

Some room takedown features rely on Meowlnir reading room IDs directly from the Synapse database. Upstream expects a user with read-only permissions, which the playbook does not create. Enabling the integration below hands Meowlnir the same credentials Synapse itself uses, which also grant write access:

```yaml
matrix_bot_meowlnir_synapse_database_integration_enabled: true
```

If you would rather not do that, create a read-only Postgres user yourself and point Meowlnir at it with `matrix_bot_meowlnir_synapse_database_uri`.

### Adopting an existing Meowlnir installation

If you already run Meowlnir outside the playbook and want to bring it under this role, two things need attention before the first run.

Your bots exist in Meowlnir's database but not in your `vars.yml` file, and [pruning](#bots-which-are-no-longer-declared) is on by default, so the first run would remove them. Declare them in `matrix_bot_meowlnir_bots_custom` — with `management_room_auto_create: false` and their existing rooms under `management_rooms` — or set `matrix_bot_meowlnir_bots_pruning_enabled: false`.

If the installation uses encryption, also copy the `pickle_key` from its old configuration file into `matrix_bot_meowlnir_config_encryption_pickle_key`. The crypto store cannot be read with a different key than it was written with, so leaving the playbook's default in place costs your bots their existing encryption sessions.

### Extending the configuration

There are some additional things you may wish to configure about the bot.

Take a look at:

- `roles/custom/matrix-bot-meowlnir/defaults/main.yml` for some variables that you can customize via your `vars.yml` file. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bot_meowlnir_configuration_extension_yaml` variable

> [!WARNING]
> Do not set any of Meowlnir's secrets to the literal value `generate`. Meowlnir re-runs its configuration upgrader on every start, so a `generate` placeholder would produce a brand new secret on every restart. The playbook derives stable values for you, and fails the run if it finds a `generate` placeholder.

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-users-created,start
```

With `management_room_auto_create`, you then have an invitation waiting for you — accept it and start sending commands. If you supplied the management room yourself, carry on from step 3 of [Supplying your own management room](#supplying-your-own-management-room): invite the bot, then give it power level 50 or more.

**Notes**:

- The `ensure-matrix-users-created` tag is what creates the bots declared in `matrix_bot_meowlnir_bots_custom`, registers their management rooms, and removes the ones you no longer declare. It deliberately does not run as part of `setup-all`, so that installing onto a server whose database you are about to restore from a backup does not write anything.

- Re-running is safe and idempotent, so adding a bot later is a matter of extending the list and running the same command again.

- If the homeserver turns out to be running without Meowlnir's appservice registration (which is the normal state of affairs on the run that first enables Meowlnir), the playbook restarts the homeserver during bot provisioning, so that everything completes in a single run.

- The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

## Usage

You can refer to the upstream [documentation](https://docs.mau.fi/meowlnir/) for a more detailed usage guide.

Below is a **non-exhaustive quick-start guide** for the impatient.

### Inspecting and driving Meowlnir directly

The playbook drives Meowlnir's management API for you based on `matrix_bot_meowlnir_bots_custom`, which is the recommended way. For anything it does not cover, helper scripts are installed under `/matrix/meowlnir/bin`, which find the management secret and reach the API inside the container:

```sh
# Show the bots, their management rooms, protected rooms and watched policy lists
/matrix/meowlnir/bin/meowlnir-bots

# Call any endpoint: meowlnir-api <METHOD> <PATH> [JSON body]
/matrix/meowlnir/bin/meowlnir-api GET /_meowlnir/v1/bots

# Create another management room for an existing bot, with the given users able to command it there
/matrix/meowlnir/bin/meowlnir-create-management-room meowlnir_bot @alice:example.com

# Ask the homeserver who Meowlnir's appservice token belongs to.
# A 401 response means the homeserver is running without Meowlnir's appservice registration, which is also what Meowlnir's own "Failed to connect to homeserver" log messages usually mean.
/matrix/meowlnir/bin/meowlnir-whoami
```

`meowlnir-create-management-room` prints the new room's ID, which you then register with `meowlnir-api PUT /_meowlnir/v1/management_room/<room ID>`.

See the upstream [bot creation documentation](https://docs.mau.fi/meowlnir/bot-create.html) for the full set of endpoints. Bear in mind that bots you create this way are not declared in your `vars.yml` file, so the next playbook run will remove them again (see [Bots which are no longer declared](#bots-which-are-no-longer-declared)).

If you have enabled encryption, each bot also needs verifying once. That step is left manual because it returns a recovery key you need to store somewhere safe:

```sh
/matrix/meowlnir/bin/meowlnir-api POST /_meowlnir/v1/bot/meowlnir_bot/verify '{"generate": true}'
```

### Protecting a room

Invite the bot to a room, give it a power level high enough to act (see below), and then tell it to protect the room by sending this command to its management room:

```
!rooms protect !qporfwt:example.com
```

If the bot has more than one management room, send this to the one that should own the room: a room can only be protected from a single management room. See [Several management rooms for one bot](#several-management-rooms-for-one-bot).

Meowlnir refuses to protect a room unless its power level reaches that room's own `ban` and `redact` levels (50 in a default room). That is only enough for user bans, though: writing `m.room.server_acl` usually requires 100, and without it the server rules in your watched lists have no effect — which is most of what a list like [CME](https://matrix.to/#/%23community-moderation-effort-bl:neko.dev) carries. **Give the bot power level 100** unless you only care about user bans.

Set the power level *before* protecting the room. Meowlnir re-sends server ACLs when it starts and when a watched list changes, but not when its own power level goes up subsequently, so raising it afterwards leaves the room without ACLs until you restart the bot (`systemctl restart matrix-bot-meowlnir` or via the playbook's Ansible `start` tag).

### Subscribing to a policy list

Policy lists are maintained in Matrix rooms. Popular public ones are:

- `#community-moderation-effort-bl:neko.dev`
- `#huginn-muninn-active-threats:feline.support`

Subscribe to one by sending the following command to the management room:

```
!lists subscribe #community-moderation-effort-bl:neko.dev cme
```

The last argument is a shortcode, which you use to refer to the list in later commands.

### Overriding a policy from someone else's list

This is the main capability Meowlnir has that Draupnir does not.

When several watched lists carry a policy for the same user, **the first match wins**, and "first" means the order in which the lists are watched. So to be able to override a community list's ban, your own list has to come before it.

`!lists subscribe` appends, which makes subscription order the precedence order. Subscribe to your own list first, and to community lists afterwards:

```
!lists create my-ban-exceptions
!lists subscribe #community-moderation-effort-bl:neko.dev cme
```

> [!NOTE]
> To subscribe somewhere other than the end of the list, pass `--insert-before <shortcode>`.

You can then publish an unban policy into your own list, which takes precedence over the community list's ban:

```
!add-unban my-bans @alice:example.com false-positive
```

> [!NOTE]
> Unlike `!ban`, the `!add-unban` command does not treat its reason as a trailing argument, so a reason containing spaces is discarded. Use a single word (or hyphenate) until that is fixed upstream.

> [!IMPORTANT]
> An unban policy stops a ban from being **re-applied**; it does not undo one that is already in place unless Meowlnir applied it itself and still has it on record. A ban placed by a human moderator, or by the Draupnir or Mjolnir you are migrating away from, stays. Unban such a user once by hand — from then on the policy keeps them unbanned, while you remain subscribed to the list that banned them.

Use `!match @alice:example.com` to see which policies currently apply to a user and which list each came from.

> [!NOTE]
> Unban policies use a Meowlnir-specific recommendation (`fi.mau.meowlnir.unban`) which is not part of the Matrix specification. If you publish your policy list for other people to subscribe to, subscribers running Draupnir or Mjolnir will ignore your unban policies.

There is also a blunter, server-wide escape hatch for policies that are too wide to tolerate at all — `matrix_bot_meowlnir_config_meowlnir_hacky_rule_filter_custom`, which makes Meowlnir ignore any policy matching the listed entities.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by running a command like `journalctl -fu matrix-bot-meowlnir`.

If bots appear to do nothing, check that they have an Administrator power level in the rooms they are meant to protect, and that the room has been added with `!rooms protect`.

If commands in a management room get no reply at all, check the bot's power level *there* too — it needs at least 50 to record its own configuration.

A bare `!lists` returns nothing in a management room which has never had a policy list. That is an upstream bug and it clears as soon as you subscribe to one; `!lists subscribe` works from the start.

+ 4
- 2
docs/configuring-playbook-bot-mjolnir.md View File

@@ -15,6 +15,8 @@ The playbook can install and configure the [Mjolnir](https://github.com/matrix-o

See the project's [documentation](https://github.com/matrix-org/mjolnir/blob/main/README.md) to learn what it does and why it might be useful to you.

**Note**: you can also use the [Draupnir](configuring-playbook-bot-draupnir.md) or [Meowlnir](configuring-playbook-bot-meowlnir.md) bots, which speak the same [policy list](https://the-draupnir-project.github.io/draupnir-documentation/concepts/policy-lists) protocol.

## Prerequisites

### Register the bot account
@@ -46,7 +48,7 @@ This can be done using Synapse's [Admin APIs](https://element-hq.github.io/synap

**Note**: access to the APIs is restricted with a valid access token, so exposing them publicly should not be a real security concern. Still, doing so is not recommended for additional security. See [official Synapse reverse-proxying recommendations](https://element-hq.github.io/synapse/latest/reverse_proxy.html#synapse-administration-endpoints).

The APIs can also be accessed via [Synapse Admin](https://github.com/etkecc/synapse-admin), a web UI tool you can use to administrate users, rooms, media, etc. on your Matrix server. The playbook can install and configure Synapse Admin for you. For details about it, see [this page](configuring-playbook-synapse-admin.md).
The APIs can also be accessed via [Ketesa](https://github.com/etkecc/ketesa), a web UI tool you can use to administrate users, rooms, media, etc. on your Matrix server. The playbook can install and configure Ketesa for you. For details about it, see [this page](configuring-playbook-ketesa.md).

#### Add the configuration

@@ -198,7 +200,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the Pantalaimon's password (`matrix_bot_mjolnir_pantalaimon_password` in your `vars.yml` file) subsequently, its credentials on the homeserver won't be updated automatically. If you'd like to change the password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_bot_mjolnir_pantalaimon_password` to let Pantalaimon know its new password.
- If you change the Pantalaimon's password (`matrix_bot_mjolnir_pantalaimon_password` in your `vars.yml` file) subsequently, its credentials on the homeserver won't be updated automatically. If you'd like to change the password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bot_mjolnir_pantalaimon_password` to let Pantalaimon know its new password.

## Usage



+ 8
- 8
docs/configuring-playbook-bridge-appservice-discord.md View File

@@ -26,9 +26,9 @@ Create a Discord Application [here](https://discordapp.com/developers/applicatio
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_appservice_discord_enabled: true
matrix_appservice_discord_client_id: "YOUR DISCORD APP CLIENT ID"
matrix_appservice_discord_bot_token: "YOUR DISCORD APP BOT TOKEN"
matrix_bridge_appservice_discord_enabled: true
matrix_bridge_appservice_discord_client_id: "YOUR DISCORD APP CLIENT ID"
matrix_bridge_appservice_discord_bot_token: "YOUR DISCORD APP BOT TOKEN"

# As of Synapse 1.90.0, uncomment to enable the backwards compatibility (https://matrix-org.github.io/synapse/latest/upgrade#upgrading-to-v1900) that this bridge needs.
# Note: This deprecated method is considered insecure.
@@ -44,7 +44,7 @@ There are some additional things you may wish to configure about the bridge.
Take a look at:

- `roles/custom/matrix-bridge-appservice-discord/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bridge-appservice-discord/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_appservice_discord_configuration_extension_yaml` variable
- `roles/custom/matrix-bridge-appservice-discord/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bridge_appservice_discord_configuration_extension_yaml` variable

## Installing

@@ -65,7 +65,7 @@ The shortcut commands with the [`just` program](just.md) are also available: `ju
Self-service bridging allows you to bridge specific and existing Matrix rooms to specific Discord rooms. To enable it, add the following configuration to your `vars.yml` file:

```yaml
matrix_appservice_discord_bridge_enableSelfServiceBridging: true
matrix_bridge_appservice_discord_bridge_enableSelfServiceBridging: true
```

**Note**: If self-service bridging is not enabled, `!discord help` commands will return no results.
@@ -91,14 +91,14 @@ All Matrix rooms created this way are **listed publicly** by default, and you wi
To disable portal bridging, add the following configuration to your `vars.yml` file:

```yaml
matrix_appservice_discord_bridge_disablePortalBridging: true
matrix_bridge_appservice_discord_bridge_disablePortalBridging: true
```

### Usage

To get started with Portal Bridging:

1. To invite the bot to Discord, retrieve the invite link from the `{{ matrix_appservice_discord_config_path }}/invite_link` file on the server (this defaults to `/matrix/appservice-discord/config/invite_link`). You need to peek at the file on the server via SSH, etc., because it's not available via HTTP(S).
1. To invite the bot to Discord, retrieve the invite link from the `{{ matrix_bridge_appservice_discord_config_path }}/invite_link` file on the server (this defaults to `/matrix/appservice-discord/config/invite_link`). You need to peek at the file on the server via SSH, etc., because it's not available via HTTP(S).
2. Room addresses follow this syntax: `#_discord_<guildID>_<channelID>`. You can easily find the guild and channel IDs by logging into Discord in a browser and opening the desired channel. The URL will have this format: `discord.com/channels/<guildID>/<channelID>`.
3. Once you have figured out the appropriate room address, you can join by doing `/join #_discord_<guildID>_<channelID>` in your Matrix client.

@@ -124,7 +124,7 @@ As with all other services, you can find the logs in [systemd-journald](https://
The default logging level for this component is `warn`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file (adapt to your needs) and re-run the playbook:

```yaml
matrix_appservice_discord_configuration_extension_yaml: |
matrix_bridge_appservice_discord_configuration_extension_yaml: |
logging:
# What level should the logger output to the console at.
console: "info" # Valid values: silent, error, warn, http, info, verbose, silly


+ 4
- 4
docs/configuring-playbook-bridge-appservice-irc.md View File

@@ -20,9 +20,9 @@ See the project's [documentation](https://github.com/matrix-org/matrix-appservic
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_appservice_irc_enabled: true
matrix_bridge_appservice_irc_enabled: true

matrix_appservice_irc_ircService_servers:
matrix_bridge_appservice_irc_ircService_servers:
irc.example.com:
name: "ExampleNet"
port: 6697
@@ -76,7 +76,7 @@ There are some additional things you may wish to configure about the bridge.
Take a look at:

- `roles/custom/matrix-bridge-appservice-irc/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bridge-appservice-irc/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_appservice_irc_configuration_extension_yaml` variable
- `roles/custom/matrix-bridge-appservice-irc/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bridge_appservice_irc_configuration_extension_yaml` variable

## Installing

@@ -104,7 +104,7 @@ As with all other services, you can find the logs in [systemd-journald](https://
The default logging level for this component is `debug`, and the log is output to the console only. If you want to change the verbosity or enable logging to a file, add the following configuration to your `vars.yml` file (adapt to your needs) and re-run the playbook:

```yaml
matrix_appservice_irc_configuration_extension_yaml: |
matrix_bridge_appservice_irc_configuration_extension_yaml: |
logging:
# Level to log on console/logfile.
# Valid values: error, warn, info, debug


+ 9
- 58
docs/configuring-playbook-bridge-appservice-kakaotalk.md View File

@@ -1,75 +1,26 @@
<!--
SPDX-FileCopyrightText: 2022 Dennis Ciba
SPDX-FileCopyrightText: 2022 Slavi Pantaleev
SPDX-FileCopyrightText: 2022 - 2026 Slavi Pantaleev
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2024 MDAD project contributors

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Appservice Kakaotalk bridging (optional)
# Setting up Appservice Kakaotalk bridging (optional, removed)

The playbook can install and configure [matrix-appservice-kakaotalk](https://src.miscworks.net/fair/matrix-appservice-kakaotalk) for you, for bridging to [Kakaotalk](https://www.kakaocorp.com/page/service/service/KakaoTalk?lang=ENG). This bridge is based on [node-kakao](https://github.com/storycraft/node-kakao) (now unmaintained) and some [mautrix-facebook](https://github.com/mautrix/facebook) code.
🪦 The playbook used to be able to install and configure [matrix-appservice-kakaotalk](https://src.miscworks.net/fair/matrix-appservice-kakaotalk) (a bridge to [Kakaotalk](https://www.kakaocorp.com/page/service/service/KakaoTalk?lang=ENG)), but no longer includes this component.

See the project's [documentation](https://src.miscworks.net/fair/matrix-appservice-kakaotalk/src/branch/master/README.md) to learn what it does and why it might be useful to you.
The bridge could only be installed by self-building its source code, and its upstream repository has become unreachable, which makes installation impossible. The bridge was also based on the now-unmaintained [node-kakao](https://github.com/storycraft/node-kakao) library, and there have been reports that using it may get your Kakaotalk account banned.

> [!WARNING]
> There have been recent reports (~2022-09-16) that **using this bridge may get your account banned**.
## Uninstalling the component manually

## Prerequisite (optional)
If you still have matrix-appservice-kakaotalk installed on your Matrix server, the playbook can no longer help you uninstall it and you will need to do it manually. To uninstall manually, run these commands on the server:

### Enable Shared Secret Auth

If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) (hint: you most likely do) for this bridge automatically, you need to have enabled [Shared Secret Auth](configuring-playbook-shared-secret-auth.md) for this playbook.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-puppeting-optional) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about setting up Double Puppeting.

**Note**: double puppeting with the Shared Secret Auth works at the time of writing, but is deprecated and will stop working in the future.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_appservice_kakaotalk_enabled: true
```

### Extending the configuration

There are some additional things you may wish to configure about the bridge.

Take a look at:

- `roles/custom/matrix-bridge-appservice-kakaotalk/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bridge-appservice-kakaotalk/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_appservice_kakaotalk_configuration_extension_yaml` variable

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

To use the bridge, you need to start a chat with `@kakaotalkbot:example.com` (where `example.com` is your base domain, not the `matrix.` domain).

You then need to send `login --save EMAIL_OR_PHONE_NUMBER` to the bridge bot to enable bridging for your Kakaotalk account. The `--save` flag may be omitted, if you'd rather not save your password.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-appservice-kakaotalk`.

### Increase logging verbosity
systemctl disable --now matrix-appservice-kakaotalk.service

The default logging level for this component is `WARNING`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:
systemctl disable --now matrix-appservice-kakaotalk-node.service

```yaml
matrix_appservice_kakaotalk_logging_level: DEBUG
rm -rf /matrix/appservice-kakaotalk
```

+ 101
- 0
docs/configuring-playbook-bridge-beeper-line.md View File

@@ -0,0 +1,101 @@
<!--
SPDX-FileCopyrightText: 2026 MDAD project contributors

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Beeper LINE bridging (optional)

<sup>Refer to the common guide for configuring mautrix bridges: [Setting up a Generic Mautrix Bridge](configuring-playbook-bridge-mautrix-bridges.md)</sup>

The playbook can install and configure [beeper-line](https://github.com/beeper/line) for you, for bridging to [LINE](https://line.me/).

See the project's [documentation](https://github.com/beeper/line/blob/main/README.md) to learn what it does and which features it supports.

## Prerequisites

### Prepare your LINE account

The bridge logs in with the email address configured in your LINE account. If your account does not have an email address, set one in the LINE mobile app under **Settings** → **Account** → **Email address** before trying to log in.

The bridge identifies itself to LINE as a Chrome Extension client. LINE only permits one active Chrome Extension session, so the bridge and the real LINE Chrome Extension cannot be used at the same time. Logging in with either one invalidates the other session.

### Enable Appservice Double Puppet (optional)

If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) for this bridge automatically, you need to have enabled [Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md) for this playbook.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-puppeting-optional) on the common mautrix bridge guide for details.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bridge_beeper_line_enabled: true
```

### Using another container image

Upstream does not publish container images publicly, as its CI only pushes them to Beeper's private registry. The playbook therefore uses [`docker.io/crispyduck/beeper-line`](https://hub.docker.com/r/crispyduck/beeper-line) by default, which is a community-maintained image built from the upstream source.

That image is only available for the amd64 architecture. On other architectures, the playbook self-builds the image from source automatically.

To use an image that you have built and published elsewhere, override the complete image name:

```yaml
matrix_bridge_beeper_line_container_image_self_build: false
matrix_bridge_beeper_line_container_image: docker.io/example/beeper-line:latest
```

The role can also build the bridge directly from a Git repository on the Matrix server:

```yaml
matrix_bridge_beeper_line_container_image_self_build: true
matrix_bridge_beeper_line_container_image_self_build_repo: https://github.com/beeper/line.git
matrix_bridge_beeper_line_container_image_self_build_branch: main
```

Self-building requires more time and resources on the server than pulling a prebuilt image.

### Extending the configuration

There are additional things you may wish to configure about the bridge.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#extending-the-configuration) on the common mautrix bridge guide for details about variables that you can customize and the bridge's default configuration, including [bridge permissions](configuring-playbook-bridge-mautrix-bridges.md#configure-bridge-permissions-optional), [encryption support](configuring-playbook-bridge-mautrix-bridges.md#enable-encryption-optional), [relay mode](configuring-playbook-bridge-mautrix-bridges.md#enable-relay-mode-optional), and the [bot's username](configuring-playbook-bridge-mautrix-bridges.md#set-the-bots-username-optional).

When following the common guide, replace `_mautrix_SERVICENAME_` in variable names with `_beeper_line_`.

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`.

`just install-all` is useful for maintaining your setup quickly when its components remain unchanged. If you adjust your `vars.yml` to remove other components, run `just setup-all` so those components are uninstalled.

## Usage

To use the bridge, start a chat with `@linebot:example.com` (where `example.com` is your base domain, not the `matrix.` domain).

Send `login` and enter your LINE email address and password when prompted. The bridge then shows you a PIN code, which you need to enter into the LINE app on your mobile device to approve the new session.

## Troubleshooting

As with all other services, you can find the logs in systemd-journald by logging in to the server with SSH and running:

```sh
journalctl -fu matrix-beeper-line
```

### Increase logging verbosity

The default logging level for this component is `warn`. To increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_bridge_beeper_line_logging_level: debug
```

+ 5
- 3
docs/configuring-playbook-bridge-beeper-linkedin.md View File

@@ -8,7 +8,9 @@ SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Beeper Linkedin bridging (optional)
# Setting up Beeper Linkedin bridging (optional, unmaintained)

**Note**: this bridge is unmaintained. Its [upstream repository](https://github.com/beeper/linkedin) has been archived and has not seen a change since March 2025. For bridging to LinkedIn, consider using the [mautrix-linkedin](configuring-playbook-bridge-mautrix-linkedin.md) bridge instead, which is actively maintained and also supported by the playbook.

The playbook can install and configure [beeper-linkedin](https://github.com/beeper/linkedin) for you, for bridging to [LinkedIn](https://www.linkedin.com/) Messaging. This bridge is based on the mautrix-python framework and can be configured in a similar way to the mautrix bridges.

@@ -29,7 +31,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_beeper_linkedin_enabled: true
matrix_bridge_beeper_linkedin_enabled: true
```

### Extending the configuration
@@ -68,7 +70,7 @@ As with all other services, you can find the logs in [systemd-journald](https://
The default logging level for this component is `WARNING`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
matrix_beeper_linkedin_logging_level: DEBUG
matrix_bridge_beeper_linkedin_logging_level: DEBUG
```

### Bridge asking for 2FA even if you don't have 2FA enabled


+ 6
- 6
docs/configuring-playbook-bridge-heisenbridge.md View File

@@ -25,26 +25,26 @@ If you wish to adjust it, see the section [below](#adjusting-the-heisenbridge-ur
To enable Heisenbridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_heisenbridge_enabled: true
matrix_bridge_heisenbridge_enabled: true

# Setting the owner is optional as the first local user to DM `@heisenbridge:example.com` will be made the owner.
# If you are not using a local user you must set it as otherwise you can't DM it at all.
matrix_heisenbridge_owner: "@alice:{{ matrix_domain }}"
matrix_bridge_heisenbridge_owner: "@alice:{{ matrix_domain }}"

# Uncomment to enable identd on host port 113/TCP (optional)
# matrix_heisenbridge_identd_enabled: true
# matrix_bridge_heisenbridge_identd_enabled: true
```

### Adjusting the Heisenbridge URL (optional)

By tweaking the `matrix_heisenbridge_hostname` and `matrix_heisenbridge_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.
By tweaking the `matrix_bridge_heisenbridge_hostname` and `matrix_bridge_heisenbridge_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.

Example additional configuration for your `vars.yml` file:

```yaml
# Change the default hostname and path prefix
matrix_heisenbridge_hostname: heisenbridge.example.com
matrix_heisenbridge_path_prefix: /
matrix_bridge_heisenbridge_hostname: heisenbridge.example.com
matrix_bridge_heisenbridge_path_prefix: /
```

If you've changed the default hostname, you may need to create a CNAME record for the Heisenbridge domain (`heisenbridge.example.com`), which targets `matrix.example.com`.


+ 28
- 25
docs/configuring-playbook-bridge-hookshot.md View File

@@ -29,20 +29,23 @@ You need to download the private key file, if you will install the file manually
Add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file. Make sure to replace `GITHUB_PRIVATE_KEY_HERE` with the one created [above](#download-github-app-private-key).

```yaml
matrix_hookshot_enabled: true
matrix_bridge_hookshot_enabled: true

# Uncomment to enable end-to-bridge encryption.
# See: https://matrix-org.github.io/matrix-hookshot/latest/advanced/encryption.html
# matrix_hookshot_encryption_enabled: true
# matrix_bridge_hookshot_encryption_enabled: true

# Uncomment and paste the contents of GitHub app private key to enable GitHub bridge.
# Alternatively, you can use one of the other methods explained below on the "Manage GitHub Private Key with aux role" section.
# matrix_hookshot_github_private_key: "GITHUB_PRIVATE_KEY_HERE"
# matrix_bridge_hookshot_github_private_key: "GITHUB_PRIVATE_KEY_HERE"
```

For each of the services (GitHub, GitLab, Jira, Figma, and generic webhooks) fill in the respective variables `matrix_hookshot_service_*` listed in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml) as required.
> [!NOTE]
> End-to-bridge encryption requires the homeserver to support (and have enabled) [MSC2409](https://github.com/matrix-org/matrix-spec-proposals/pull/2409) and [MSC3202](https://github.com/matrix-org/matrix-spec-proposals/pull/3202). When using Synapse, the playbook turns on the experimental features this depends on (`msc2409_to_device_messages_enabled` and `msc3202_transaction_extensions`) for you. On other homeserver implementations, you need to arrange for this yourself.

Take special note of the `matrix_hookshot_*_enabled` variables. Services that need no further configuration are enabled by default (GitLab and generic webhooks), while you must first add the required configuration and enable the others (GitHub, Jira, and Figma).
For each of the services (GitHub, GitLab, Jira, Figma, and generic webhooks) fill in the respective variables `matrix_bridge_hookshot_service_*` listed in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml) as required.

Take special note of the `matrix_bridge_hookshot_*_enabled` variables. Services that need no further configuration are enabled by default (GitLab and generic webhooks), while you must first add the required configuration and enable the others (GitHub, Jira, and Figma).

### Extending the configuration

@@ -51,7 +54,7 @@ There are some additional things you may wish to configure about the bridge.
Take a look at:

- `roles/custom/matrix-bridge-hookshot/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bridge-hookshot/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_hookshot_configuration_extension_yaml` and `matrix_hookshot_registration_extension_yaml` variables
- `roles/custom/matrix-bridge-hookshot/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bridge_hookshot_configuration_extension_yaml` and `matrix_bridge_hookshot_registration_extension_yaml` variables

Refer the [official instructions](https://matrix-org.github.io/matrix-hookshot/latest/setup.html) and the comments in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml) to learn what the individual options do.

@@ -96,31 +99,31 @@ Unless indicated otherwise, the following endpoints are reachable on your `matri

| Listener | Default path | Variable | Used as |
|---|---|---|---|
| - | `/hookshot/webhooks/` | `matrix_hookshot_webhook_endpoint` | Webhook-prefix, which affects all webhook-related URLs below |
| generic | `/hookshot/webhooks/webhook` | `matrix_hookshot_generic_endpoint` | Generic webhooks |
| github oauth | `/hookshot/webhooks/oauth` | `matrix_hookshot_github_oauth_endpoint` | GitHub "Callback URL" |
| jira oauth | `/hookshot/webhooks/jira/oauth` | `matrix_hookshot_jira_oauth_endpoint` | Jira OAuth |
| figma endpoint | `/hookshot/webhooks/figma/webhook` | `matrix_hookshot_figma_endpoint` | Figma |
| appservice | `/hookshot/_matrix/app/` | `matrix_hookshot_appservice_endpoint` | Matrix server |
| widgets | `/hookshot/widgetapi/` | `matrix_hookshot_widgets_endpoint` | Widgets |
| - | `/hookshot/webhooks/` | `matrix_bridge_hookshot_webhook_endpoint` | Webhook-prefix, which affects all webhook-related URLs below |
| generic | `/hookshot/webhooks/webhook` | `matrix_bridge_hookshot_generic_endpoint` | Generic webhooks |
| github oauth | `/hookshot/webhooks/oauth` | `matrix_bridge_hookshot_github_oauth_endpoint` | GitHub "Callback URL" |
| jira oauth | `/hookshot/webhooks/jira/oauth` | `matrix_bridge_hookshot_jira_oauth_endpoint` | Jira OAuth |
| figma endpoint | `/hookshot/webhooks/figma/webhook` | `matrix_bridge_hookshot_figma_endpoint` | Figma |
| appservice | `/hookshot/_matrix/app/` | `matrix_bridge_hookshot_appservice_endpoint` | Matrix server |
| widgets | `/hookshot/widgetapi/` | `matrix_bridge_hookshot_widgets_endpoint` | Widgets |

Also see the various `matrix_hookshot_container_labels_*` variables in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml), which expose URLs publicly.
Also see the various `matrix_bridge_hookshot_container_labels_*` variables in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml), which expose URLs publicly.

The different listeners are also reachable *internally* in the docker-network via the container's name (configured by `matrix_hookshot_container_url`) and on different ports (e.g. `matrix_hookshot_appservice_port`). Read [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml) in detail for more info.
The different listeners are also reachable *internally* in the docker-network via the container's name (configured by `matrix_bridge_hookshot_container_url`) and on different ports (e.g. `matrix_bridge_hookshot_appservice_port`). Read [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml) in detail for more info.

### Manage GitHub Private Key with aux role

The GitHub bridge requires you to install a private key file. This can be done in multiple ways:

- copy the *contents* of the downloaded file and set the variable `matrix_hookshot_github_private_key` to the contents (see example in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml)).
- somehow copy the file to the path `{{ matrix_hookshot_base_path }}/{{ matrix_hookshot_github_private_key_file }}` (default: `/matrix/hookshot/private-key.pem`) on the server manually.
- copy the *contents* of the downloaded file and set the variable `matrix_bridge_hookshot_github_private_key` to the contents (see example in [main.yml](../roles/custom/matrix-bridge-hookshot/defaults/main.yml)).
- somehow copy the file to the path `{{ matrix_bridge_hookshot_base_path }}/{{ matrix_bridge_hookshot_github_private_key_file }}` (default: `/matrix/hookshot/private-key.pem`) on the server manually.
- use the [`aux` role](https://github.com/mother-of-all-self-hosting/ansible-role-aux) to copy the file from an arbitrary path on your ansible client to the correct path on the server.

To use the `aux` role, make sure the `matrix_hookshot_github_private_key` variable is empty. Then add the following configuration to your `vars.yml` file:
To use the `aux` role, make sure the `matrix_bridge_hookshot_github_private_key` variable is empty. Then add the following configuration to your `vars.yml` file:

```yaml
aux_file_definitions:
- dest: "{{ matrix_hookshot_base_path }}/{{ matrix_hookshot_github_private_key_file }}"
- dest: "{{ matrix_bridge_hookshot_base_path }}/{{ matrix_bridge_hookshot_github_private_key_file }}"
content: "{{ lookup('file', '/path/to/your-github-private-key.pem') }}"
mode: '0400'
owner: "{{ matrix_user_name }}"
@@ -139,23 +142,23 @@ To enable the metrics, add the following configuration to your `vars.yml` file:

```yaml
# Expose metrics (locally, on the container network).
matrix_hookshot_metrics_enabled: true
matrix_bridge_hookshot_metrics_enabled: true
```

**To collect metrics from an external Prometheus server**, besides enabling metrics as described above, you will also need to enable metrics exposure on `https://matrix.example.com/metrics/hookshot` by adding the following configuration to your `vars.yml` file:

```yaml
matrix_hookshot_metrics_proxying_enabled: true
matrix_bridge_hookshot_metrics_proxying_enabled: true
```

By default metrics are exposed publicly **without** password-protection. To password-protect the metrics with dedicated credentials, add the following configuration to your `vars.yml` file:

```yaml
matrix_hookshot_container_labels_metrics_middleware_basic_auth_enabled: true
matrix_hookshot_container_labels_metrics_middleware_basic_auth_users: ''
matrix_bridge_hookshot_container_labels_metrics_middleware_basic_auth_enabled: true
matrix_bridge_hookshot_container_labels_metrics_middleware_basic_auth_users: ''
```

To `matrix_hookshot_container_labels_metrics_middleware_basic_auth_users`, set the Basic Authentication credentials (raw `htpasswd` file content) used to protect the endpoint. See https://doc.traefik.io/traefik/middlewares/http/basicauth/#users for details about it.
To `matrix_bridge_hookshot_container_labels_metrics_middleware_basic_auth_users`, set the Basic Authentication credentials (raw `htpasswd` file content) used to protect the endpoint. See https://doc.traefik.io/traefik/middlewares/http/basicauth/#users for details about it.

**Note**: alternatively, you can use `matrix_metrics_exposure_enabled` to expose all services on this `/metrics/*` feature, and you can use `matrix_metrics_exposure_http_basic_auth_enabled` and `matrix_metrics_exposure_http_basic_auth_users` to password-protect the metrics of them. See [this section](configuring-playbook-prometheus-grafana.md#collecting-metrics-to-an-external-prometheus-server) for more information.

@@ -175,5 +178,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: error, warn, info, debug
matrix_hookshot_logging_level: debug
matrix_bridge_hookshot_logging_level: debug
```

+ 10
- 10
docs/configuring-playbook-bridge-matrix-bridge-sms.md View File

@@ -21,23 +21,23 @@ The bridge uses [android-sms-gateway-server](https://github.com/RebekkaMa/androi
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_sms_bridge_enabled: true
matrix_bridge_sms_enabled: true

# (optional but recommended) a room ID to a default room
matrix_sms_bridge_default_room: ""
matrix_bridge_sms_default_room: ""

# (optional but recommended) configure your server location
matrix_sms_bridge_default_region: DE
matrix_sms_bridge_default_timezone: Europe/Berlin
matrix_bridge_sms_default_region: DE
matrix_bridge_sms_default_timezone: Europe/Berlin

# Settings to connect to android-sms-gateway-server
matrix_sms_bridge_provider_android_baseurl: https://192.168.24.24:9090
matrix_sms_bridge_provider_android_username: admin
matrix_sms_bridge_provider_android_password: supeSecretPassword
matrix_bridge_sms_provider_android_baseurl: https://192.168.24.24:9090
matrix_bridge_sms_provider_android_username: admin
matrix_bridge_sms_provider_android_password: supeSecretPassword

# (optional) if your android-sms-gateway-server uses a self signed vertificate, the bridge needs a "truststore". This can be the certificate itself.
matrix_sms_bridge_provider_android_truststore_local_path: android-sms-gateway-server.p12
matrix_sms_bridge_provider_android_truststore_password: 123
matrix_bridge_sms_provider_android_truststore_local_path: android-sms-gateway-server.p12
matrix_bridge_sms_provider_android_truststore_password: 123
```

### Extending the configuration
@@ -46,7 +46,7 @@ There are some additional things you may wish to configure about the bridge.

Take a look at:

- `roles/custom/matrix-bridge-sms/defaults/main.yml` for some variables that you can customize via your `vars.yml` file. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_sms_bridge_configuration_extension_yaml` variable
- `roles/custom/matrix-bridge-sms/defaults/main.yml` for some variables that you can customize via your `vars.yml` file. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bridge_sms_configuration_extension_yaml` variable

## Installing



+ 2
- 2
docs/configuring-playbook-bridge-mautrix-bluesky.md View File

@@ -27,7 +27,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_bluesky_enabled: true
matrix_bridge_mautrix_bluesky_enabled: true
```

### Extending the configuration
@@ -70,5 +70,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_bluesky_logging_level: 'debug'
matrix_bridge_mautrix_bluesky_logging_level: 'debug'
```

+ 43
- 14
docs/configuring-playbook-bridge-mautrix-bridges.md View File

@@ -21,12 +21,12 @@ To enable the bridge, add the following configuration to your `inventory/host_va

```yaml
# Replace SERVICENAME with one of: twitter, discord, signal, googlechat, etc.
matrix_mautrix_SERVICENAME_enabled: true
matrix_bridge_mautrix_SERVICENAME_enabled: true
```

**Note**: for bridging to Meta's Messenger or Instagram, you would need to add `meta` with an underscore symbol (`_`) or hyphen (`-`) based on the context as prefix to each `SERVICENAME`; add `_` to variables (as in `matrix_mautrix_meta_messenger_configuration_extension_yaml` for example) and `-` to paths of the configuration files (as in `roles/custom/matrix-bridge-mautrix-meta-messenger/templates/config.yaml.j2`), respectively.
**Note**: for bridging to Meta's Messenger or Instagram, you would need to add `meta` with an underscore symbol (`_`) or hyphen (`-`) based on the context as prefix to each `SERVICENAME`; add `_` to variables (as in `matrix_bridge_mautrix_meta_messenger_configuration_extension_yaml` for example) and `-` to paths of the configuration files (as in `roles/custom/matrix-bridge-mautrix-meta-messenger/templates/config.yaml.j2`), respectively.

There are some additional things you may wish to configure about the bridge before you continue. Each bridge may have additional requirements besides `_enabled: true`. For example, the mautrix-telegram bridge (our documentation page about it is [here](configuring-playbook-bridge-mautrix-telegram.md)) requires the `matrix_mautrix_telegram_api_id` and `matrix_mautrix_telegram_api_hash` variables to be defined. Refer to each bridge's individual documentation page for details about enabling bridges.
There are some additional things you may wish to configure about the bridge before you continue. Each bridge may have additional requirements besides `_enabled: true`. For example, the mautrix-telegram bridge (our documentation page about it is [here](configuring-playbook-bridge-mautrix-telegram.md)) requires the `matrix_bridge_mautrix_telegram_api_id` and `matrix_bridge_mautrix_telegram_api_hash` variables to be defined. Refer to each bridge's individual documentation page for details about enabling bridges.

### Configure bridge permissions (optional)

@@ -43,7 +43,7 @@ If you don't define the `matrix_admin` in your configuration (e.g. `matrix_admin
**Alternatively** (more verbose, but allows multiple admins to be configured), you can do the same on a per-bridge basis with:

```yaml
matrix_mautrix_SERVICENAME_configuration_extension_yaml: |
matrix_bridge_mautrix_SERVICENAME_configuration_extension_yaml: |
bridge:
permissions:
'@alice:{{ matrix_domain }}': admin
@@ -67,8 +67,8 @@ matrix_bridges_encryption_default: true
**Alternatively**, for a specific bridge:

```yaml
matrix_mautrix_SERVICENAME_bridge_encryption_enabled: true
matrix_mautrix_SERVICENAME_bridge_encryption_default: true
matrix_bridge_mautrix_SERVICENAME_bridge_encryption_enabled: true
matrix_bridge_mautrix_SERVICENAME_bridge_encryption_default: true
```

### Enable relay mode (optional)
@@ -86,16 +86,16 @@ matrix_bridges_relay_enabled: true
**Alternatively**, for a specific bridge:

```yaml
matrix_mautrix_SERVICENAME_configuration_extension_yaml: |
matrix_bridge_mautrix_SERVICENAME_configuration_extension_yaml: |
bridge:
relay:
enabled: true
```

You can only have one `matrix_mautrix_SERVICENAME_configuration_extension_yaml` definition in `vars.yml` per bridge, so if you need multiple pieces of configuration there, just merge them like this:
You can only have one `matrix_bridge_mautrix_SERVICENAME_configuration_extension_yaml` definition in `vars.yml` per bridge, so if you need multiple pieces of configuration there, just merge them like this:

```yaml
matrix_mautrix_SERVICENAME_configuration_extension_yaml: |
matrix_bridge_mautrix_SERVICENAME_configuration_extension_yaml: |
bridge:
relay:
enabled: true
@@ -115,7 +115,7 @@ Use `!prefix set-pl 100` to be able for the bot to modify room settings and invi
By default, only admins are allowed to set themselves as relay users. To allow anyone on your homeserver to set themselves as relay users, add the following configuration to your `vars.yml` file:

```yaml
matrix_mautrix_SERVICENAME_bridge_relay_admin_only: false
matrix_bridge_mautrix_SERVICENAME_bridge_relay_admin_only: false
```

### Set the bot's username (optional)
@@ -123,7 +123,7 @@ matrix_mautrix_SERVICENAME_bridge_relay_admin_only: false
To set the bot's username, add the following configuration to your `vars.yml` file:

```yaml
matrix_mautrix_SERVICENAME_appservice_bot_username: "BOTNAME"
matrix_bridge_mautrix_SERVICENAME_appservice_bot_username: "BOTNAME"
```

### Configure the logging level (optional)
@@ -131,13 +131,42 @@ matrix_mautrix_SERVICENAME_appservice_bot_username: "BOTNAME"
To specify the logging level, add the following configuration to your `vars.yml` file:

```yaml
matrix_mautrix_SERVICENAME_logging_level: warn
matrix_bridge_mautrix_SERVICENAME_logging_level: warn
```

Replace `warn` with one of the following to control the verbosity of the logs generated: `trace`, `debug`, `info`, `warn`, `error` or `fatal`.

If you have issues with a service, and are requesting support, the higher levels of logging (those that appear earlier in the list, like `trace`) will generally be more helpful.

### Expose the bridge's API (for Mautrix Manager and similar tools)

Each mautrix bridge runs an HTTP API which tools like [Mautrix Manager](https://github.com/mautrix/manager) can use to help you log into the bridge. This is especially handy for bridges where logging in manually is cumbersome (like [mautrix-gmessages](configuring-playbook-bridge-mautrix-gmessages.md)).

By default, the playbook exposes this API publicly at `https://matrix.example.com/bridges/SERVICENAME` (for example, `https://matrix.example.com/bridges/gmessages`). Such tools authenticate to the bridge with your own Matrix access token, so you never need to share any bridge secret with them.

To make discovery easier, the playbook also serves a `/.well-known/matrix/mautrix` file which advertises all your exposed bridges. Mautrix Manager reads this file and offers your bridges automatically, so you don't need to enter their URLs by hand.

This is all enabled by default. To **disable exposing the API for all bridges**, add the following configuration to your `vars.yml` file:

```yaml
matrix_bridges_exposure_enabled: false
```

**Alternatively**, to disable it for a specific bridge:

```yaml
matrix_bridge_mautrix_SERVICENAME_exposure_enabled: false
```

If you run additional bridges on the same server which are not managed by this playbook and would like compatible tools to discover them as well, you can advertise their base URLs in the `/.well-known/matrix/mautrix` file:

```yaml
matrix_static_files_file_matrix_mautrix_property_fi_mau_bridges_custom:
- https://matrix.example.com/bridges/SOME_OTHER_BRIDGE
```

Only list bridges hosted on (and connected to) this server here, as compatible tools will send your Matrix access token to them. For bridges on other servers, take a look at the `fi.mau.external_bridge_servers` property described in the [Mautrix Manager](https://github.com/mautrix/manager) documentation, which you can add via `matrix_static_files_file_matrix_mautrix_configuration_extension_json`.

### Extending the configuration

There are some additional things you may wish to configure about the bridge.
@@ -145,7 +174,7 @@ There are some additional things you may wish to configure about the bridge.
Take a look at:

- `roles/custom/matrix-bridge-mautrix-SERVICENAME/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bridge-mautrix-SERVICENAME/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_mautrix_SERVICENAME_configuration_extension_yaml` variable
- `roles/custom/matrix-bridge-mautrix-SERVICENAME/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bridge_mautrix_SERVICENAME_configuration_extension_yaml` variable

## Installing

@@ -197,7 +226,7 @@ This is the recommended way of setting up Double Puppeting, as it's easier to ac
- Previously there were multiple different automatic double puppeting methods like one with the help of the [Shared Secret Auth password provider module](./configuring-playbook-shared-secret-auth.md), but they have been superseded by this Appservice Double Puppet method. Double puppeting with the Shared Secret Auth works at the time of writing, but is deprecated and will stop working in the future as the older methods were completely removed in the megabridge rewrites on [the upstream project](https://docs.mau.fi/bridges/general/double-puppeting.html#automatically).

<!-- TODO: remove this note if the Shared Secret Auth service has stopped working or the bridges have been removed -->
- Some bridges like [the deprecated Facebook mautrix bridge](configuring-playbook-bridge-mautrix-facebook.md) and [matrix-appservice-kakaotalk](configuring-playbook-bridge-appservice-kakaotalk.md), which is partially based on the Facebook bridge, are compatible with the Shared Secret Auth service only. These bridges automatically perform Double Puppeting if [Shared Secret Auth](configuring-playbook-shared-secret-auth.md) service is configured and enabled on the server for this playbook.
- Some bridges like [the deprecated Facebook mautrix bridge](configuring-playbook-bridge-mautrix-facebook.md) are compatible with the Shared Secret Auth service only. These bridges automatically perform Double Puppeting if [Shared Secret Auth](configuring-playbook-shared-secret-auth.md) service is configured and enabled on the server for this playbook.

#### Method 2: manually, by asking each user to provide a working access token



+ 2
- 2
docs/configuring-playbook-bridge-mautrix-discord.md View File

@@ -39,7 +39,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_discord_enabled: true
matrix_bridge_mautrix_discord_enabled: true
```

### Extending the configuration
@@ -96,7 +96,7 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_discord_logging_level: 'debug'
matrix_bridge_mautrix_discord_logging_level: 'debug'
```

### Command requires room admin rights when user is creator


+ 2
- 2
docs/configuring-playbook-bridge-mautrix-gmessages.md View File

@@ -27,7 +27,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_gmessages_enabled: true
matrix_bridge_mautrix_gmessages_enabled: true
```

### Extending the configuration
@@ -68,5 +68,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_gmessages_logging_level: 'debug'
matrix_bridge_mautrix_gmessages_logging_level: 'debug'
```

+ 2
- 2
docs/configuring-playbook-bridge-mautrix-googlechat.md View File

@@ -30,7 +30,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the [Google Chat](https://chat.google.com/) bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_googlechat_enabled: true
matrix_bridge_mautrix_googlechat_enabled: true
```

### Extending the configuration
@@ -70,5 +70,5 @@ As with all other services, you can find the logs in [systemd-journald](https://
The default logging level for this component is `WARNING`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
matrix_mautrix_googlechat_logging_level: DEBUG
matrix_bridge_mautrix_googlechat_logging_level: DEBUG
```

+ 73
- 0
docs/configuring-playbook-bridge-mautrix-gvoice.md View File

@@ -0,0 +1,73 @@
<!--
SPDX-FileCopyrightText: 2026 MDAD project contributors
SPDX-FileCopyrightText: 2026 Nikita Chernyi

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Mautrix Google Voice bridging (optional)

<sup>Refer the common guide for configuring mautrix bridges: [Setting up a Generic Mautrix Bridge](configuring-playbook-bridge-mautrix-bridges.md)</sup>

The playbook can install and configure [mautrix-gvoice](https://github.com/mautrix/gvoice) for you, for bridging to [Google Voice](https://voice.google.com/).

See the project's [documentation](https://docs.mau.fi/bridges/go/gvoice/index.html) to learn what it does and why it might be useful to you.

## Prerequisite (optional)

### Enable Appservice Double Puppet

If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) (hint: you most likely do) for this bridge automatically, you need to have enabled [Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md) for this playbook.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-puppeting-optional) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about setting up Double Puppeting.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bridge_mautrix_gvoice_enabled: true
```

### Extending the configuration

There are some additional things you may wish to configure about the bridge.

<!-- NOTE: relay mode is not supported for this bridge -->
See [this section](configuring-playbook-bridge-mautrix-bridges.md#extending-the-configuration) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about variables that you can customize and the bridge's default configuration, including [bridge permissions](configuring-playbook-bridge-mautrix-bridges.md#configure-bridge-permissions-optional), [encryption support](configuring-playbook-bridge-mautrix-bridges.md#enable-encryption-optional), [bot's username](configuring-playbook-bridge-mautrix-bridges.md#set-the-bots-username-optional), etc.

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

To use the bridge, start a chat with `@gvoicebot:example.com` (where `example.com` is your base domain, not the `matrix.` domain).

Google Voice has no phone to pair and no QR code to scan. It logs in with cookies, which you copy from a browser already signed in to [voice.google.com](https://voice.google.com/) and hand to the bot. It is fiddlier than scanning a code and feels more suspicious than it is, but Google leaves no cleaner door open. The bridge's [official Authentication guide](https://docs.mau.fi/bridges/go/gvoice/authentication.html) has the exact cookies to grab and the steps for grabbing them.

Those cookies are a login session, and Google expires them on its own schedule. When they lapse the bridge goes quiet and you log in again. Nothing is broken, that is just how cookie auth ages.

Once you log in, the bridge builds portal rooms for your recent conversations and carries text and media both ways. Don't reach for it to start a brand-new chat or to place a call, though. That ground still belongs to Google Voice, so keep the app around for those.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-mautrix-gvoice`.

### Increase logging verbosity

The default logging level for this component is `warn`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_bridge_mautrix_gvoice_logging_level: 'debug'
```

+ 112
- 0
docs/configuring-playbook-bridge-mautrix-linkedin.md View File

@@ -0,0 +1,112 @@
<!--
SPDX-FileCopyrightText: 2026 MDAD project contributors
SPDX-FileCopyrightText: 2026 Nikita Chernyi
SPDX-FileCopyrightText: 2026 Suguru Hirahara

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Mautrix LinkedIn bridging (optional)

<sup>Refer the common guide for configuring mautrix bridges: [Setting up a Generic Mautrix Bridge](configuring-playbook-bridge-mautrix-bridges.md)</sup>

The playbook can install and configure [mautrix-linkedin](https://github.com/mautrix/linkedin) for you, for bridging to [LinkedIn](https://www.linkedin.com/) messaging.

See the project's [documentation](https://docs.mau.fi/bridges/go/linkedin/index.html) to learn what it does and why it might be useful to you.

>[!NOTE]
> LinkedIn keeps its messaging function behind a login wall and does not provide a usable public API, so using this bridge requires you to manually copy cookies on a web browser for logging in. Refer to [this section](#usage) below for details.

## Prerequisite

### Uninstalling `beeper-linkedin`

If `beeper-linkedin` bridge is enabled on your host, you need to uninstall it first, since it claims the `@linkedinbot` username and `@linkedin_*` user range as exclusive appservice namespaces, which will cause conflicts with `mautrix-linkedin`.

To uninstall the bridge, set `matrix_bridge_beeper_linkedin_enabled: false` and re-run the playbook. The playbook refuses to install `mautrix-linkedin` until `beeper-linkedin` is uninstalled.

### Enable Appservice Double Puppet (optional)

If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) (hint: you most likely do) for this bridge automatically, you need to have enabled [Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md) for this playbook.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-puppeting-optional) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about setting up Double Puppeting.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bridge_mautrix_linkedin_enabled: true
```

### Extending the configuration

There are some additional things you may wish to configure about the bridge.

<!-- NOTE: relay mode is not supported for this bridge -->
See [this section](configuring-playbook-bridge-mautrix-bridges.md#extending-the-configuration) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about variables that you can customize and the bridge's default configuration, including [bridge permissions](configuring-playbook-bridge-mautrix-bridges.md#configure-bridge-permissions-optional), [encryption support](configuring-playbook-bridge-mautrix-bridges.md#enable-encryption-optional), [bot's username](configuring-playbook-bridge-mautrix-bridges.md#set-the-bots-username-optional), etc.

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

Start a chat with `@linkedinbot:example.com` (where `example.com` is your base domain, the bare one without the `matrix.` prefix) and send `login`.

### Logging in

To log in, you need to sign in to LinkedIn with a web browser and hand one of the requests it makes to the bot. Because the bridge presents itself as Chrome on Linux, the request needs to come from **Chrome or a Chrome-based browser**.

>[!WARNING]
> LinkedIn ties the session to the browser that made the request and rejects it when it is replayed under a different user-agent. A request copied from Firefox therefore results in a session that stops working immediately, without an error message.

You need to follow these steps to log in:

1. Open [linkedin.com](https://www.linkedin.com/) in a private/incognito window on Chrome / a Chrome-based browser
2. Sign in to LinkedIn
3. Open your browser's devtools (F12) and go to the Network tab
4. Filter for `graphql`
5. Right-click any one of those requests, then "Copy" and "Copy as cURL"
6. Paste the output into the chat with the bot and send it

The bridge's [official Authentication guide](https://docs.mau.fi/bridges/go/linkedin/authentication.html) walks the same steps with screenshots.

Once you log in, the bridge builds portal rooms for your recent conversations and carries messages both ways.

**💡 Notes:**

- The request contains a login session, which LinkedIn may expire at any time. When the bridge goes quiet, log in again by following the steps above.
- If you would rather not retrieve the request yourself, you may wish to take a look at [mautrix-manager](https://github.com/mautrix/manager).

## Troubleshooting

### The bot does not respond after you send it the cURL output

This most likely means that you have obtained the request with a browser other than Chrome or a Chrome-based one. LinkedIn silently discards a session replayed under a different user-agent. Follow the login steps above again, this time using Chrome or a Chrome-based browser.

### The bridge worked before, but has gone quiet

Your LinkedIn session has most likely expired. Send `login` to the bot and follow the login steps above again.

### Other issues

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-mautrix-linkedin`.

### Increase logging verbosity

The default logging level for this component is `warn`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_bridge_mautrix_linkedin_logging_level: 'debug'
```

+ 4
- 4
docs/configuring-playbook-bridge-mautrix-meta-instagram.md View File

@@ -13,7 +13,7 @@ The playbook can install and configure the [mautrix-meta](https://github.com/mau

See the project's [documentation](https://docs.mau.fi/bridges/go/meta/index.html) to learn what it does and why it might be useful to you.

Since this bridge component can bridge to both [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/) and you may wish to do both at the same time, the playbook makes it available via 2 different Ansible roles (`matrix-bridge-mautrix-meta-messenger` and `matrix-bridge-mautrix-meta-instagram`). The latter is a reconfigured copy of the first one (created by `just rebuild-mautrix-meta-instagram` and `bin/rebuild-mautrix-meta-instagram.sh`).
The mautrix-meta project provides bridging to both [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/), each via a separate bridge (its own binary and container image) since mautrix-meta v26.07. The playbook makes them available via 2 different Ansible roles (`matrix-bridge-mautrix-meta-messenger` and `matrix-bridge-mautrix-meta-instagram`), which can both be enabled at the same time.

This documentation page only deals with the bridge's ability to bridge to Instagram. For bridging to Facebook/Messenger, see [Setting up Messenger bridging via Mautrix Meta](configuring-playbook-bridge-mautrix-meta-messenger.md).

@@ -23,7 +23,7 @@ This documentation page only deals with the bridge's ability to bridge to Instag

If you've been using the [mautrix-instagram](./configuring-playbook-bridge-mautrix-instagram.md) bridge, **you'd better get rid of it first** or the 2 bridges will be in conflict:

- both trying to use `@instagrambot:example.com` as their username. This conflict may be resolved by adjusting `matrix_mautrix_instagram_appservice_bot_username` or `matrix_mautrix_meta_instagram_appservice_username`
- both trying to use `@instagrambot:example.com` as their username. This conflict may be resolved by adjusting `matrix_mautrix_instagram_appservice_bot_username` or `matrix_bridge_mautrix_meta_instagram_appservice_username`
- both trying to bridge the same DMs

To do so, send a `clean-rooms` command to the management room with the old bridge bot (`@instagrambot:example.com`). It gives you a list of portals and groups of portals you may purge. Proceed with sending commands like `clean recommended`, etc.
@@ -41,7 +41,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_meta_instagram_enabled: true
matrix_bridge_mautrix_meta_instagram_enabled: true
```

Before proceeding to [re-running the playbook](./installing.md), you may wish to adjust the configuration further. See below.
@@ -83,5 +83,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# This bridge uses zerolog, so valid levels are: panic, fatal, error, warn, info, debug, trace
matrix_mautrix_meta_instagram_logging_min_level: debug
matrix_bridge_mautrix_meta_instagram_logging_min_level: debug
```

+ 4
- 4
docs/configuring-playbook-bridge-mautrix-meta-messenger.md View File

@@ -14,7 +14,7 @@ The playbook can install and configure the [mautrix-meta](https://github.com/mau

See the project's [documentation](https://docs.mau.fi/bridges/go/meta/index.html) to learn what it does and why it might be useful to you.

Since this bridge component can bridge to both [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/) and you may wish to do both at the same time, the playbook makes it available via 2 different Ansible roles (`matrix-bridge-mautrix-meta-messenger` and `matrix-bridge-mautrix-meta-instagram`). The latter is a reconfigured copy of the first one (created by `just rebuild-mautrix-meta-instagram` and `bin/rebuild-mautrix-meta-instagram.sh`).
The mautrix-meta project provides bridging to both [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/), each via a separate bridge (its own binary and container image) since mautrix-meta v26.07. The playbook makes them available via 2 different Ansible roles (`matrix-bridge-mautrix-meta-messenger` and `matrix-bridge-mautrix-meta-instagram`), which can both be enabled at the same time.

This documentation page only deals with the bridge's ability to bridge to Facebook Messenger. For bridging to Instagram, see [Setting up Instagram bridging via Mautrix Meta](configuring-playbook-bridge-mautrix-meta-instagram.md).

@@ -41,7 +41,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_meta_messenger_enabled: true
matrix_bridge_mautrix_meta_messenger_enabled: true
```

Before proceeding to [re-running the playbook](./installing.md), you may wish to adjust the configuration further. See below.
@@ -56,7 +56,7 @@ The bridge can pull your Messenger messages via 3 different methods:
- (`facebook-tor`) Facebook via `facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion` ([Tor](https://www.torproject.org/)) — does not currently proxy media downloads
- (default) (`messenger`) Messenger via `messenger.com` — usable even without a Facebook account

You may switch the mode via the `matrix_mautrix_meta_messenger_meta_mode` variable. The playbook defaults to the `messenger` mode, because it's most universal (every Facebook user has a Messenger account, but the opposite is not true).
You may switch the mode via the `matrix_bridge_mautrix_meta_messenger_meta_mode` variable. The playbook defaults to the `messenger` mode, because it's most universal (every Facebook user has a Messenger account, but the opposite is not true).

Note that switching the mode (especially between `facebook*` and `messenger`) will intentionally make the bridge use another database (`matrix_mautrix_meta_facebook` or `matrix_mautrix_meta_messenger`) to isolate the 2 instances. Switching between Tor and non-Tor may be possible without dataloss, but your mileage may vary. Before switching to a new mode, you may wish to de-configure the old one (send `help` to the bridge bot and unbridge your portals, etc.).

@@ -99,5 +99,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# This bridge uses zerolog, so valid levels are: panic, fatal, error, warn, info, debug, trace
matrix_mautrix_meta_messenger_logging_min_level: debug
matrix_bridge_mautrix_meta_messenger_logging_min_level: debug
```

+ 3
- 3
docs/configuring-playbook-bridge-mautrix-signal.md View File

@@ -28,7 +28,7 @@ See the project's [documentation](https://docs.mau.fi/bridges/go/signal/index.ht

If you're running with the Postgres database server integrated by the playbook (which is the default), you don't need to do anything special and can easily proceed with installing.

However, if you're [using an external Postgres server](configuring-playbook-external-postgres.md), you'd need to manually prepare a Postgres database for this bridge and adjust the variables related to that (`matrix_mautrix_signal_database_*`).
However, if you're [using an external Postgres server](configuring-playbook-external-postgres.md), you'd need to manually prepare a Postgres database for this bridge and adjust the variables related to that (`matrix_bridge_mautrix_signal_database_*`).

### Enable Appservice Double Puppet

@@ -41,7 +41,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_signal_enabled: true
matrix_bridge_mautrix_signal_enabled: true
```

### Extending the configuration
@@ -83,5 +83,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_signal_logging_level: 'debug'
matrix_bridge_mautrix_signal_logging_level: 'debug'
```

+ 2
- 2
docs/configuring-playbook-bridge-mautrix-slack.md View File

@@ -34,7 +34,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_slack_enabled: true
matrix_bridge_mautrix_slack_enabled: true
```

### Extending the configuration
@@ -74,5 +74,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_slack_logging_level: 'debug'
matrix_bridge_mautrix_slack_logging_level: 'debug'
```

+ 13
- 39
docs/configuring-playbook-bridge-mautrix-telegram.md View File

@@ -1,5 +1,5 @@
<!--
SPDX-FileCopyrightText: 2018 - 2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2018 - 2026 Slavi Pantaleev
SPDX-FileCopyrightText: 2018 Hugues Morisset
SPDX-FileCopyrightText: 2019 - 2022 MDAD project contributors
SPDX-FileCopyrightText: 2021 Panagiotis Georgiadis
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later

The playbook can install and configure [mautrix-telegram](https://github.com/mautrix/telegram) for you.

See the project's [documentation](https://docs.mau.fi/bridges/python/telegram/index.html) to learn what it does and why it might be useful to you.
See the project's [documentation](https://docs.mau.fi/bridges/go/telegram/index.html) to learn what it does and why it might be useful to you.

## Prerequisites

@@ -25,61 +25,34 @@ See the project's [documentation](https://docs.mau.fi/bridges/python/telegram/in

To use the bridge, you'd need to obtain an API key from [https://my.telegram.org/apps](https://my.telegram.org/apps).

### Enable Appservice Double Puppet or Shared Secret Auth (optional)
### Enable Appservice Double Puppet (optional)

If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) (hint: you most likely do) for this bridge automatically, you need to have enabled [Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md) or [Shared Secret Auth](configuring-playbook-shared-secret-auth.md) service for this playbook.
If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) (hint: you most likely do) for this bridge automatically, you need to have enabled [Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md) service for this playbook.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-puppeting-optional) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about setting up Double Puppeting.

**Notes**:

- Double puppeting with the Shared Secret Auth works at the time of writing, but is deprecated and will stop working in the future.

- If you decided to enable Double Puppeting manually, send `login-matrix` to the bot in order to receive an instruction about how to send an access token to it.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file. Make sure to replace `YOUR_TELEGRAM_APP_ID` and `YOUR_TELEGRAM_API_HASH`.

```yaml
matrix_mautrix_telegram_enabled: true
matrix_mautrix_telegram_api_id: YOUR_TELEGRAM_APP_ID
matrix_mautrix_telegram_api_hash: YOUR_TELEGRAM_API_HASH
matrix_bridge_mautrix_telegram_enabled: true
matrix_bridge_mautrix_telegram_api_id: YOUR_TELEGRAM_APP_ID
matrix_bridge_mautrix_telegram_api_hash: YOUR_TELEGRAM_API_HASH
```

### Relaying

### Enable relay-bot (optional)

If you want to use the relay-bot feature ([relay bot documentation](https://docs.mau.fi/bridges/python/telegram/relay-bot.html)), which allows anonymous user to chat with telegram users, add the following configuration to your `vars.yml` file:

```yaml
matrix_mautrix_telegram_bot_token: YOUR_TELEGRAM_BOT_TOKEN
matrix_mautrix_telegram_configuration_extension_yaml: |
bridge:
permissions:
'*': relaybot
```
This bridge supports the common [mautrix bridge relay mode](configuring-playbook-bridge-mautrix-bridges.md#enable-relay-mode-optional). Once enabled, any authenticated user can be turned into a relaybot for a chat by sending `!tg set-relay` in that chat.

### Configure a user as an administrator of the bridge (optional)

You might also want to give permissions to a user to administrate the bot. See [this section](configuring-playbook-bridge-mautrix-bridges.md#configure-bridge-permissions-optional) on the common guide for details about it.

More details about permissions in this example: https://github.com/mautrix/telegram/blob/master/mautrix_telegram/example-config.yaml#L410

### Use the bridge for direct chats only (optional)

If you want to exclude all groups from syncing and use the Telegram-Bridge only for direct chats, add the following configuration to your `vars.yml` file:

```yaml
matrix_mautrix_telegram_filter_mode: whitelist
```

### Extending the configuration

There are some additional things you may wish to configure about the bridge.

<!-- NOTE: common relay mode is not supported for this bridge -->
See [this section](configuring-playbook-bridge-mautrix-bridges.md#extending-the-configuration) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about variables that you can customize and the bridge's default configuration, including [bridge permissions](configuring-playbook-bridge-mautrix-bridges.md#configure-bridge-permissions-optional), [encryption support](configuring-playbook-bridge-mautrix-bridges.md#enable-encryption-optional), [bot's username](configuring-playbook-bridge-mautrix-bridges.md#set-the-bots-username-optional), etc.

## Installing
@@ -99,9 +72,9 @@ The shortcut commands with the [`just` program](just.md) are also available: `ju

To use the bridge, you need to start a chat with `@telegrambot:example.com` (where `example.com` is your base domain, not the `matrix.` domain).

You can then follow instructions on the bridge's [official documentation on Authentication](https://docs.mau.fi/bridges/python/telegram/authentication.html).
You can then follow instructions on the bridge's [official documentation on Authentication](https://docs.mau.fi/bridges/go/telegram/authentication.html).

After logging in, the bridge will create portal rooms for all of your Telegram groups and invite you to them. Note that the bridge won't automatically create rooms for private chats.
After logging in, the bridge will create portal rooms for all of your Telegram groups and invite you to them.

## Troubleshooting

@@ -109,8 +82,9 @@ As with all other services, you can find the logs in [systemd-journald](https://

### Increase logging verbosity

The default logging level for this component is `WARNING`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:
The default logging level for this component is `warn`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
matrix_mautrix_telegram_logging_level: DEBUG
# Valid values: fatal, error, warn, info, debug, trace
matrix_bridge_mautrix_telegram_logging_level: debug
```

+ 2
- 2
docs/configuring-playbook-bridge-mautrix-twitter.md View File

@@ -28,7 +28,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_twitter_enabled: true
matrix_bridge_mautrix_twitter_enabled: true
```

### Extending the configuration
@@ -69,5 +69,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_twitter_logging_level: 'debug'
matrix_bridge_mautrix_twitter_logging_level: 'debug'
```

+ 2
- 2
docs/configuring-playbook-bridge-mautrix-whatsapp.md View File

@@ -34,7 +34,7 @@ See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_whatsapp_enabled: true
matrix_bridge_mautrix_whatsapp_enabled: true
```

### Extending the configuration
@@ -76,5 +76,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_mautrix_whatsapp_logging_level: 'debug'
matrix_bridge_mautrix_whatsapp_logging_level: 'debug'
```

+ 8
- 8
docs/configuring-playbook-bridge-mautrix-wsproxy.md View File

@@ -25,26 +25,26 @@ When setting, replace `example.com` with your own.
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mautrix_wsproxy_enabled: true
matrix_bridge_mautrix_wsproxy_enabled: true

matrix_mautrix_androidsms_appservice_token: 'secret token from bridge'
matrix_mautrix_androidsms_homeserver_token: 'secret token from bridge'
matrix_mautrix_imessage_appservice_token: 'secret token from bridge'
matrix_mautrix_imessage_homeserver_token: 'secret token from bridge'
matrix_mautrix_wsproxy_syncproxy_shared_secret: 'secret token from bridge'
matrix_bridge_mautrix_wsproxy_androidsms_appservice_token: 'secret token from bridge'
matrix_bridge_mautrix_wsproxy_androidsms_homeserver_token: 'secret token from bridge'
matrix_bridge_mautrix_wsproxy_imessage_appservice_token: 'secret token from bridge'
matrix_bridge_mautrix_wsproxy_imessage_homeserver_token: 'secret token from bridge'
matrix_bridge_mautrix_wsproxy_syncproxy_shared_secret: 'secret token from bridge'
```

Note that the tokens must match what is compiled into the [mautrix-imessage](https://github.com/mautrix/imessage) bridge running on your Mac or Android device.

### Adjusting the wsproxy URL (optional)

By tweaking the `matrix_mautrix_wsproxy_hostname` variable, you can easily make the service available at a **different hostname** than the default one.
By tweaking the `matrix_bridge_mautrix_wsproxy_hostname` variable, you can easily make the service available at a **different hostname** than the default one.

Example additional configuration for your `vars.yml` file:

```yaml
# Change the default hostname
matrix_mautrix_wsproxy_hostname: ws.example.com
matrix_bridge_mautrix_wsproxy_hostname: ws.example.com
```

After changing the domain, **you may need to adjust your DNS** records to point the wsproxy domain to the Matrix server.


+ 95
- 0
docs/configuring-playbook-bridge-meshtastic-relay.md View File

@@ -0,0 +1,95 @@
<!--
SPDX-FileCopyrightText: 2025 - 2026 luschmar
SPDX-FileCopyrightText: 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up a Matrix <-> Meshtastic bridge (optional)

The playbook can install and configure [meshtastic-matrix-relay](https://github.com/jeremiah-k/meshtastic-matrix-relay) (sometimes referred to as `mmrelay`) for you — a bridge between [Matrix](https://matrix.org/) and [Meshtastic](https://meshtastic.org/) mesh networks.

See the [project's documentation](https://github.com/jeremiah-k/meshtastic-matrix-relay) to learn what it does and why it might be useful to you.

## Prerequisites

You need a Matrix account for the bot. You can either [register the bot account manually](registering-users.md) or let the playbook create it when running `ansible-playbook … --tags=ensure-matrix-users-created`. Either way, you'll need the account's **password** to configure the bridge — unlike most other bridges in this playbook, `mmrelay` authenticates with a password and creates its own session (optionally with End-to-End Encryption material).

You also need access to a Meshtastic device, connected to the server via one of:

- **TCP**: the device is reachable on the network (e.g. a Meshtastic node running the TCP API),
- **Serial**: the device is plugged in via USB and available on the host (e.g. `/dev/ttyUSB0`),
- **BLE**: the device is reachable via Bluetooth Low Energy from the host.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bridge_meshtastic_relay_enabled: true

# Password for the bot's Matrix account.
# On first startup, the bridge uses this to log in and persist credentials
# (including End-to-End Encryption material) under its data directory.
# After that, the password can be removed from this variable.
matrix_bridge_meshtastic_relay_matrix_bot_password: "PASSWORD_FOR_THE_BOT"

# How the bridge connects to your Meshtastic device.
# One of: tcp, serial, ble
matrix_bridge_meshtastic_relay_connection_type: tcp

# For connection_type: tcp
matrix_bridge_meshtastic_relay_tcp_host: "meshtastic.local"

# For connection_type: serial
# matrix_bridge_meshtastic_relay_serial_port: "/dev/ttyUSB0"

# For connection_type: ble
# matrix_bridge_meshtastic_relay_ble_address: "AA:BB:CC:DD:EE:FF"

# Matrix rooms to bridge to Meshtastic channels.
matrix_bridge_meshtastic_relay_matrix_rooms_list:
- id: "#meshtastic:{{ matrix_domain }}"
meshtastic_channel: "0"
```

By default, the bot's Matrix ID is `@meshtasticbot:{{ matrix_domain }}`. To change it, adjust `matrix_bridge_meshtastic_relay_matrix_bot_user_id`.

### Bluetooth (BLE) connections

When `matrix_bridge_meshtastic_relay_connection_type` is `ble`, the container runs with `--network=host` and bind-mounts the host's DBus socket — both are required for Bluetooth pairing/communication. Only use this connection type if you trust the playbook-managed host and are comfortable with these privileges.

### Serial connections

When `matrix_bridge_meshtastic_relay_connection_type` is `serial`, the host device referenced by `matrix_bridge_meshtastic_relay_serial_port` is passed through to the container. Make sure that `matrix_user_uid` / `matrix_user_gid` have read/write access to that device (e.g. by adding the matrix user to the `dialout` group, or adjusting udev rules).

### Extending the configuration

There are some additional things you may wish to configure about the bridge.

Take a look at:

- `roles/custom/matrix-bridge-meshtastic-relay/defaults/main.yml` for some variables that you can customize via your `vars.yml` file. You can override individual `matrix_bridge_meshtastic_relay_*` variables, or make finer-grained adjustments via `matrix_bridge_meshtastic_relay_configuration_extension_yaml`.

## Installing

After configuring the playbook, run the playbook with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`.

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

Invite the bot to the Matrix rooms listed in `matrix_bridge_meshtastic_relay_matrix_rooms_list` and it will relay between Matrix and the corresponding Meshtastic channel. Messages sent on Meshtastic will appear in Matrix and vice versa.

See the [project's wiki](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki) for details about commands, plugins and advanced usage.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-meshtastic-relay`.

+ 1
- 1
docs/configuring-playbook-bridge-mx-puppet-groupme.md View File

@@ -18,7 +18,7 @@ See the project's [documentation](https://gitlab.com/xangelix-pub/matrix/mx-pupp
To enable the [GroupMe](https://groupme.com/) bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mx_puppet_groupme_enabled: true
matrix_bridge_mx_puppet_groupme_enabled: true
```

## Installing


+ 1
- 1
docs/configuring-playbook-bridge-mx-puppet-steam.md View File

@@ -20,7 +20,7 @@ See the project's [documentation](https://codeberg.org/icewind/mx-puppet-steam/b
To enable the [Steam](https://steampowered.com/) bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_mx_puppet_steam_enabled: true
matrix_bridge_mx_puppet_steam_enabled: true
```

## Installing


+ 7
- 7
docs/configuring-playbook-bridge-postmoogle.md View File

@@ -24,7 +24,7 @@ Open the following ports on your server to be able to receive incoming emails:

If you don't open these ports, you will still be able to send emails, but not receive any.

These port numbers are configurable via the `matrix_postmoogle_smtp_host_bind_port` and `matrix_postmoogle_submission_host_bind_port` variables, but other email servers will try to deliver on these default (standard) ports, so changing them is of little use.
These port numbers are configurable via the `matrix_bridge_postmoogle_smtp_host_bind_port` and `matrix_bridge_postmoogle_submission_host_bind_port` variables, but other email servers will try to deliver on these default (standard) ports, so changing them is of little use.

## Adjusting DNS records

@@ -44,17 +44,17 @@ To make Postmoogle enable its email sending features, you need to configure MX a
Add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_postmoogle_enabled: true
matrix_bridge_postmoogle_enabled: true

# Uncomment and adjust this part if you'd like to use a username different than the default
# matrix_postmoogle_login: postmoogle
# matrix_bridge_postmoogle_login: postmoogle

# Generate a strong password for the bot. You can create one with a command like `pwgen -s 64 1`.
matrix_postmoogle_password: PASSWORD_FOR_THE_BOT
matrix_bridge_postmoogle_password: PASSWORD_FOR_THE_BOT

# Uncomment to add one or more admins to this bridge:
#
# matrix_postmoogle_admins:
# matrix_bridge_postmoogle_admins:
# - '@yourAdminAccount:{{ matrix_domain }}'
#
# … unless you've made yourself an admin of all bots/bridges like this:
@@ -87,7 +87,7 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,ensure-matrix-use

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

- If you change the bridge's bot password (`matrix_postmoogle_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [synapse-admin](configuring-playbook-synapse-admin.md) to change it, and then update `matrix_postmoogle_password` to let the bot know its new password.
- If you change the bridge's bot password (`matrix_bridge_postmoogle_password` in your `vars.yml` file) subsequently, the bot user's credentials on the homeserver won't be updated automatically. If you'd like to change the bot user's password, use a tool like [Ketesa](configuring-playbook-ketesa.md) to change it, and then update `matrix_bridge_postmoogle_password` to let the bot know its new password.

## Usage

@@ -108,5 +108,5 @@ As with all other services, you can find the logs in [systemd-journald](https://
The default logging level for this component is `INFO`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
matrix_postmoogle_loglevel: 'DEBUG'
matrix_bridge_postmoogle_loglevel: 'DEBUG'
```

+ 100
- 0
docs/configuring-playbook-bridge-rustpush.md View File

@@ -0,0 +1,100 @@
<!--
SPDX-FileCopyrightText: 2026 MDAD project contributors
SPDX-FileCopyrightText: 2026 Jason LaGuidice

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up RustPush (iMessage) bridging (optional)

> **Note:** This bridge is in early development and may have stability issues. It may not be desirable to deploy this to a large number of users. Your testing and feedback is appreciated.

<sup>Refer the common guide for configuring mautrix bridges: [Setting up a Generic Mautrix Bridge](configuring-playbook-bridge-mautrix-bridges.md)</sup>

The playbook can install and configure [RustPush bridge to iMessage](https://github.com/jasonlaguidice/imessage) for you using Apple's push notification service.

See the project's [documentation](https://github.com/jasonlaguidice/imessage/blob/main/README.md) to learn what it does and why it might be useful to you.

## Prerequisites

### Hardware Key Extraction

To use this bridge on Linux (Docker), each user needs a **hardware key** extracted from a real Mac. This key contains hardware identifiers needed for iMessage registration. Hardware keys can be shared by a number of users (approximately 20) before causing issues with Apple.

The key is entered interactively through the bridge bot's login flow (not configured via Ansible variables). See the upstream [README](https://github.com/jasonlaguidice/imessage/blob/main/README.md) for instructions on extracting the key.

If extracted from an Intel Mac, the Mac does not need to remain running after the key is extracted for this bridge to work. Apple Silicon Macs must run a NAC relay and thus must remain running.

### Phone Number Registration (optional)

This bridge can **not** do phone number registration (PNR). The only way to have your phone number registered and used (instead of an Apple ID e-mail address) is to have an iPhone connected to your Apple account. Reference the [BlueBubbles Phone Number Registration Guide](https://docs.bluebubbles.app/server/advanced/registering-a-phone-number-with-your-imessage-account) for information on how to set this up.

### Enable Appservice Double Puppet (optional)

If you want to set up [Double Puppeting](https://docs.mau.fi/bridges/general/double-puppeting.html) (hint: you most likely do) for this bridge automatically, you need to have enabled [Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md) service for this playbook.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#set-up-double-puppeting-optional) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about setting up Double Puppeting.

## Adjusting the playbook configuration

To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_bridge_rustpush_enabled: true
```

### Disable Backfill (optional)

Backfill can be disabled globally if desired via config. By default, the bridge will backfill from iCloud (CloudKit) and APNS if available. Backfill from `chat.db` is only possible when the bridge is running on MacOS.

```yaml
matrix_bridge_rustpush_backfill_enabled: false
```

### Extending the Configuration

There are some additional things you may wish to configure about the bridge.

See [this section](configuring-playbook-bridge-mautrix-bridges.md#extending-the-configuration) on the [common guide for configuring mautrix bridges](configuring-playbook-bridge-mautrix-bridges.md) for details about variables that you can customize and the bridge's default configuration, including [bridge permissions](configuring-playbook-bridge-mautrix-bridges.md#configure-bridge-permissions-optional), [encryption support](configuring-playbook-bridge-mautrix-bridges.md#enable-encryption-optional), [bot's username](configuring-playbook-bridge-mautrix-bridges.md#set-the-bots-username-optional), etc.

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

**Notes**:

- The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed.

## Usage

To use the bridge, you need to start a chat with `@rustpushbot:example.com` (where `example.com` is your base domain, not the `matrix.` domain).

After logging in, the bridge will start receiving iMessages and creating portal rooms.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-rustpush-bridge`.

### Increase logging verbosity

The default logging level for this component is `warn`. If you want to increase the verbosity, add the following configuration to your `vars.yml` file and re-run the playbook:

```yaml
# Valid values: fatal, error, warn, info, debug, trace
matrix_bridge_rustpush_logging_level: 'debug'

# Enable debug logging for RustPush
matrix_bridge_rustpush_rust_log: "warn,rustpushgo=info,openabsinthe=debug"
```
## Notable Configuration Options
- `matrix_bridge_rustpush_statuskit_notifications` will display StatusKit information for conversation participants. In some clients, this update will cause the DM to be pushed to the top of the conversation list continuously, so this option is disabled by default.
- `matrix_bridge_rustpush_statuskit_notification_style` can be set to either `topic` or `notice`
- `topic` sets the status as a room topic. In supported clients (like Cinny and Sable), this will display `🔕 Focus` as a second line when the person has focus mode enabled.
- `notice` sends an `m.notice` event to the room which will display text in the room but should not generate a notification

+ 4
- 1
docs/configuring-playbook-bridge-steam.md View File

@@ -15,7 +15,7 @@ See the project's [documentation](https://github.com/jasonlaguidice/matrix-steam
To enable the [Steam](https://steampowered.com/) bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_steam_bridge_enabled: true
matrix_bridge_steam_enabled: true
```

## Installing
@@ -46,3 +46,6 @@ Once logged in, send `search [name]` to search through recognized Steam friends.
Chat rooms will automatically be opened as new messages are received.

Send `help` to the bot to see the available commands.

## Notable Configuration Options
- `matrix_bridge_steam_network_presence_topic_enabled` and `matrix_bridge_steam_network_presence_topic_rich_presence_enabled` mirror Steam's [Enhanced Rich Presence](https://partner.steamgames.com/doc/features/enhancedrichpresence) feature in Matrix. This will display the user's current game and rich presence if supported by the game. This sets the DM room's `m.topic` field to achieve this. Some games (like Deadlock) update the rich presence every minute with a match timer. In some clients, the topic update will cause the DM to be pushed to the top of the conversation list continuously, so this option is disabled by default.

+ 3
- 3
docs/configuring-playbook-bridge-wechat.md View File

@@ -19,7 +19,7 @@ See the project's [documentation](https://github.com/duo/matrix-wechat/blob/mast
To enable the bridge, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_wechat_enabled: true
matrix_bridge_wechat_enabled: true
```

### Extending the configuration
@@ -29,7 +29,7 @@ There are some additional things you may wish to configure about the bridge.
Take a look at:

- `roles/custom/matrix-bridge-wechat/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-bridge-wechat/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_wechat_configuration_extension_yaml` variable
- `roles/custom/matrix-bridge-wechat/templates/config.yaml.j2` for the bridge's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_bridge_wechat_configuration_extension_yaml` variable

## Installing

@@ -62,5 +62,5 @@ The default logging level for this component is `warn`. If you want to increase

```yaml
# Valid values: fatal, error, warn, info, debug
matrix_wechat_log_level: 'debug'
matrix_bridge_wechat_log_level: 'debug'
```

+ 93
- 0
docs/configuring-playbook-client-commet.md View File

@@ -0,0 +1,93 @@
<!--
SPDX-FileCopyrightText: 2026 MDAD project contributors

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Commet (optional)

The playbook can install and configure the [Commet](https://github.com/commetchat/commet) Matrix web client for you.

## Adjusting DNS records

By default, this playbook installs Commet on the `commet.` subdomain (`commet.example.com`) and requires you to create a CNAME record for `commet`, which targets `matrix.example.com`.

When setting, replace `example.com` with your own.

## Adjusting the playbook configuration

To enable Commet, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_client_commet_enabled: true
```

### Adjusting the Commet URL (optional)

By tweaking the `matrix_client_commet_hostname` and `matrix_client_commet_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.

Example additional configuration for your `vars.yml` file:

```yaml
# Switch to the domain used for Matrix services (`matrix.example.com`),
# so we won't need to add additional DNS records for Commet.
matrix_client_commet_hostname: "{{ matrix_server_fqn_matrix }}"

# Expose under the /commet subpath
matrix_client_commet_path_prefix: /commet
```

After changing the domain, **you may need to adjust your DNS** records to point the Commet domain to the Matrix server.

If you've decided to reuse the `matrix.` domain, you won't need to do any extra DNS configuration.

**Note**: `matrix_client_commet_path_prefix` must either be `/` or not end with a slash (e.g. `/commet`).

### Adjusting the default homeserver (optional)

Commet is configured with a `default_homeserver` value. By default, the playbook uses `matrix.org`.

To change it, add the following configuration to your `vars.yml` file:

```yaml
matrix_client_commet_default_homeserver: "{{ matrix_domain }}"
```

### Adjusting the Commet version/branch to build (optional)

When self-building the container image (`matrix_client_commet_container_image_self_build: true`), the playbook checks out the Commet source repository and builds an image from it.

To build from a different git branch/tag/SHA, set `matrix_client_commet_version` in your `vars.yml` file:

```yaml
# Examples: "main", "v1.2.3", "feature-branch", "a1b2c3d4"
matrix_client_commet_version: "main"
```

**Note**: by default, the image tag is derived from `matrix_client_commet_version` (`localhost/matrix-client-commet:{{ matrix_client_commet_version }}`). If your branch name contains `/` (e.g. `feature/foo`), override `matrix_client_commet_container_image` (and optionally `matrix_client_commet_container_image_self_build_version_tag`) to a Docker-tag-safe value.

### Extending the configuration

There are some additional things you may wish to configure about the component.

Take a look at:

- `roles/custom/matrix-client-commet/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-client-commet/templates/global_config.json.j2` for the component's default runtime configuration

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records), run the playbook with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-client-commet`.

+ 1
- 1
docs/configuring-playbook-client-sable.md View File

@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later

# Setting up Sable (optional)

The playbook can install and configure the [Sable](https://github.com/7w1/sable) Matrix web client for you.
The playbook can install and configure the [Sable](https://github.com/SableClient/Sable) Matrix web client for you.

Sable is a web client focusing primarily on simple, elegant and secure interface. It can be installed alongside or instead of [Element Web](./configuring-playbook-client-element-web.md), [Cinny](./configuring-playbook-client-cinny.md) and others.



+ 6
- 2
docs/configuring-playbook-conduwuit.md View File

@@ -1,6 +1,6 @@
<!--
SPDX-FileCopyrightText: 2019 Eduardo Beltrame
SPDX-FileCopyrightText: 2019-2025 Slavi Pantaleev
SPDX-FileCopyrightText: 2019-2026 Slavi Pantaleev
SPDX-FileCopyrightText: 2020 Tulir Asokan
SPDX-FileCopyrightText: 2021, 2024 MDAD project contributors
SPDX-FileCopyrightText: 2022 Dennis Ciba
@@ -29,13 +29,17 @@ To uninstall the service, run the command below on the server:
systemctl disable --now matrix-conduwuit.service
```

## Migrating to Tuwunel

[Tuwunel](configuring-playbook-tuwunel.md) is a fork of conduwuit, [endorsed as conduwuit's successor](https://github.com/spantaleev/matrix-docker-ansible-deploy/pull/5200#issuecomment-4396211185) by the former conduwuit maintainer. It reads conduwuit's database directly, so migration is possible. Please refer to [this section](./configuring-playbook-tuwunel.md#migrating-from-conduwuit) for details.

## Migrating to Continuwuity

Since [Continuwuity](configuring-playbook-continuwuity.md) is a drop-in replacement for conduwuit, migration is possible. Please refer to [this section](./configuring-playbook-continuwuity.md#migrating-from-conduwuit) for details.

## Removing data manually

If you are not going to migrate to [Continuwuity](configuring-playbook-continuwuity.md), you can remove data by running the command on the server:
If you are not going to migrate to [Tuwunel](configuring-playbook-tuwunel.md) or [Continuwuity](configuring-playbook-continuwuity.md), you can remove data by running the command on the server:

```sh
rm -rf /matrix/conduwuit


+ 7
- 0
docs/configuring-playbook-continuwuity.md View File

@@ -46,6 +46,13 @@ Take a look at:

There are various Ansible variables that control settings in the `continuwuity.toml` file.

💡 By default, the playbook wires Continuwuity into a few playbook-wide settings:

- if `exim_relay_enabled: true` (the default), Continuwuity SMTP is automatically enabled and pointed at the [local Exim relay](configuring-playbook-email.md) service
- `matrix_continuwuity_config_well_known_client` is automatically set to the public homeserver URL in the usual SSL-enabled setup, which helps email verification and password-reset links work in delegated-domain setups

You can override any of these defaults in your `vars.yml` file if you want Continuwuity to use a different SMTP server or a different well-known client URL.

If a specific setting you'd like to change does not have a dedicated Ansible variable, you can either submit a PR to us to add it, or you can [override the setting using an environment variable](https://continuwuity.org/configuration#environment-variables) using `matrix_continuwuity_environment_variables_extension`. For example:

```yaml


+ 1
- 1
docs/configuring-playbook-element-admin.md View File

@@ -13,7 +13,7 @@ Element Admin is a web-based administration panel for Synapse and [Matrix Authen

See the project's [documentation](https://github.com/element-hq/element-admin) to learn more.

💡 **Note**: This project is still very young and doesn't have many features. For now, it's recommended to use [Synapse Admin](./configuring-playbook-synapse-admin.md) instead. Deployments that use [Matrix Authentication Service](./configuring-playbook-matrix-authentication-service.md) can use Element Admin for user-management (something that Synapse Admin can't do), while continuing to use Synapse Admin for all other purposes.
💡 **Note**: This project is still very young and doesn't have many features. [Ketesa](./configuring-playbook-ketesa.md) is the fully-featured alternative — it covers all Synapse and MAS Admin APIs, including complete user management, session management, and MAS policy data. Element Admin remains a valid choice if you prefer its interface.

## Prerequisites



+ 1
- 1
docs/configuring-playbook-email.md View File

@@ -23,7 +23,7 @@ The [Ansible role for exim-relay](https://github.com/mother-of-all-self-hosting/

1. **Final delivery capability**: Can deliver emails directly if you don't have an SMTP server

2. **Centralized configuration**: Configure your upstream SMTP server once in exim-relay, then point all services ([Synapse](configuring-playbook-synapse.md), [Matrix Authentication Service](configuring-playbook-matrix-authentication-service.md), etc.) there—no need to configure SMTP in each component
2. **Centralized configuration**: Configure your upstream SMTP server once in exim-relay, then point all services ([Synapse](configuring-playbook-synapse.md), [Matrix Authentication Service](configuring-playbook-matrix-authentication-service.md), [Continuwuity](configuring-playbook-continuwuity.md), etc.) there, with no need to configure SMTP in each component

3. **Local spooling**: Stores messages locally and retries delivery if your upstream SMTP server is temporarily unavailable



+ 6
- 4
docs/configuring-playbook-federation.md View File

@@ -24,14 +24,14 @@ matrix_synapse_federation_domain_whitelist:

If you wish to disable federation, you can do that with an empty list (`[]`), or better yet by completely disabling federation (see below).

## Exposing the room directory over federation
## Controlling exposure of the room directory over federation

By default, your server's public rooms directory is not exposed to other servers via federation.
By default, your server's public rooms directory is exposed to other servers via federation, so that public rooms hosted on your server can be discovered by users on other servers. This goes against the Synapse upstream default (which is `false`); see the [2023-10-23 changelog entry](../CHANGELOG.md#enabling-allow_public_rooms_over_federation-by-default-for-synapse) for the reasoning behind this choice.

To expose it, add the following configuration to your `vars.yml` file:
To prevent your public rooms directory from being exposed over federation (restoring the Synapse upstream default), add the following configuration to your `vars.yml` file:

```yaml
matrix_synapse_allow_public_rooms_over_federation: true
matrix_synapse_allow_public_rooms_over_federation: false
```

## Disabling federation
@@ -71,4 +71,6 @@ matrix_synapse_federation_port_enabled: false
matrix_synapse_tls_federation_listener_enabled: false
```

**Note**: `matrix_synapse_federation_port_enabled: false` only makes sense in this specific setup, where federation traffic is served through the client port (because of the `federation` entry in `matrix_synapse_http_listener_resource_names`). If federation still flows through the dedicated federation port on your setup (e.g. another reverse proxy of yours forwarding a custom public port to this playbook's federation port), leave `matrix_synapse_federation_port_enabled` at its default (enabled). Disabling it removes the federation route entirely and breaks such setups.

**Use this at you own risk as all the possible side-effects of doing this are not fully known. However, it has been tested and works fine and passes all the tests on <https://federationtester.matrix.org/> without issues.**

+ 0
- 47
docs/configuring-playbook-jwt-service.md View File

@@ -1,47 +0,0 @@
<!--
SPDX-FileCopyrightText: 2024 wjbeckett
SPDX-FileCopyrightText: 2024 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up JWT Service (optional)

The playbook can install and configure [LiveKit JWT Service](https://github.com/element-hq/lk-jwt-service) for you.

LK-JWT-Service is currently used for a single reason: generate JWT tokens with a given identity for a given room, so that users can use them to authenticate against LiveKit SFU.

See the project's [documentation](https://github.com/element-hq/lk-jwt-service/) to learn more.

## Decide on a domain and path

By default, JWT Service is configured to be served:

- on the Matrix domain (`matrix.example.com`), configurable via `matrix_livekit_jwt_service_hostname`
- under a `/livekit-jwt-service` path prefix, configurable via `matrix_livekit_jwt_service_path_prefix`

This makes it easy to set it up, **without** having to adjust your DNS records manually.

## Adjusting DNS records

If you've changed the default hostname, **you may need to adjust your DNS** records accordingly to point to the correct server.

## Adjusting the playbook configuration

Add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_livekit_jwt_service_enabled: true
```

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records), run the [installation](installing.md) command: `just install-all` or `just setup-all`

## Usage

Once installed, a new `org.matrix.msc4143.rtc_foci` section is added to the Element Web client to point to your JWT service URL (e.g., `https://matrix.example.com/livekit-jwt-service`).

## Additional Information

Refer to the LiveKit JWT-Service documentation for more details on configuring and using JWT Service.

+ 101
- 0
docs/configuring-playbook-ketesa.md View File

@@ -0,0 +1,101 @@
<!--
SPDX-FileCopyrightText: 2020-2024 MDAD project contributors
SPDX-FileCopyrightText: 2020-2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2021 Aaron Raimist
SPDX-FileCopyrightText: 2023 Christian González
SPDX-FileCopyrightText: 2024 Nikita Chernyi
SPDX-FileCopyrightText: 2024 Uğur İLTER
SPDX-FileCopyrightText: 2024-2026 Suguru Hirahara
SPDX-FileCopyrightText: 2026 Nikita Chernyi

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Ketesa (optional)

The playbook can install and configure [Ketesa](https://ketesa.app) ([source code](https://github.com/etkecc/ketesa)) for you.

Ketesa is a fully-featured admin interface for Matrix homeservers — manage users, rooms, media, sessions, and more from one clean, responsive web UI. It is the evolution of [Awesome-Technologies/synapse-admin](https://github.com/Awesome-Technologies/synapse-admin): what began as a fork has grown into its own independent project with a redesigned interface, comprehensive Synapse and MAS API coverage, and multi-language support. See the [Ketesa v1.0.0 announcement](https://etke.cc/blog/introducing-ketesa/) for a full overview of what's new.

>[!NOTE]
>
> - Ketesa does not work with other homeserver implementations than Synapse due to API's incompatibility.
> - The latest version of Ketesa is hosted by [etke.cc](https://etke.cc/) at [cloud.ketesa.app](https://cloud.ketesa.app/). If you only need this service occasionally and trust giving your admin credentials to a 3rd party Single Page Application, you can consider using it from there and avoiding the (small) overhead of self-hosting.
> - This playbook also supports an alternative management UI in the shape of [Element Admin](./configuring-playbook-element-admin.md). Please note that it's currently less feature-rich than Ketesa and requires [Matrix Authentication Service](./configuring-playbook-matrix-authentication-service.md).

## Adjusting DNS records (optional)

By default, this playbook installs Ketesa on the `matrix.` subdomain, at the `/synapse-admin` path (https://matrix.example.com/synapse-admin) — the legacy path is kept for backward compatibility. This makes it easy to install it, because it **doesn't require additional DNS records to be set up**. If that's okay, you can skip this section.

If you wish to adjust it, see the section [below](#adjusting-the-ketesa-url-optional) for details about DNS configuration.

## Adjusting the playbook configuration

To enable Ketesa, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_ketesa_enabled: true
```

**Note**: Ketesa requires Synapse's [Admin APIs](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html) to function. Access to them is restricted with a valid access token, so exposing them publicly should not be a real security concern. Still, for additional security, we normally leave them unexposed, following [official Synapse reverse-proxying recommendations](https://element-hq.github.io/synapse/latest/reverse_proxy.html#synapse-administration-endpoints). Because Ketesa needs these APIs to function, when installing Ketesa, the playbook **automatically** exposes the Synapse Admin API publicly for you. Depending on the homeserver implementation you're using (Synapse, Dendrite), this is equivalent to:

- for [Synapse](./configuring-playbook-synapse.md) (our default homeserver implementation): `matrix_synapse_container_labels_public_client_synapse_admin_api_enabled: true`
- for [Dendrite](./configuring-playbook-dendrite.md): `matrix_dendrite_container_labels_public_client_synapse_admin_api_enabled: true`
- for [Tuwunel](./configuring-playbook-tuwunel.md): `matrix_tuwunel_container_labels_public_client_synapse_admin_api_enabled: true`

By default, Ketesa installation will be [restricted to only work with one homeserver](https://github.com/etkecc/ketesa/blob/main/README.md#restricting-available-homeserver) — the one managed by the playbook. To adjust these restrictions, tweak the `matrix_ketesa_config_restrictBaseUrl` variable.

### Adjusting the Ketesa URL (optional)

By tweaking the `matrix_ketesa_hostname` and `matrix_ketesa_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.

We recommend updating the path prefix to `/ketesa` to align with the new branding, while the default `/synapse-admin` is kept for backward compatibility:

```yaml
matrix_ketesa_path_prefix: /ketesa
```

Or to change the hostname entirely:

```yaml
# Change the default hostname and path prefix
matrix_ketesa_hostname: admin.example.com
matrix_ketesa_path_prefix: /
```

If you've changed the default hostname, you may need to create a CNAME record for the Ketesa domain (`admin.example.com`), which targets `matrix.example.com`.

When setting, replace `example.com` with your own.

### Extending the configuration

There are some additional things you may wish to configure about the component.

Take a look at:

- `roles/custom/matrix-ketesa/defaults/main.yml` for some variables that you can customize via your `vars.yml` file. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_ketesa_configuration_extension_json` variable

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records), run the playbook with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

After installation, Ketesa will be accessible at: `https://matrix.example.com/synapse-admin/` (or `/ketesa/` if you updated the path prefix as recommended)

To use Ketesa, you need to have [registered at least one administrator account](registering-users.md) on your server.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-ketesa`.

If you have questions, you can join this community room and feel free to ask: [#ketesa:etke.cc](https://matrix.to/#/#ketesa:etke.cc)

+ 1
- 7
docs/configuring-playbook-ldap-auth.md View File

@@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later

The playbook can install and configure the [matrix-synapse-ldap3](https://github.com/matrix-org/matrix-synapse-ldap3) LDAP Auth password provider for you.

See the project's [documentation](https://github.com/matrix-org/matrix-synapse-ldap3/blob/main/README.rst) to learn what it does and why it might be useful to you.
See the project's [documentation](https://github.com/matrix-org/matrix-synapse-ldap3/blob/main/README.md) to learn what it does and why it might be useful to you.

## Adjusting the playbook configuration

@@ -52,9 +52,3 @@ ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

### Handling user registration

If you wish for users to also be able to make new registrations against LDAP, you may **also** wish to [set up the ldap-registration-proxy](configuring-playbook-matrix-ldap-registration-proxy.md).

+ 6
- 0
docs/configuring-playbook-livekit-server.md View File

@@ -61,6 +61,12 @@ livekit_server_container_labels_turn_traefik_entrypoints: "<your-livekit-turn-tr

and configuring their own Traefik TCP entrypoint dedicated to LiveKit TURN traffic.

## TURN access controls

LiveKit's embedded TURN server enforces a credential TTL and restricts which peer CIDRs it will relay to. The playbook leaves these at the role's secure defaults, which are appropriate for typical deployments where TURN peers live on the public Internet.

If your setup needs TURN to relay to private/restricted ranges, or you want to override the credential TTL, see the [TURN access controls and credential TTL](https://github.com/mother-of-all-self-hosting/ansible-role-livekit-server/blob/main/docs/configuring-livekit-server.md#turn-access-controls-and-credential-ttl) section of the role's documentation.

## Limitations

LiveKit Server's TURN listener behavior depends on where TLS is terminated:


+ 3
- 1
docs/configuring-playbook-matrix-authentication-service.md View File

@@ -51,7 +51,7 @@ This section details what you can expect when switching to the Matrix Authentica

- ❌ **Synapse password providers will need to be disabled**. You can no longer use [shared-secret-auth](./configuring-playbook-shared-secret-auth.md), [rest-auth](./configuring-playbook-rest-auth.md), [LDAP auth](./configuring-playbook-ldap-auth.md), etc. When the authentication flow is handled by MAS (not by Synapse anymore), it doesn't make sense to extend the Synapse authentication flow with additional modules. Many bridges used to rely on shared-secret-auth for doing double-puppeting (impersonating other users), but most (at least the mautrix bridges) nowadays use [Appservice Double Puppet](./configuring-playbook-appservice-double-puppet.md) as a better alternative. Older/maintained bridges may still rely on shared-secret-auth, as do other services like [matrix-corporal](./configuring-playbook-matrix-corporal.md).

- ❌ Certain **tools like [Synapse Admin](./configuring-playbook-synapse-admin.md) do not have full compatibility with MAS yet**. Synapse Admin already supports OIDC auth, browsing users (which Synapse will internally fetch from MAS) and updating user avatars. However, editing users (passwords, etc.) now needs to happen directly against MAS using the [MAS Admin API](https://element-hq.github.io/matrix-authentication-service/api/index.html), which Synapse Admin cannot interact with yet. You may be interested in using [Element Admin](./configuring-playbook-element-admin.md) for these purposes.
- ✅ **[Ketesa](./configuring-playbook-ketesa.md) has full MAS integration**. Ketesa supports OIDC auth, user management, all session types (browser, OAuth2, compatibility), linked email addresses, upstream OAuth provider links, MAS policy data, and user creation through MAS. It is the recommended tool for managing homeservers running MAS.

- ❌ **Some services experience issues when authenticating via MAS**:

@@ -398,6 +398,8 @@ To perform a real migration, run the `matrix-authentication-service-mas-cli-syn2
just run-tags matrix-authentication-service-mas-cli-syn2mas
```

After `syn2mas` completes, Synapse will intentionally remain stopped to avoid new registrations or other authentication changes from being accepted before the migration is completed. Continue with the next steps in this guide before re-running the installation.

Having performed a `syn2mas` migration once, trying to do it again will report errors (e.g. "Error: The MAS database is not empty: rows found in at least `users`. Please drop and recreate the database, then try again.").

## Verify that Matrix Authentication Service is installed correctly


+ 20
- 57
docs/configuring-playbook-matrix-ldap-registration-proxy.md View File

@@ -1,69 +1,32 @@
<!--
SPDX-FileCopyrightText: 2022 - 2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2019 Edgars Voroboks
SPDX-FileCopyrightText: 2019 Eduardo Beltrame
SPDX-FileCopyrightText: 2019-2025 MDAD project contributors
SPDX-FileCopyrightText: 2019-2025 Slavi Pantaleev
SPDX-FileCopyrightText: 2020 Chris van Dijk
SPDX-FileCopyrightText: 2020 Tulir Asokan
SPDX-FileCopyrightText: 2020 jens quade
SPDX-FileCopyrightText: 2022 Dennis Ciba
SPDX-FileCopyrightText: 2022 Julian-Samuel Gebühr
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2022 Kim Brose
SPDX-FileCopyrightText: 2022 Travis Ralston
SPDX-FileCopyrightText: 2022 Vladimir Panteleev
SPDX-FileCopyrightText: 2022 Yan Minagawa
SPDX-FileCopyrightText: 2024-2026 Suguru Hirahara

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up matrix-ldap-registration-proxy (optional)
# Setting up matrix-ldap-registration-proxy (optional, removed)

The playbook can install and configure [matrix-ldap-registration-proxy](https://gitlab.com/activism.international/matrix_ldap_registration_proxy) for you.
🪦 The playbook used to be able to install and configure [matrix-ldap-registration-proxy](https://gitlab.com/activism.international/matrix_ldap_registration_proxy), but no longer includes this component, as it has become unavailable.

This proxy handles Matrix registration requests and forwards them to LDAP.
## Uninstalling the component manually

See the project's [documentation](https://gitlab.com/activism.international/matrix_ldap_registration_proxy/-/blob/main/README.md) to learn what it does and why it might be useful to you.
If you still have matrix-ldap-registration-proxy installed on your Matrix server, the playbook can no longer help you uninstall it and you will need to do it manually. To uninstall manually, run these commands on the server:

**Note**: This does support the full Matrix specification for registrations. It only provide a very coarse implementation of a basic password registration.

## Adjusting the playbook configuration

To enable the component, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file (adapt to your needs):

```yaml
matrix_ldap_registration_proxy_enabled: true

# LDAP credentials
matrix_ldap_registration_proxy_ldap_uri: YOUR_URI_HERE
matrix_ldap_registration_proxy_ldap_base_dn: YOUR_DN_HERE
matrix_ldap_registration_proxy_ldap_user: YOUR_USER_HERE
matrix_ldap_registration_proxy_ldap_password: YOUR_PASSWORD_HERE
```

If you already use the [synapse external password provider via LDAP](configuring-playbook-ldap-auth.md) (that is, you have `matrix_synapse_ext_password_provider_ldap_enabled: true` and other options in your configuration) you can use the following values as configuration:

```yaml
# Use the LDAP values specified for the synapse role to setup LDAP proxy
matrix_ldap_registration_proxy_ldap_uri: "{{ matrix_synapse_ext_password_provider_ldap_uri }}"
matrix_ldap_registration_proxy_ldap_base_dn: "{{ matrix_synapse_ext_password_provider_ldap_base }}"
matrix_ldap_registration_proxy_ldap_user: "{{ matrix_synapse_ext_password_provider_ldap_bind_dn }}"
matrix_ldap_registration_proxy_ldap_password: "{{ matrix_synapse_ext_password_provider_ldap_bind_password }}"

matrix_ldap_registration_proxy_systemd_wanted_services_list_custom:
- matrix-synapse.service
```

### Extending the configuration

There are some additional things you may wish to configure about the component.

Take a look at:

- `roles/custom/matrix-ldap-registration-proxy/defaults/main.yml` for some variables that you can customize via your `vars.yml` file

## Installing

After configuring the playbook, run it with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.
systemctl disable --now matrix-ldap-registration-proxy.service

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-ldap-registration-proxy`.
rm -rf /matrix/matrix_ldap_registration_proxy
```

+ 22
- 101
docs/configuring-playbook-matrix-registration.md View File

@@ -1,115 +1,36 @@
<!--
SPDX-FileCopyrightText: 2020 - 2022 Slavi Pantaleev
SPDX-FileCopyrightText: 2022 MDAD project contributors
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2019 Edgars Voroboks
SPDX-FileCopyrightText: 2019 Eduardo Beltrame
SPDX-FileCopyrightText: 2019-2025 MDAD project contributors
SPDX-FileCopyrightText: 2019-2025 Slavi Pantaleev
SPDX-FileCopyrightText: 2020 Chris van Dijk
SPDX-FileCopyrightText: 2020 Tulir Asokan
SPDX-FileCopyrightText: 2020 jens quade
SPDX-FileCopyrightText: 2022 Dennis Ciba
SPDX-FileCopyrightText: 2022 Kim Brose
SPDX-FileCopyrightText: 2022 Travis Ralston
SPDX-FileCopyrightText: 2022 Vladimir Panteleev
SPDX-FileCopyrightText: 2022 Yan Minagawa
SPDX-FileCopyrightText: 2024-2026 Suguru Hirahara

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up matrix-registration (optional)
# Setting up matrix-registration (optional, removed)

> [!WARNING]
> - This is a poorly maintained and buggy project. It's better to avoid using it.
> - This is not related to [matrix-registration-bot](configuring-playbook-bot-matrix-registration-bot.md)
> [!NOTE]
> This is not related to [matrix-registration-bot](configuring-playbook-bot-matrix-registration-bot.md).

The playbook can install and configure [matrix-registration](https://github.com/ZerataX/matrix-registration) for you. It is a simple python application to have a token based Matrix registration.
🪦 The playbook used to be able to install and configure [matrix-registration](https://github.com/ZerataX/matrix-registration), but no longer includes this component, as it has been unmaintained since November, 2025.

Use matrix-registration to **create unique registration links**, which people can use to register on your Matrix server. It allows certain people (these having a special link) to register a user account, **keeping your server's registration closed (private)**.
## Uninstalling the component manually

**matrix-registration** provides 2 things:
If you still have matrix-registration installed on your Matrix server, the playbook can no longer help you uninstall it and you will need to do it manually. To uninstall manually, run these commands on the server:

- **an API for creating registration tokens** (unique registration links). This API can be used via `curl` or via the playbook (see [Usage](#usage) below)

- **a user registration page**, where people can use these registration tokens. By default, exposed at `https://matrix.example.com/matrix-registration`

## Adjusting DNS records (optional)

By default, this playbook installs the matrix-registration on the `matrix.` subdomain, at the `/matrix-registration` path (https://matrix.example.com/matrix-registration). This makes it easy to install it, because it **doesn't require additional DNS records to be set up**. If that's okay, you can skip this section.

If you wish to adjust it, see the section [below](#adjusting-the-matrix-registration-url-optional) for details about DNS configuration.

## Adjusting the playbook configuration

To enable matrix-registration, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_registration_enabled: true

# Generate a strong secret here. You can create one with a command like `pwgen -s 64 1`.
matrix_registration_admin_secret: "ENTER_SOME_SECRET_HERE"
```

### Adjusting the matrix-registration URL (optional)

By tweaking the `matrix_registration_hostname` and `matrix_registration_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.

Example additional configuration for your `vars.yml` file:

```yaml
# Change the default hostname and path prefix
matrix_registration_hostname: registration.example.com
matrix_registration_path_prefix: /
```

If you've changed the default hostname, you may need to create a CNAME record for the matrix-registration domain (`registration.example.com`), which targets `matrix.example.com`.

When setting, replace `example.com` with your own.

### Extending the configuration

There are some additional things you may wish to configure about the component.

Take a look at:

- `roles/custom/matrix-registration/defaults/main.yml` for some variables that you can customize via your `vars.yml` file
- `roles/custom/matrix-registration/templates/config.yaml.j2` for the component's default configuration. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_registration_configuration_extension_yaml` variable

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records), run the playbook with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage
systemctl disable --now matrix-registration.service

**matrix-registration** gets exposed at `https://matrix.example.com/matrix-registration`
rm -rf /matrix/matrix-registration

It provides various [APIs](https://github.com/ZerataX/matrix-registration/wiki/api) — for creating registration tokens, listing tokens, disabling tokens, etc. To make use of all of its capabilities, consider using `curl`.

We make the most common APIs easy to use via the playbook (see below).

### Creating registration tokens

To **create a new user registration token (link)**, use this command:

```sh
ansible-playbook -i inventory/hosts setup.yml \
--tags=generate-matrix-registration-token \
--extra-vars="one_time=yes ex_date=2021-12-31"
/matrix/postgres/bin/cli-non-interactive -c 'DROP DATABASE matrix_registration;'
```

The above command creates and returns a **one-time use** token, which **expires** on the 31st of December 2021. Adjust the `one_time` and `ex_date` variables as you see fit.

Share the unique registration link (generated by the command above) with users to let them register on your Matrix server.

### Listing registration tokens

To **list the existing user registration tokens**, use this command:

```sh
ansible-playbook -i inventory/hosts setup.yml \
--tags=list-matrix-registration-tokens
```

The shortcut command with `just` program is also available: `just run-tags list-matrix-registration-tokens`

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-registration`.

+ 6
- 0
docs/configuring-playbook-matrix-rtc.md View File

@@ -38,6 +38,12 @@ matrix_rtc_enabled: true

In addition to the HTTP/HTTPS ports (which you've already exposed as per the [prerequisites](prerequisites.md) document), you'll also need to open ports required by [LiveKit Server](configuring-playbook-livekit-server.md) as described in its own [Adjusting firewall rules](configuring-playbook-livekit-server.md#adjusting-firewall-rules) section.

## Fronting the integrated reverse-proxy with another reverse-proxy

If you're [fronting the integrated reverse-proxy webserver with another reverse-proxy](configuring-playbook-own-webserver.md#fronting-the-integrated-reverse-proxy-webserver-with-another-reverse-proxy) (e.g. nginx), it needs to forward WebSocket traffic for [LiveKit Server](configuring-playbook-livekit-server.md) at the `/livekit-server/` path. Without that, Matrix RTC calls will not work.

See [`examples/reverse-proxies/nginx/matrix.conf`](../examples/reverse-proxies/nginx/matrix.conf) for an nginx example.

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records) and [adjusting firewall rules](#adjusting-firewall-rules), run the playbook with [playbook tags](playbook-tags.md) as below:


+ 3
- 0
docs/configuring-playbook-prometheus-grafana.md View File

@@ -183,6 +183,9 @@ Name | Description
`prometheus_postgres_exporter_container_labels_metrics_enabled`|Set this to `true` to expose the [Postgres exporter](#enable-metrics-and-graphs-for-postgres-optional) metrics on `https://matrix.example.com/metrics/postgres-exporter`.
`prometheus_nginxlog_exporter_enabled`|Set this to `true` to enable the [prometheus-nginxlog-exporter](#enable-metrics-and-graphs-for-nginx-logs-optional) (locally, on the container network).
`prometheus_nginxlog_exporter_container_labels_metrics_enabled`|Set this to `true` to expose the [prometheus-nginxlog-exporter](#enable-metrics-and-graphs-for-nginx-logs-optional) metrics on `https://matrix.example.com/metrics/nginxlog`.
`ntfy_metrics_listen_http_port`|Set this to a port number (e.g. `9090`) to make [ntfy](configuring-playbook-ntfy.md) serve its metrics (locally, on the container network) on that port.
`ntfy_container_labels_traefik_metrics_enabled`|Set this to `true` to expose the [ntfy](configuring-playbook-ntfy.md) metrics on `https://matrix.example.com/metrics/ntfy`.
`matrix_synapse_usage_exporter_metrics_proxying_enabled`|Set this to `true` to expose the [synapse-usage-exporter](configuring-playbook-synapse-usage-exporter.md) metrics on `https://matrix.example.com/metrics/synapse-usage-exporter`.

### Expose metrics of other services/roles



+ 0
- 93
docs/configuring-playbook-synapse-admin.md View File

@@ -1,93 +0,0 @@
<!--
SPDX-FileCopyrightText: 2020-2024 MDAD project contributors
SPDX-FileCopyrightText: 2020-2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2021 Aaron Raimist
SPDX-FileCopyrightText: 2023 Christian González
SPDX-FileCopyrightText: 2024 Nikita Chernyi
SPDX-FileCopyrightText: 2024 Uğur İLTER
SPDX-FileCopyrightText: 2024-2026 Suguru Hirahara

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Setting up Synapse Admin (optional)

The playbook can install and configure Synapse Admin for you.

Synapse Admin is a web UI tool you can use to **administrate users, rooms, media, etc. on your Matrix homeserver**. This playbook is configured to install [etkecc/synapse-admin](https://github.com/etkecc/synapse-admin), which is a [feature-rich](https://github.com/etkecc/synapse-admin#fork-differences) fork of [Awesome-Technologies/synapse-admin](https://github.com/Awesome-Technologies/synapse-admin).

>[!NOTE]
>
> - Synapse Admin does not work with other homeserver implementations than Synapse due to API's incompatibility.
> - The latest version of Synapse Admin is hosted by [etke.cc](https://etke.cc/) at [admin.etke.cc](https://admin.etke.cc/). If you only need this service occasionally and trust giving your admin credentials to a 3rd party Single Page Application, you can consider using it from there and avoiding the (small) overhead of self-hosting.
> - This playbook also supports an alternative management UI in the shape of [Element Admin](./configuring-playbook-element-admin.md). Please note that it's currently less feature-rich than Synapse Admin and requires [Matrix Authentication Service](./configuring-playbook-matrix-authentication-service.md).

## Adjusting DNS records (optional)

By default, this playbook installs Synapse Admin on the `matrix.` subdomain, at the `/synapse-admin` path (https://matrix.example.com/synapse-admin). This makes it easy to install it, because it **doesn't require additional DNS records to be set up**. If that's okay, you can skip this section.

If you wish to adjust it, see the section [below](#adjusting-the-synapse-admin-url-optional) for details about DNS configuration.

## Adjusting the playbook configuration

To enable Synapse Admin, add the following configuration to your `inventory/host_vars/matrix.example.com/vars.yml` file:

```yaml
matrix_synapse_admin_enabled: true
```

**Note**: Synapse Admin requires Synapse's [Admin APIs](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/index.html) to function. Access to them is restricted with a valid access token, so exposing them publicly should not be a real security concern. Still, for additional security, we normally leave them unexposed, following [official Synapse reverse-proxying recommendations](https://element-hq.github.io/synapse/latest/reverse_proxy.html#synapse-administration-endpoints). Because Synapse Admin needs these APIs to function, when installing Synapse Admin, the playbook **automatically** exposes the Synapse Admin API publicly for you. Depending on the homeserver implementation you're using (Synapse, Dendrite), this is equivalent to:

- for [Synapse](./configuring-playbook-synapse.md) (our default homeserver implementation): `matrix_synapse_container_labels_public_client_synapse_admin_api_enabled: true`
- for [Dendrite](./configuring-playbook-dendrite.md): `matrix_dendrite_container_labels_public_client_synapse_admin_api_enabled: true`

By default, synapse-admin installation will be [restricted to only work with one homeserver](https://github.com/etkecc/synapse-admin/blob/e21e44362c879ac41f47c580b04210842b6ff3d7/README.md#restricting-available-homeserver) — the one managed by the playbook. To adjust these restrictions, tweak the `matrix_synapse_admin_config_restrictBaseUrl` variable.

### Adjusting the Synapse Admin URL (optional)

By tweaking the `matrix_synapse_admin_hostname` and `matrix_synapse_admin_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.

Example additional configuration for your `vars.yml` file:

```yaml
# Change the default hostname and path prefix
matrix_synapse_admin_hostname: admin.example.com
matrix_synapse_admin_path_prefix: /
```

If you've changed the default hostname, you may need to create a CNAME record for the Synapse Admin domain (`admin.example.com`), which targets `matrix.example.com`.

When setting, replace `example.com` with your own.

### Extending the configuration

There are some additional things you may wish to configure about the component.

Take a look at:

- `roles/custom/matrix-synapse-admin/defaults/main.yml` for some variables that you can customize via your `vars.yml` file. You can override settings (even those that don't have dedicated playbook variables) using the `matrix_synapse_admin_configuration_extension_json` variable

## Installing

After configuring the playbook and potentially [adjusting your DNS records](#adjusting-dns-records), run the playbook with [playbook tags](playbook-tags.md) as below:

<!-- NOTE: let this conservative command run (instead of install-all) to make it clear that failure of the command means something is clearly broken. -->
```sh
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```

The shortcut commands with the [`just` program](just.md) are also available: `just install-all` or `just setup-all`

`just install-all` is useful for maintaining your setup quickly ([2x-5x faster](../CHANGELOG.md#2x-5x-performance-improvements-in-playbook-runtime) than `just setup-all`) when its components remain unchanged. If you adjust your `vars.yml` to remove other components, you'd need to run `just setup-all`, or these components will still remain installed. Note these shortcuts run the `ensure-matrix-users-created` tag too.

## Usage

After installation, Synapse Admin will be accessible at: `https://matrix.example.com/synapse-admin/`

To use Synapse Admin, you need to have [registered at least one administrator account](registering-users.md) on your server.

## Troubleshooting

As with all other services, you can find the logs in [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html) by logging in to the server with SSH and running `journalctl -fu matrix-synapse-admin`.

If you have questions, you can join this community room and feel free to ask: [#synapse-admin:etke.cc](https://matrix.to/#/#synapse-admin:etke.cc)

+ 24
- 2
docs/configuring-playbook-synapse-usage-exporter.md View File

@@ -1,7 +1,7 @@
<!--
SPDX-FileCopyrightText: 2024 - 2025 Suguru Hirahara
SPDX-FileCopyrightText: 2024 Michael Hollister
SPDX-FileCopyrightText: 2024 Slavi Pantaleev
SPDX-FileCopyrightText: 2024 - 2026 Slavi Pantaleev

SPDX-License-Identifier: AGPL-3.0-or-later
-->
@@ -38,13 +38,35 @@ To enable synapse-usage-exporter, add the following configuration to your `inven
```yaml
matrix_synapse_usage_exporter_enabled: true

# (Optional) Expose endpoint if you want to collect statistics from outside (from other homeservers).
# (Optional) Expose the usage-stats ingestion endpoint if you want to collect statistics from outside (from other homeservers).
# If enabled, synapse-usage-exporter will be exposed publicly at `matrix.example.com/report-usage-stats/push`.
# When collecting usage statistics for Synapse running on the same host, you don't need to enable this.
# You can adjust the hostname and path via `matrix_synapse_usage_exporter_hostname` and `matrix_synapse_usage_exporter_path_prefix`.
# matrix_synapse_usage_exporter_proxying_enabled: true
```

**Note**: `matrix_synapse_usage_exporter_proxying_enabled` only exposes the endpoint that Synapse pushes usage statistics **to** (`/report-usage-stats/push`). Despite its generic name, it has nothing to do with the metrics endpoint that Prometheus reads **from**. See [below](#collecting-metrics-to-an-external-prometheus-server) for exposing metrics.

### Collecting metrics to an external Prometheus server

Metrics are always served on the container network, so the [integrated Prometheus](./configuring-playbook-prometheus-grafana.md) (`prometheus_enabled: true`) scrapes them without any additional configuration.

To collect them with an **external Prometheus server**, you need to expose them publicly. You can do so by enabling metrics exposure for all services (`matrix_metrics_exposure_enabled: true`), or just for this service:

```yaml
# Expose the metrics on https://matrix.example.com/metrics/synapse-usage-exporter
matrix_synapse_usage_exporter_metrics_proxying_enabled: true

# Uncomment to password-protect the metrics for synapse-usage-exporter.
# matrix_synapse_usage_exporter_container_labels_traefik_metrics_middleware_basic_auth_enabled: true

# Uncomment and set this part to the Basic Authentication credentials (raw `htpasswd` file content) used to protect the endpoint.
# See https://doc.traefik.io/traefik/middlewares/http/basicauth/#users
# matrix_synapse_usage_exporter_container_labels_traefik_metrics_middleware_basic_auth_users: ''
```

Refer to [this section](./configuring-playbook-prometheus-grafana.md#collecting-metrics-to-an-external-prometheus-server) of the Prometheus and Grafana documentation for more details.

### Adjusting the synapse-usage-exporter URL (optional)

By tweaking the `matrix_synapse_usage_exporter_hostname` and `matrix_synapse_usage_exporter_path_prefix` variables, you can easily make the service available at a **different hostname and/or path** than the default one.


+ 3
- 3
docs/configuring-playbook-synapse.md View File

@@ -196,11 +196,11 @@ The shortcut commands with the [`just` program](just.md) are also available: `ju

## Usage

### Synapse Admin
### Ketesa

With [Synapse Admin](configuring-playbook-synapse-admin.md), certain Synapse administration tasks (managing users and rooms, etc.) can be performed via a web user-interace.
[Ketesa](configuring-playbook-ketesa.md) is a fully-featured web UI for administrating your homeserver — managing users, rooms, media, sessions, and more.

The playbook can install and configure Synapse Admin for you. For details about it, see [this page](configuring-playbook-synapse-admin.md).
The playbook can install and configure Ketesa for you. For details about it, see [this page](configuring-playbook-ketesa.md).

### Monitoring Synapse Metrics with Prometheus and Grafana



+ 179
- 0
docs/configuring-playbook-synology.md View File

@@ -0,0 +1,179 @@
<!--
SPDX-FileCopyrightText: 2026 Chiu Ki Sit

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Configuring Synology DSM

This document is a guide for preparing Synology DSM for the installation of the [Matrix Docker Ansible Deploy](https://github.com/spantaleev/matrix-docker-ansible-deploy) project.

> **Note:** Synology DSM is a community-supported platform. It is not officially tested or maintained by the project maintainers. Use at your own discretion.

**Intended audience:** Users already familiar with DSM, SSH, and this Ansible project.

## Assumptions

- DSM version 7 or higher
- `Volume1` is used as the default Docker storage location
- You are using DSM's built-in reverse proxy for handling HTTPS

## How Synology Support Works

The playbook automatically detects Synology DSM by checking for `/etc/synoinfo.conf`. When detected, it:

- Uses `synouser` and `synogroup` (DSM-native tools) instead of standard Linux user management
- Constrains the Python `requests` package to a version compatible with the Docker SDK
- Ensures `/volume1` has shared mount propagation so container bind mounts work correctly
- Deploys a `matrix-synology-boot-fix` service that runs on every boot after Docker is ready

You can override auto-detection by setting `matrix_base_host_is_synology: true` or `false` in your `vars.yml`.

### Matrix Service Account

The playbook creates a `matrix` system account using Synology's `synouser` tool. The account is secured as follows:

- **Expired** (`expired=1`) — the account cannot be used to log in to DSM or any application

You must set a password for this account via `matrix_synology_user_password` in your `vars.yml` (see [vars.yml Configuration](#varsyml-configuration)). The password cannot be used to log in because the account is expired, but a non-empty password is required as an additional security layer.

> If you pre-create the `matrix` user manually before running the playbook, the playbook will not modify the existing account's settings — you are responsible for securing it.

### Boot-fix Service

Synology DSM has two boot-time quirks that the boot-fix service addresses automatically:

1. **`/volume1` shared mount propagation**

Docker requires `/volume1` to be mounted as shared (`mount --make-shared /volume1`) for container bind mounts with `bind-propagation=slave` to work correctly (used by matrix-synapse for its media store). On Synology, this cannot be inserted into the systemd chain before Container Manager starts — doing so causes Container Manager to detect a broken dependency and prompt for repair on every boot. The playbook applies this during setup, and the boot-fix service re-applies it on every subsequent reboot, safely outside Container Manager's dependency chain.

2. **Skipped services at boot**

Synology's systemd drops services with multi-level dependency chains from the boot activation queue (e.g. `matrix-traefik → matrix-container-socket-proxy → docker`). These services show as `inactive` or `failed` after reboot even though they are enabled. The boot-fix service scans for any enabled `matrix-*.service` in either state and starts them automatically.

> **If you previously configured a Task Scheduler entry** (`Control Panel > Task Scheduler`) to run `mount --make-shared /volume1` at boot-up, you can remove it — the boot-fix service now handles this.

## Synology GUI Preparation

1. **Enable SSH**
- `Control Panel` > `Terminal & SNMP` > `Enable SSH service`

2. **Enable SFTP**
- `Control Panel` > `File Service` > `FTP` > `Enable SFTP service` with default port

3. **Enable User Home Directory**
- `Control Panel` > `User & Group` > `Advanced` > `Enable user home service`

4. **Install Container Manager**
- Install from `Package Center`

5. **Configure Reverse Proxy**
- `Control Panel` > `Login Portal` > `Advanced` > `Reverse Proxy`
- Create entries for each service you enable (e.g. Matrix, Element, admin page)
- Example entry:
- Source: `HTTPS` / `matrix.example.com` / port `443`
- Destination: `HTTP` / `localhost` / port `81`

## SSH Preparation

### (Optional but Recommended) Enable SSH Key Authentication

Configure key-based SSH login to avoid password prompts during Ansible runs.

### Set Up the Ansible Environment

Create a project folder and Python virtual environment on the DSM host:

```shell
mkdir ~/path/to/your/project/folder
cd ~/path/to/your/project/folder

python3 -m venv ./myenv
# (optional) activate python virtual environment
# source ./myenv/bin/activate
```

## Inventory Configuration

In your `inventory/hosts` file, set the Python interpreter to your virtual environment:

```ini
# SSH key authentication with empty passphrase example
matrix.example.com ansible_host=<your-dsm-ip> ansible_ssh_user=<dsm-ssh-user> become=true become_user=root ansible_python_interpreter=/volume1/homes/path/to/your/project/folder/myenv/bin/python ansible_sudo_pass='your-password'
```

## vars.yml Configuration

Add the following Synology-specific variables to your `vars.yml`:

```yaml
# Synology-specific settings

# Controls Synology DSM-specific handling. `null` means autodetect (via /etc/synoinfo.conf).
# Set to `true`/`false` to force.
# matrix_base_host_is_synology: true

# Password for the Matrix service account created by the playbook.
# The account is created as expired so this password cannot be used to log in.
matrix_synology_user_password: "your-strong-password"

# User and group that will be created automatically by the playbook
matrix_user_name: "matrix"
matrix_group_name: "matrix"

# Data path on your Synology volume
matrix_base_data_path: "/volume1/docker/matrix"

# Use Synology Container Manager's Docker daemon instead of installing Docker
matrix_playbook_docker_installation_enabled: false
devture_systemd_docker_base_host_command_docker: "/var/packages/ContainerManager/target/usr/bin/docker"
devture_systemd_docker_base_docker_service_name: "pkg-ContainerManager-dockerd.service"

# Use Synology's NTP service
devture_timesync_ntpd_service: "chronyd"

# Reverse proxy settings — use HTTPS at the DSM reverse proxy level
matrix_playbook_ssl_enabled: true
traefik_config_entrypoint_web_secure_enabled: false

# Bind to localhost only — DSM reverse proxy handles public traffic
traefik_container_web_host_bind_port: '127.0.0.1:81'
matrix_playbook_public_matrix_federation_api_traefik_entrypoint_host_bind_port: '127.0.0.1:8449'

# Trust X-Forwarded-* headers from the local reverse proxy
traefik_config_entrypoint_web_forwardedHeaders_insecure: true

matrix_playbook_public_matrix_federation_api_traefik_entrypoint_config_custom:
forwardedHeaders:
insecure: true
```

## Running the Playbook

```shell
# Full setup
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all

# start
ansible-playbook -i inventory/hosts setup.yml --tags=install-all,start

# Stop all services
ansible-playbook -i inventory/hosts setup.yml --tags=stop

# Apply config changes (always include start to restart running containers)
ansible-playbook -i inventory/hosts setup.yml --tags=stop,setup-all,start
```

> **Important:** Always include `stop` before `setup-all,start` when changing configuration. Running `setup-all` alone does not restart already-running containers.

## Creating Matrix Users

After the services are running, create your first Matrix user:

```shell
# option 1:
sudo docker exec -it matrix-synapse register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml -u your_username -p your_password

# option 2:
ansible-playbook -i inventory/hosts setup.yml --extra-vars='username=your_username password=your_password admin=yes|no' --tags=register-user
```

+ 18
- 3
docs/configuring-playbook-traefik.md View File

@@ -25,16 +25,31 @@ traefik_config_accessLog_enabled: false

### Enable Traefik Dashboard

To enable a Traefik [Dashboard](https://doc.traefik.io/traefik/operations/dashboard/) UI at `https://matrix.example.com/dashboard/` (note the trailing `/`), add the following configuration to your `vars.yml` file:
To enable the Traefik [Dashboard](https://doc.traefik.io/traefik/operations/dashboard/) UI at `https://matrix.example.com/dashboard/` (note the trailing `/`), add the following configuration to your `vars.yml` file:

```yaml
traefik_dashboard_enabled: true
traefik_dashboard_hostname: "{{ matrix_server_fqn_matrix }}"
traefik_dashboard_basicauth_enabled: true
traefik_dashboard_basicauth_user: YOUR_USERNAME_HERE
traefik_dashboard_basicauth_password: YOUR_PASSWORD_HERE
traefik_dashboard_basicauth_htpasswd: "YOUR_USERNAME_HERE:$apr1$..."
```

Choose a username and password for the dashboard, then generate the corresponding `htpasswd` entry with:

```sh
htpasswd -nb YOUR_USERNAME_HERE YOUR_PASSWORD_HERE
```

The command outputs the exact value to use for `traefik_dashboard_basicauth_htpasswd` — your username, a colon, and a hash of your chosen password:

```text
YOUR_USERNAME_HERE:$apr1$...
```

Copy the full output line into `traefik_dashboard_basicauth_htpasswd`. After deploying, log in to the dashboard using the same username and password that you chose earlier.

The role also supports the legacy `traefik_dashboard_basicauth_user` / `traefik_dashboard_basicauth_password` convenience variables, but that path depends on the `passlib` Python library on the Ansible controller, may be affected by passlib/bcrypt compatibility issues, and generates non-deterministic hashes which can lead to unnecessary changes.

> [!WARNING]
> Enabling the dashboard on a hostname you use for something else (like `matrix_server_fqn_matrix` in the configuration above) may cause conflicts. Enabling the Traefik Dashboard makes Traefik capture all `/dashboard` and `/api` requests and forward them to itself. If any of the services hosted on the same hostname requires any of these 2 URL prefixes, you will experience problems. So far, we're not aware of any playbook services which occupy these endpoints and are likely to cause conflicts.



+ 269
- 0
docs/configuring-playbook-tuwunel.md View File

@@ -0,0 +1,269 @@
<!--
SPDX-FileCopyrightText: 2026 MDAD project contributors
SPDX-FileCopyrightText: 2026 Jason Volk

SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Configuring Tuwunel (optional)

The playbook can install and configure the [Tuwunel](https://matrix-construct.github.io/tuwunel/) Matrix homeserver for you.

Tuwunel is a featureful homeserver written entirely in Rust, intended as a scalable, low-cost, enterprise-ready alternative to Synapse that fully implements the [Matrix specification](https://spec.matrix.org/latest/) for all but the most niche uses. It is the official successor to [conduwuit](configuring-playbook-conduwuit.md), is now sponsored by the government of Switzerland 🇨🇭 (where it is currently deployed for citizens), and is used by a number of organisations with a vested interest in its continued development. See the project's [documentation](https://matrix-construct.github.io/tuwunel/) for further background.

By default, the playbook installs [Synapse](https://github.com/element-hq/synapse) as it's the only full-featured Matrix server at the moment. If that's okay, you can skip this document.

> [!WARNING]
> - **You can't switch an existing Matrix server's implementation** (e.g. Synapse → Tuwunel). Proceed below only if you're OK with starting over, or you're dealing with a server on a new domain name which hasn't participated in the Matrix federation yet. The one exception is migrating from conduwuit; see [Migrating from conduwuit](#migrating-from-conduwuit).
> - **Homeserver implementations other than Synapse may not be fully functional** with every part of this playbook. Make yourself familiar with the trade-offs before proceeding.

## Adjusting the playbook configuration

To use Tuwunel, set the following on `inventory/host_vars/matrix.example.com/vars.yml`:

```yaml
matrix_homeserver_implementation: tuwunel

# Open the registration endpoint long enough to create your first user.
# After signing up, set this back to false.
matrix_tuwunel_config_allow_registration: true

# A registration token to protect the endpoint from abuse.
# Generate one with `pwgen -s 64 1` or similar.
matrix_tuwunel_config_registration_token: ''
```

The first user account that registers becomes a server admin and is automatically invited to the admin room. See [Creating the first user account](#creating-the-first-user-account) below for the bootstrap procedure.

## Wiring done for you

When `matrix_homeserver_implementation: tuwunel` is set, the playbook automatically integrates Tuwunel with the rest of your stack:

- **Federation.** Toggled by `matrix_homeserver_federation_enabled`. The federation virtual host (port 8448 in the default setup) is wired up via Traefik labels.
- **Well-known.** `matrix_tuwunel_config_well_known_client` is set to your public homeserver URL whenever SSL is enabled. Matrix clients use this for delegated-domain server discovery; identity-provider entries below can also omit their `callback_url`, since Tuwunel derives `<well-known>/_matrix/client/unstable/login/sso/callback/<client_id>` automatically.
- **Element Call / MatrixRTC.** When the [LiveKit JWT service](configuring-playbook-matrix-rtc.md) is enabled, Tuwunel publishes its public URL through `.well-known/matrix/client` per [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143).
- **Legacy calls (TURN).** When [Coturn](configuring-playbook-turn.md) is enabled, its URIs and shared secret (or username/password, depending on `coturn_authentication_method`) are wired automatically.

## Extending the configuration

Tuwunel exposes a large configuration surface. The role surfaces commonly used options as Ansible variables under `matrix_tuwunel_config_*`. See [`roles/custom/matrix-tuwunel/defaults/main.yml`](../roles/custom/matrix-tuwunel/defaults/main.yml) for the complete list, and [`roles/custom/matrix-tuwunel/templates/tuwunel.toml.j2`](../roles/custom/matrix-tuwunel/templates/tuwunel.toml.j2) for the rendered configuration.

For options that aren't surfaced as a dedicated variable, [environment variables](https://matrix-construct.github.io/tuwunel/configuration.html#environment-variables) are the recommended override mechanism. They take priority over the rendered TOML, are scoped to the running container, and require no template patching:

```yaml
matrix_tuwunel_environment_variables_extension: |
TUWUNEL_REQUEST_TIMEOUT=60
TUWUNEL_DNS_CACHE_SIZE=131072
```

Keys nested under a TOML section use `__` (double underscore) to descend, e.g. `TUWUNEL_WELL_KNOWN__SERVER`. User-named sections become path segments too: `TUWUNEL_STORAGE_PROVIDER__ARCHIVE__S3__URL` overrides the `url` field of the `archive` storage provider in the example below.

If you need wholesale control of the configuration file, copy [`roles/custom/matrix-tuwunel/templates/tuwunel.toml.j2`](../roles/custom/matrix-tuwunel/templates/tuwunel.toml.j2) into your inventory and point `matrix_tuwunel_template_tuwunel_config` at your copy.

The container image published as `:latest` is built with `io_uring`, `jemalloc`, LDAP, blurhashing, URL preview, sentry telemetry, and zstd compression all enabled, so most opt-in features are simply a configuration toggle away.

### Identity providers (OAuth2 / OIDC)

Configure one or more `[[global.identity_provider]]` entries via a list. Each entry maps directly to Tuwunel's [identity-provider fields](https://matrix-construct.github.io/tuwunel/authentication/providers.html); only the fields you set are emitted. GitHub, GitLab, and Google have built-in `issuer_url` defaults so a `client_id` plus `client_secret` is enough; for any other `brand` (Apple, Facebook, Keycloak, MAS, Twitter, etc.) you must supply `issuer_url` explicitly:

```yaml
matrix_tuwunel_config_identity_providers:
- brand: keycloak
client_id: matrix
client_secret: '<provider secret>'
issuer_url: https://sso.example.com/realms/matrix
callback_url: https://matrix.example.com/_matrix/client/unstable/login/sso/callback/matrix
trusted: true
- brand: github
client_id: '<github oauth app id>'
client_secret: '<github oauth app secret>'
```

Self-hosted providers must supply both `client_id` and `issuer_url`. Set `trusted: true` only on providers you operate yourself; trusting a public provider (GitHub, Google, etc.) is an account-takeover risk.

### LDAP

Tuwunel can authenticate `m.login.password` requests against an LDAP directory and, in search-then-bind mode, keep admin status in sync with directory membership. The shipped image already includes the `ldap` build feature.

```yaml
matrix_tuwunel_config_ldap_enabled: true
matrix_tuwunel_config_ldap_uri: ldaps://ldap.example.com:636
matrix_tuwunel_config_ldap_base_dn: ou=users,dc=example,dc=org
matrix_tuwunel_config_ldap_bind_dn: cn=ldap-reader,dc=example,dc=org
matrix_tuwunel_config_ldap_bind_password_file: /etc/tuwunel/ldap.pw
matrix_tuwunel_config_ldap_filter: '(&(objectClass=person)(memberOf=cn=matrix,ou=groups,dc=example,dc=org))'
```

> [!NOTE]
> `bind_password_file` is read **inside the container**. The role bind-mounts `/matrix/tuwunel/config` to `/etc/tuwunel` (read-only) and `/matrix/tuwunel/data` to `/var/lib/tuwunel`. To make the file available at the path above, drop it on the host at `/matrix/tuwunel/config/ldap.pw` (owned by `matrix:matrix`) before running the playbook; the role does not template secret files for you.

For direct-bind, anonymous-search, and admin-sync details, see [LDAP authentication](https://matrix-construct.github.io/tuwunel/authentication/ldap.html).

### JWT login

Tuwunel can accept signed JSON Web Tokens both as a login flow and as a User-Interactive Authentication step:

```yaml
matrix_tuwunel_config_jwt_enabled: true
matrix_tuwunel_config_jwt_key: '<shared secret>'
matrix_tuwunel_config_jwt_format: HMAC # one of HMAC, B64HMAC, ECDSA, EDDSA
matrix_tuwunel_config_jwt_algorithm: HS256
matrix_tuwunel_config_jwt_audience: ['matrix']
matrix_tuwunel_config_jwt_issuer: ['https://issuer.example.com']
```

The defaults match Synapse's `experimental_features.jwt_config` semantics, so a key + algorithm port should authenticate the same set of tokens. See [Enterprise JWT](https://matrix-construct.github.io/tuwunel/authentication/jwt.html) for the full reference, including the asymmetric (ECDSA / EdDSA) formats and the operator-controlled UIAA override flow.

### Media storage providers

Each entry becomes a `[global.storage_provider.<id>.<kind>]` block. `kind` is `local` or `s3`; the remaining keys map directly to the fields documented in [Storage providers](https://matrix-construct.github.io/tuwunel/media/storage.html):

```yaml
matrix_tuwunel_config_storage_providers:
- id: primary
kind: local
base_path: /var/lib/tuwunel/media

- id: archive
kind: s3
url: s3://my-bucket/media
region: us-east-1
key: AKIA...
secret: '<aws secret>'
multipart_threshold: 100 MiB
```

The S3 backend ships with native multipart upload, so no goofys/rclone sidecar is required. MinIO, Cloudflare R2, and DigitalOcean Spaces all work; set `endpoint` and `use_vhost_request: false` as appropriate.

> [!NOTE]
> Local provider paths must live under `/var/lib/tuwunel` (the container's data mount, persisted on the host at `/matrix/tuwunel/data`), or you must mount the target directory into the container yourself via `matrix_tuwunel_container_extra_arguments`. The container otherwise runs read-only.

### RocksDB and cache tuning

Tuwunel embeds RocksDB. The defaults (`rocksdb_compression_algo: zstd`) suit most deployments. For high-throughput servers you may want to enable direct I/O, raise parallelism, and configure a backup path:

```yaml
matrix_tuwunel_config_rocksdb_direct_io: true
matrix_tuwunel_config_rocksdb_parallelism_threads: 8
matrix_tuwunel_config_database_backup_path: /var/lib/tuwunel/backups
```

`matrix_tuwunel_config_cache_capacity_modifier` is left empty by default, so Tuwunel picks a value (`1.0` since v1.7.0, with rebalanced per-cache sizes that already raise memory use). Set it to `2.0` only on small hosts with four or fewer cores; on larger machines the default is recommended.

If you run on ZFS, the [Tuwunel maintenance guide](https://matrix-construct.github.io/tuwunel/maintenance.html#zfs) lists the dataset properties (`recordsize`, `primarycache`, `compression`, `atime`, `logbias`) and config flags (`rocksdb_direct_io`, `rocksdb_allow_fallocate`) you need to adjust to avoid severe write amplification.

To enable Sentry crash reporting, set `matrix_tuwunel_config_sentry_enabled: true`.

### Federation gating

Tuwunel accepts regular-expression patterns at every level of remote-server filtering:

```yaml
matrix_tuwunel_config_forbidden_remote_server_names:
- 'bad\.example\.com$'
matrix_tuwunel_config_forbidden_remote_room_directory_server_names:
- 'spam\.example\.com$'
matrix_tuwunel_config_prevent_media_downloads_from:
- 'heavy\.example\.com$'
```

Tuwunel additionally implements [MSC4284 policy servers](https://github.com/matrix-org/matrix-spec-proposals/pull/4284) for room-level federation gating. The policy itself lives in room state, but enforcement is opt-in at the server level:

```yaml
matrix_tuwunel_config_enable_policy_servers: true
matrix_tuwunel_config_policy_server_request_timeout: 5
```

When enabled, rooms with a valid `m.room.policy` state event have outgoing events signed by the configured policy server before federation. Transient network or timeout failures fail open (with a warn log), so a policy-server outage will not silently take the room offline.

### Default room version

The role sets `default_room_version: '12'`, so newly created rooms default to Matrix [room version 12](https://github.com/matrix-org/matrix-spec-proposals/pull/4289) ("Hydra"). Override `matrix_tuwunel_config_default_room_version` if you need an earlier version for client compatibility.

### The `/_tuwunel` API path

Besides `/_matrix`, Tuwunel serves its own first-party routes under `/_tuwunel`. This namespace carries ad-hoc endpoints such as `/_tuwunel/server_version` and `/_tuwunel/local_user_count`, and the [native OpenID Connect provider](https://matrix-construct.github.io/tuwunel/authentication/oidc-server.html) endpoints (`/_tuwunel/oidc/...`) that clients use when Tuwunel handles OIDC login itself, rather than delegating to an upstream provider as described above. The role routes `/_tuwunel` on the public entrypoint by default so these features work out of the box.

To keep this namespace off the public entrypoint and expose it only on the internal one, set:

```yaml
matrix_tuwunel_container_labels_public_tuwunel_api_enabled: false
matrix_tuwunel_container_labels_internal_tuwunel_api_enabled: true
```

### Exposing the Administration API

Tuwunel serves a Synapse-compatible Administration API under the `/_synapse/admin` path, so administration dashboards (such as synapse-admin and ketesa) and moderation bots (such as Draupnir and Meowlnir) work against it. The served endpoints are listed on the [Tuwunel Synapse Admin API page](https://matrix-construct.github.io/tuwunel/development/compliance/synapse-admin.html).

The API is not routed through the reverse proxy by default. Every endpoint requires an administrator access token, but you may still prefer to keep it off the public entrypoint. To reach it only from trusted networks, expose it on the internal Traefik entrypoint:

```yaml
matrix_tuwunel_container_labels_internal_client_synapse_admin_api_enabled: true
```

To expose it publicly instead (for example, when a dashboard runs in the browser), set:

```yaml
matrix_tuwunel_container_labels_public_client_synapse_admin_api_enabled: true
```

## Creating the first user account

Unlike Synapse and Dendrite, Tuwunel does not register users from the command line or via the playbook. On first startup it logs a one-time-use registration token to its journal:

```sh
# Adjust the duration if necessary or remove the --since argument.
journalctl -u matrix-tuwunel.service --since="10 minutes ago"
```

Use the token to create your first account from any client that supports token-gated registration (e.g. [Element Web](configuring-playbook-client-element-web.md)). The account is auto-promoted to admin and invited to the admin room together with the `@conduit:<server_name>` server bot. The bot keeps the legacy `conduit` localpart due to the project's lineage from Conduit.

## Configuring bridges and appservices

The playbook does not auto-register appservices for Tuwunel. After your bridge has produced its `registration.yaml` (e.g. `/matrix/mautrix-signal/bridge/registration.yaml`), register it manually by sending the contents to the admin room, prefixed with `!admin appservices register` and wrapped in a fenced code block:

!admin appservices register
```
id: signal
url: http://matrix-mautrix-signal:29328
as_token: <token>
hs_token: <token>
sender_localpart: _bot_signalbot
rate_limited: false
namespaces:
users:
- exclusive: true
regex: '^@signal_.+:example\.org$'
- exclusive: true
regex: '^@signalbot:example\.org$'
aliases:
- exclusive: true
regex: '^#signal_.+:example\.org$'
```

Registrations stored this way are persisted in the database and survive restarts. Re-running the command with the same `id` replaces the existing entry. See [Application services](https://matrix-construct.github.io/tuwunel/appservices.html) for the full reference and admin commands.

## Migrating from conduwuit

Tuwunel is a "binary swap" for conduwuit; it reads conduwuit's RocksDB layout directly, so migration is a data move, not an export/import.

1. Set `matrix_homeserver_implementation: tuwunel` on `vars.yml` and remove any `matrix_conduwuit_*` overrides.
2. Run a full installation so that the new service is created and the old one removed (e.g. `just setup-all`).
3. Run `just run-tags tuwunel-migrate-from-conduwuit`.

The migration stops `matrix-conduwuit.service`, copies `/matrix/conduwuit` into `/matrix/tuwunel`, renames the config file, and starts `matrix-tuwunel.service`. The freshly generated tuwunel data directory is preserved alongside as `/matrix/tuwunel_old` until you remove it manually.

> [!CAUTION]
> Migrating from any other Conduit derivative (Conduit itself, Continuwuity, or any other fork) is **not supported** and will corrupt your database. All Conduit forks share the same linear database version with no awareness of each other; switching between them produces unrecoverable damage. See the [upstream migration table](https://matrix-construct.github.io/tuwunel/#migrating-to-tuwunel).

## Troubleshooting

As with all other services, the logs are available via [systemd-journald](https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html):

```sh
journalctl -fu matrix-tuwunel
```

Logging verbosity is controlled by `matrix_tuwunel_config_log` in [`tracing-subscriber` env-filter syntax](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html). The default (`info,state_res=warn`) is reasonable for production; for debugging, try `debug` or scope it tighter, e.g. `info,tuwunel_service::sending=debug`.

For RocksDB-level issues, online backups, and offline backup procedures, see the [Tuwunel maintenance guide](https://matrix-construct.github.io/tuwunel/maintenance.html). For protocol-compliance state across MSCs, the spec, and Complement, the project's [compliance dashboard](https://matrix-construct.github.io/tuwunel/development/compliance.html) is the authoritative tracker.

+ 28
- 12
docs/configuring-playbook.md View File

@@ -53,6 +53,8 @@ For a more custom setup, see the [Other configuration options](#other-configurat

- [Configuring continuwuity](configuring-playbook-continuwuity.md), if you've switched to the [continuwuity](https://continuwuity.org) homeserver implementation

- [Configuring Tuwunel](configuring-playbook-tuwunel.md), if you've switched to the [Tuwunel](https://matrix-construct.github.io/tuwunel/) homeserver implementation

- [Configuring Dendrite](configuring-playbook-dendrite.md), if you've switched to the [Dendrite](https://matrix-org.github.io/dendrite) homeserver implementation

- Server components:
@@ -87,12 +89,14 @@ Web clients for Matrix that you can host on your own domains.

- [Setting up Cinny](configuring-playbook-client-cinny.md), if you've enabled [Cinny](https://github.com/ajbura/cinny), a web client focusing primarily on simple, elegant and secure interface

- [Setting up Sable](configuring-playbook-client-sable.md), if you've enabled [Sable](https://github.com/7w1/sable), a web client focusing primarily on simple, elegant and secure interface
- [Setting up Sable](configuring-playbook-client-sable.md), if you've enabled [Sable](https://github.com/SableClient/Sable), a web client focusing primarily on simple, elegant and secure interface

- [Setting up SchildiChat Web](configuring-playbook-client-schildichat-web.md), if you've enabled [SchildiChat Web](https://schildi.chat/), a web client based on [Element Web](https://element.io/) with some extras and tweaks

- [Setting up FluffyChat Web](configuring-playbook-client-fluffychat-web.md), if you've enabled [FluffyChat Web](https://github.com/krille-chan/fluffychat), a cute cross-platform messenger (web, iOS, Android) for Matrix written in [Flutter](https://flutter.dev/)

- [Setting up Commet](configuring-playbook-client-commet.md), if you've enabled [Commet](https://github.com/commetchat/commet), a Matrix web client


### Authentication and user-related

@@ -102,9 +106,7 @@ Extend and modify how users are authenticated on your homeserver.

- [Setting up Appservice Double Puppet](configuring-playbook-appservice-double-puppet.md)

- [Setting up Synapse Admin](configuring-playbook-synapse-admin.md)

- [Setting up matrix-registration](configuring-playbook-matrix-registration.md)
- [Setting up Ketesa](configuring-playbook-ketesa.md)

- [Setting up the REST authentication password provider module](configuring-playbook-rest-auth.md) (advanced)

@@ -112,8 +114,6 @@ Extend and modify how users are authenticated on your homeserver.

- [Setting up the LDAP authentication password provider module](configuring-playbook-ldap-auth.md) (advanced)

- [Setting up matrix-ldap-registration-proxy](configuring-playbook-matrix-ldap-registration-proxy.md) (advanced)

- [Setting up Synapse Simple Antispam](configuring-playbook-synapse-simple-antispam.md) (advanced)

- [Setting up Matrix User Verification Service](configuring-playbook-user-verification-service.md) (advanced)
@@ -146,6 +146,10 @@ Bridges can be used to connect your Matrix installation with third-party communi

- [Setting up Mautrix Google Messages bridging](configuring-playbook-bridge-mautrix-gmessages.md)

- [Setting up Mautrix Google Voice bridging](configuring-playbook-bridge-mautrix-gvoice.md)

- [Setting up Mautrix LinkedIn bridging](configuring-playbook-bridge-mautrix-linkedin.md)

- [Setting up Mautrix Whatsapp bridging](configuring-playbook-bridge-mautrix-whatsapp.md)

- [Setting up Instagram bridging via Mautrix Meta](configuring-playbook-bridge-mautrix-meta-instagram.md)
@@ -160,13 +164,13 @@ Bridges can be used to connect your Matrix installation with third-party communi

- [Setting up Mautrix wsproxy for bridging Android SMS or Apple iMessage](configuring-playbook-bridge-mautrix-wsproxy.md)

- [Setting up RustPush (iMessage) bridging](configuring-playbook-bridge-rustpush.md)

- [Setting up Appservice IRC bridging](configuring-playbook-bridge-appservice-irc.md)

- [Setting up Appservice Discord bridging](configuring-playbook-bridge-appservice-discord.md)

- [Setting up Appservice Kakaotalk bridging](configuring-playbook-bridge-appservice-kakaotalk.md)

- [Setting up Beeper LinkedIn bridging](configuring-playbook-bridge-beeper-linkedin.md)
- [Setting up Beeper LINE bridging](configuring-playbook-bridge-beeper-line.md)

- [Setting up matrix-hookshot](configuring-playbook-bridge-hookshot.md) — a bridge between Matrix and multiple project management services, such as [GitHub](https://github.com), [GitLab](https://about.gitlab.com) and [JIRA](https://www.atlassian.com/software/jira).

@@ -182,18 +186,18 @@ Bridges can be used to connect your Matrix installation with third-party communi

- [Setting up Heisenbridge bouncer-style IRC bridging](configuring-playbook-bridge-heisenbridge.md)

- [Setting up a Matrix <-> Meshtastic bridge](configuring-playbook-bridge-meshtastic-relay.md)

- [Setting up WeChat bridging](configuring-playbook-bridge-wechat.md)

### Bots

Bots provide various additional functionality to your installation.

- [Setting up baibot](configuring-playbook-bot-baibot.md) — a bot through which you can talk to various [AI](https://en.wikipedia.org/wiki/Artificial_intelligence) / [Large Language Models](https://en.wikipedia.org/wiki/Large_language_model) services ([OpenAI](https://openai.com/)'s [ChatGPT](https://openai.com/blog/chatgpt/) and [others](https://github.com/etkecc/baibot/blob/main/docs/providers.md))
- [Setting up baibot](configuring-playbook-bot-baibot.md) — a bot through which you can talk to various [AI](https://en.wikipedia.org/wiki/Artificial_intelligence) / [Large Language Models](https://en.wikipedia.org/wiki/Large_language_model) services (the privacy-first [Venice](configuring-playbook-bot-baibot.md#venice) we recommend, [OpenAI](https://openai.com/)'s [ChatGPT](https://openai.com/blog/chatgpt/), and [others](https://github.com/etkecc/baibot/blob/main/docs/providers.md))

- [Setting up matrix-reminder-bot](configuring-playbook-bot-matrix-reminder-bot.md) — a bot to remind you about stuff

- [Setting up matrix-registration-bot](configuring-playbook-bot-matrix-registration-bot.md) — a bot to create and manage registration tokens to invite users

- [Setting up maubot](configuring-playbook-bot-maubot.md) — a plugin-based Matrix bot system

- [Setting up Honoroit](configuring-playbook-bot-honoroit.md) — a helpdesk bot
@@ -204,6 +208,8 @@ Bots provide various additional functionality to your installation.

- [Setting up Draupnir for all/D4A](configuring-playbook-appservice-draupnir-for-all.md) — like the [Draupnir bot](configuring-playbook-bot-draupnir.md) mentioned above, but running in appservice mode and supporting multiple instances

- [Setting up Meowlnir](configuring-playbook-bot-meowlnir.md) — a moderation tool/bot which speaks the same policy list protocol as Draupnir and Mjolnir, but runs in appservice mode and can override policies coming from lists you do not control

- [Setting up Buscarron](configuring-playbook-bot-buscarron.md) — a bot you can use to send any form (HTTP POST, HTML) to a (encrypted) Matrix room

### Administration
@@ -261,10 +267,14 @@ Various services that don't fit any other categories.

- [Setting up the Sliding Sync proxy](configuring-playbook-sliding-sync-proxy.md) for clients which require Sliding Sync support (like old Element X versions, before it got switched to Simplified Sliding Sync)

- [Setting up Appservice Kakaotalk bridging](configuring-playbook-bridge-appservice-kakaotalk.md) (removed; the upstream repository has become unreachable and the component could only be installed by self-building it)

- [Setting up Appservice Slack bridging](configuring-playbook-bridge-appservice-slack.md) (removed; this component has been discontinued)

- [Setting up Appservice Webhooks bridging](configuring-playbook-bridge-appservice-webhooks.md) (deprecated; the bridge's author suggests taking a look at [matrix-hookshot](https://github.com/matrix-org/matrix-hookshot) as a replacement, which can also be [installed using this playbook](configuring-playbook-bridge-hookshot.md))

- [Setting up Beeper LinkedIn bridging](configuring-playbook-bridge-beeper-linkedin.md) (unmaintained; the [upstream repository](https://github.com/beeper/linkedin) has been archived. Consider [setting up Mautrix LinkedIn bridging](configuring-playbook-bridge-mautrix-linkedin.md))

- [Setting up the Dimension integration manager](configuring-playbook-dimension.md) ([unmaintained](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/2806#issuecomment-1673559299); after [installing](installing.md))

- [Setting up Email2Matrix](configuring-playbook-email2matrix.md) (removed; the author suggests taking a look at [Postmoogle](https://github.com/etkecc/postmoogle) as a replacement, which can also be [installed using this playbook](configuring-playbook-bridge-postmoogle.md))
@@ -277,6 +287,12 @@ Various services that don't fit any other categories.

- [Setting up matrix-bot-chatgpt](configuring-playbook-bot-chatgpt.md) (unmaintained; the bridge's author suggests taking a look at [baibot](https://github.com/etkecc/baibot) as a replacement, which can also be [installed using this playbook](configuring-playbook-bot-baibot.md))

- [Setting up matrix-ldap-registration-proxy](configuring-playbook-matrix-ldap-registration-proxy.md) (removed; the repository of the source code has been removed)

- [Setting up matrix-registration](configuring-playbook-matrix-registration.md) (removed; this component has been unmaintained)

- [Setting up matrix-registration-bot](configuring-playbook-bot-matrix-registration-bot.md) (removed; this component has been unmaintained)

- [Setting up Mautrix Facebook bridging](configuring-playbook-bridge-mautrix-facebook.md) (deprecated in favor of the Messenger/Instagram bridge with [mautrix-meta-messenger](configuring-playbook-bridge-mautrix-meta-messenger.md))

- [Setting up Mautrix Instagram bridging](configuring-playbook-bridge-mautrix-instagram.md) (deprecated in favor of the Messenger/Instagram bridge with [mautrix-meta-instagram](configuring-playbook-bridge-mautrix-meta-instagram.md))


+ 28
- 1
docs/configuring-well-known.md View File

@@ -104,6 +104,14 @@ All you need to do is:

- set up the server at your base domain (e.g. `example.com`) so that it adds an extra HTTP header when serving the `/.well-known/matrix/client` file. [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), the `Access-Control-Allow-Origin` header should be set with a value of `*`. If you don't do this step, web-based Matrix clients (like Element Web) may fail to work. Setting up headers for the `/.well-known/matrix/server` file is not necessary, as this file is only consumed by non-browsers, which don't care about CORS.

- make sure the files are served with a `Content-Type: application/json` HTTP header. You can verify this by running `curl -i https://example.com/.well-known/matrix/client`. Some web servers serve extensionless files as plain text or even offer them as downloads, which breaks stricter clients such as Element X ([manifesting as errors like `MISSING_MATRIX_RTC_FOCUS`](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/4763)). On Apache-based hosting, you can force the correct content type by placing an `.htaccess` file next to the files:

```apache
<FilesMatch "^(client|server|support)$">
ForceType application/json
</FilesMatch>
```

This is relatively easy to do and possibly your only choice if you can only host static files from the base domain's server. It is, however, **a little fragile**, as future updates performed by this playbook may regenerate the well-known files and you may need to notice that and copy them over again.

#### (Option 2): **Setting up reverse-proxying** of the well-known files from the base domain's server to the Matrix server
@@ -112,7 +120,9 @@ This option is less fragile and generally better.

On the base domain's server (e.g. `example.com`), you can set up reverse-proxying (or simply a 302 redirect), so that any access for the `/.well-known/matrix` location prefix is forwarded to the Matrix domain's server (e.g. `matrix.example.com`).

With this method, you **don't need** to add special HTTP headers for [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) reasons (like `Access-Control-Allow-Origin`), because your Matrix server (where requests ultimately go) will be configured by this playbook correctly.
With reverse-proxying, you **don't need** to add special HTTP headers for [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) reasons (like `Access-Control-Allow-Origin`), because your Matrix server (where requests ultimately go) will be configured by this playbook correctly.

If you use a 302 redirect instead, be aware that browsers apply CORS checks to every response in the redirect chain, so the redirect response itself must also carry an `Access-Control-Allow-Origin: *` header. Otherwise, web-based Matrix clients (like Element Web) may fail to work even though the final destination sets the header correctly.

**For nginx**, it would be something like this:

@@ -155,6 +165,23 @@ example.com {
}
```

**Note**: Caddy does not process directives in the order they appear in the Caddyfile, but according to its own [directive order](https://caddyserver.com/docs/caddyfile/directives#directive-order). Notably, `redir` is evaluated before `reverse_proxy`, so a `redir` elsewhere in the same site block (a common way to send the base domain to `www.example.com` or to another site) takes precedence and breaks the well-known reverse-proxying. In such cases, wrap the directives in [`handle`](https://caddyserver.com/docs/caddyfile/directives/handle) blocks to enforce the intended priority:

```caddy
example.com {
handle /.well-known/matrix/* {
reverse_proxy https://matrix.example.com {
header_up Host {upstream_hostport}
}
}

handle {
# Everything else, e.g. a redirect to some other site
redir https://www.example.com{uri}
}
}
```

**For HAProxy**, it would be something like this:

```haproxy


+ 14
- 9
docs/container-images.md View File

@@ -28,6 +28,7 @@ We try to stick to official images (provided by their respective projects) as mu
| [Synapse](configuring-playbook-synapse.md) | [element-hq/synapse](https://ghcr.io/element-hq/synapse) | ✅ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network |
| [Conduit](configuring-playbook-conduit.md) | [matrixconduit/matrix-conduit](https://hub.docker.com/r/matrixconduit/matrix-conduit) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. Conduit is a lightweight open-source server implementation of the Matrix Specification with a focus on easy setup and low system requirements |
| [continuwuity](configuring-playbook-continuwuity.md) | [continuwuation/continuwuity](https://forgejo.ellis.link/continuwuation/continuwuity) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. continuwuity is a continuation of conduwuit. |
| [Tuwunel](configuring-playbook-tuwunel.md) | [matrix-construct/tuwunel](https://ghcr.io/matrix-construct/tuwunel) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. Tuwunel is the official successor to conduwuit. |
| [Dendrite](configuring-playbook-dendrite.md) | [matrixdotorg/dendrite-monolith](https://hub.docker.com/r/matrixdotorg/dendrite-monolith/) | ❌ | Storing your data and managing your presence in the [Matrix](http://matrix.org/) network. Dendrite is a second-generation Matrix homeserver written in Go, an alternative to Synapse. |

## Clients
@@ -66,8 +67,6 @@ Extend and modify how users are authenticated on your homeserver.
| [matrix-synapse-rest-auth](configuring-playbook-rest-auth.md) | (N/A) | ❌ | REST authentication password provider module |
| [matrix-synapse-shared-secret-auth](configuring-playbook-shared-secret-auth.md) | (N/A) | ❌ | Password provider module |
| [matrix-synapse-ldap3](configuring-playbook-ldap-auth.md) (advanced) | (N/A) | ❌ | LDAP Auth password provider module |
| [matrix-ldap-registration-proxy](configuring-playbook-matrix-ldap-registration-proxy.md) | [activism.international/matrix_ldap_registration_proxy](https://gitlab.com/activism.international/matrix_ldap_registration_proxy/container_registry) | ❌ | Proxy that handles Matrix registration requests and forwards them to LDAP |
| [matrix-registration](configuring-playbook-matrix-registration.md) | [zeratax/matrix-registration](https://hub.docker.com/r/devture/zeratax-matrix-registration/) | ❌ | Simple python application to have a token based Matrix registration |
| [Matrix User Verification Service](configuring-playbook-user-verification-service.md) | [matrixdotorg/matrix-user-verification-service](https://hub.docker.com/r/atrixdotorg/matrix-user-verification-service) | ❌ | Service to verify details of a user based on an Open ID token |
| [synapse-simple-antispam](configuring-playbook-synapse-simple-antispam.md) (advanced) | (N/A) | ❌ | Spam checker module |

@@ -92,6 +91,8 @@ Bridges can be used to connect your Matrix installation with third-party communi
| [mautrix-slack](configuring-playbook-bridge-mautrix-slack.md) | [mautrix/slack](https://mau.dev/mautrix/slack/container_registry) | ❌ | Bridge to [Slack](https://slack.com/) |
| [mautrix-telegram](configuring-playbook-bridge-mautrix-telegram.md) | [mautrix/telegram](https://mau.dev/mautrix/telegram/container_registry) | ❌ | Bridge to [Telegram](https://telegram.org/) |
| [mautrix-gmessages](configuring-playbook-bridge-mautrix-gmessages.md) | [mautrix/gmessages](https://mau.dev/mautrix/gmessages/container_registry) | ❌ | Bridge to [Google Messages](https://messages.google.com/) |
| [mautrix-gvoice](configuring-playbook-bridge-mautrix-gvoice.md) | [mautrix/gvoice](https://mau.dev/mautrix/gvoice/container_registry) | ❌ | Bridge to [Google Voice](https://voice.google.com/) |
| [mautrix-linkedin](configuring-playbook-bridge-mautrix-linkedin.md) | [mautrix/linkedin](https://mau.dev/mautrix/linkedin/container_registry) | ❌ | Bridge to [LinkedIn](https://www.linkedin.com/) |
| [mautrix-whatsapp](configuring-playbook-bridge-mautrix-whatsapp.md) | [mautrix/whatsapp](https://mau.dev/mautrix/whatsapp/container_registry) | ❌ | Bridge to [WhatsApp](https://www.whatsapp.com/) |
| [mautrix-wsproxy](configuring-playbook-bridge-mautrix-wsproxy.md) | [mautrix/wsproxy](https://mau.dev/mautrix/wsproxy/container_registry) | ❌ | Bridge to Android SMS or Apple iMessage |
| [mautrix-twitter](configuring-playbook-bridge-mautrix-twitter.md) | [mautrix/twitter](https://mau.dev/mautrix/twitter/container_registry) | ❌ | Bridge to [Twitter](https://twitter.com/) |
@@ -99,8 +100,8 @@ Bridges can be used to connect your Matrix installation with third-party communi
| mautrix-meta (for [Messenger](configuring-playbook-bridge-mautrix-meta-messenger.md) and [Instagram](configuring-playbook-bridge-mautrix-meta-instagram.md)) | [mautrix/meta](https://mau.dev/mautrix/meta/container_registry) | ❌ | Bridge to [Messenger](https://messenger.com/) and [Instagram](https://instagram.com/) |
| [mautrix-signal](configuring-playbook-bridge-mautrix-signal.md) | [mautrix/signal](https://mau.dev/mautrix/signal/container_registry) | ❌ | Bridge to [Signal](https://www.signal.org/) |
| [beeper-linkedin](configuring-playbook-bridge-beeper-linkedin.md) | [beeper/linkedin](https://ghcr.io/beeper/linkedin) | ❌ | Bridge to [LinkedIn](https://www.linkedin.com/) |
| [beeper-line](configuring-playbook-bridge-beeper-line.md) | [crispyduck/beeper-line](https://hub.docker.com/r/crispyduck/beeper-line) | ❌ | Bridge to [LINE](https://line.me/) |
| [matrix-appservice-irc](configuring-playbook-bridge-appservice-irc.md) | [matrixdotorg/matrix-appservice-irc](https://hub.docker.com/r/matrixdotorg/matrix-appservice-irc) | ❌ | Bridge to [IRC](https://wikipedia.org/wiki/Internet_Relay_Chat) |
| [matrix-appservice-kakaotalk](configuring-playbook-bridge-appservice-kakaotalk.md) | Self-building | ❌ | Bridge to [Kakaotalk](https://www.kakaocorp.com/page/service/service/KakaoTalk?lang=ENG) |
| [matrix-appservice-discord](configuring-playbook-bridge-appservice-discord.md) | [matrix-org/matrix-appservice-discord](https://ghcr.io/matrix-org/matrix-appservice-discord) | ❌ | Bridge to [Discord](https://discordapp.com/) |
| [matrix-hookshot](configuring-playbook-bridge-hookshot.md) | [halfshot/matrix-hookshot](https://hub.docker.com/r/halfshot/matrix-hookshot) | ❌ | Bridge for generic webhooks and multiple project management services, such as GitHub, GitLab, Figma, and Jira in particular |
| [matrix-sms-bridge](configuring-playbook-bridge-matrix-bridge-sms.md) | [folivonet/matrix-sms-bridge](https://hub.docker.com/repository/docker/folivonet/matrix-sms-bridge) | ❌ | Bridge to SMS |
@@ -108,6 +109,7 @@ Bridges can be used to connect your Matrix installation with third-party communi
| [Heisenbridge](configuring-playbook-bridge-heisenbridge.md) | [hif1/heisenbridge](https://hub.docker.com/r/hif1/heisenbridge) | ❌ | Bouncer-style bridge to [IRC](https://wikipedia.org/wiki/Internet_Relay_Chat) |
| [mx-puppet-groupme](configuring-playbook-bridge-mx-puppet-groupme.md) | [xangelix/mx-puppet-groupme](https://hub.docker.com/r/xangelix/mx-puppet-groupme) | ❌ | Bridge to [GroupMe](https://groupme.com/) |
| [matrix-steam-bridge](configuring-playbook-bridge-steam.md) | [jasonlaguidice/matrix-steam-bridge](https://github.com/jasonlaguidice/matrix-steam-bridge/pkgs/container/matrix-steam-bridge) | ❌ | Bridge to [Steam](https://steampowered.com/) |
| [matrix-rustpush-bridge](configuring-playbook-bridge-rustpush.md) | [jasonlaguidice/imessage](https://github.com/jasonlaguidice/imessage/pkgs/container/imessage) | ❌ | Bridge to [iMessage](https://support.apple.com/messages) via Apple Push Notification service |
| [mx-puppet-steam](configuring-playbook-bridge-mx-puppet-steam.md) | [icewind1991/mx-puppet-steam](https://hub.docker.com/r/icewind1991/mx-puppet-steam) | ❌ | Bridge to [Steam](https://steamapp.com/) |
| [Postmoogle](configuring-playbook-bridge-postmoogle.md) | [etke.cc/postmoogle](https://github.com/etkecc/postmoogle/container_registry) | ❌ | Email to Matrix bridge |

@@ -119,11 +121,11 @@ Bots provide various additional functionality to your installation.
| ------- | --------------- | -------- | ----------- |
| [baibot](configuring-playbook-bot-baibot.md) | [etke.cc/baibot](https://ghcr.io/etkecc/baibot) | ❌ | Bot that exposes the power of [AI](https://en.wikipedia.org/wiki/Artificial_intelligence) / [Large Language Models](https://en.wikipedia.org/wiki/Large_language_model) to you |
| [matrix-reminder-bot](configuring-playbook-bot-matrix-reminder-bot.md) | [anoa/matrix-reminder-bot](https://hub.docker.com/r/anoa/matrix-reminder-bot) | ❌ | Bot for scheduling one-off & recurring reminders and alarms |
| [matrix-registration-bot](configuring-playbook-bot-matrix-registration-bot.md) | [moanos/matrix-registration-bot](https://hub.docker.com/r/moanos/matrix-registration-bot/) | ❌ | Bot for invitations by creating and managing registration tokens |
| [maubot](configuring-playbook-bot-maubot.md) | [dock.mau.dev/maubot/maubot](https://mau.dev/maubot/maubot/container_registry) | ❌ | Plugin-based Matrix bot system |
| [Honoroit](configuring-playbook-bot-honoroit.md) | [etke.cc/honoroit](https://github.com/etkecc/honoroit/container_registry) | ❌ | Helpdesk bot |
| [Mjolnir](configuring-playbook-bot-mjolnir.md) | [matrixdotorg/mjolnir](https://hub.docker.com/r/matrixdotorg/mjolnir) | ❌ | Moderation tool for Matrix |
| [Draupnir](configuring-playbook-bot-draupnir.md) | [gnuxie/draupnir](https://hub.docker.com/r/gnuxie/draupnir) | ❌ | Moderation tool for Matrix (Fork of Mjolnir) |
| [Meowlnir](configuring-playbook-bot-meowlnir.md) | [maunium/meowlnir](https://mau.dev/maunium/meowlnir/container_registry) | ❌ | Moderation tool for Matrix, running in appservice mode |
| [Buscarron](configuring-playbook-bot-buscarron.md) | [etke.cc/buscarron](https://ghcr.io/etkecc/buscarron) | ❌ | Web forms (HTTP POST) to Matrix |

## Administration
@@ -134,7 +136,7 @@ Services that help you in administrating and monitoring your Matrix installation
| ------- | --------------- | -------- | ----------- |
| [matrix-alertmanager-receiver](configuring-playbook-alertmanager-receiver.md) | [metio/matrix-alertmanager-receiver](https://hub.docker.com/r/metio/matrix-alertmanager-receiver) | ❌ | Prometheus' [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) client |
| [Matrix Authentication Service](configuring-playbook-matrix-authentication-service.md) | [element-hq/matrix-authentication-service](https://ghcr.io/element-hq/matrix-authentication-service) | ❌ | OAuth 2.0 and OpenID Provider server |
| [synapse-admin](configuring-playbook-synapse-admin.md) | [etke.cc/synapse-admin](https://ghcr.io/etkecc/synapse-admin) | ❌ | Web UI tool for administrating users and rooms on your Matrix server |
| [Ketesa](configuring-playbook-ketesa.md) | [etkecc/ketesa](https://ghcr.io/etkecc/ketesa) | ❌ | Fully-featured web UI for administrating your Matrix homeserver — users, rooms, media, sessions, and more |
| [Metrics and Graphs](configuring-playbook-prometheus-grafana.md) | [prom/prometheus](https://hub.docker.com/r/prom/prometheus/) | ❌ | [Prometheus](https://prometheus.io) time-series database server |
| [Metrics and Graphs](configuring-playbook-prometheus-grafana.md) | [prom/node-exporter](https://hub.docker.com/r/prom/node-exporter/) | ❌ | Prometheus [node-exporter](https://prometheus.io/docs/guides/node-exporter/) host metrics exporter |
| [Metrics and Graphs](configuring-playbook-prometheus-grafana.md) | [grafana/grafana](https://hub.docker.com/r/grafana/grafana/) | ❌ | Graphing tool that works well with the above two images. Our playbook also adds two dashboards for [Synapse](https://github.com/element-hq/synapse/tree/master/contrib/grafana) and [Node Exporter](https://github.com/rfrail3/grafana-dashboards) |
@@ -153,10 +155,10 @@ Various services that don't fit any other categories.
| [synapse_auto_compressor](configuring-playbook-synapse-auto-compressor.md) | [mb-saces/rust-synapse-tools](https://gitlab.com/mb-saces/rust-synapse-tools/container_registry) | ❌ | Cli tool that automatically compresses Synapse's `state_groups` database table in background |
| [Matrix Corporal](configuring-playbook-matrix-corporal.md) (advanced) | [devture/matrix-corporal](https://hub.docker.com/r/devture/matrix-corporal/) | ❌ | Reconciliator and gateway for a managed Matrix server |
| [Etherpad](configuring-playbook-etherpad.md) | [etherpad/etherpad](https://hub.docker.com/r/etherpad/etherpad/) | ❌ | Open source collaborative text editor |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/web](https://hub.docker.com/r/jitsi/web) | ❌ | [Jitsi](https://jitsi.org/) web UI |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/jicofo](https://hub.docker.com/r/jitsi/jicofo) | ❌ | [Jitsi](https://jitsi.org/) Focus component |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/prosody](https://hub.docker.com/r/jitsi/prosody) | ❌ | [Jitsi](https://jitsi.org/) Prosody XMPP server component |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/jvb](https://hub.docker.com/r/jitsi/jvb) | ❌ | [Jitsi](https://jitsi.org/) Video Bridge component |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/web](https://github.com/jitsi/docker-jitsi-meet/pkgs/container/web) | ❌ | [Jitsi](https://jitsi.org/) web UI |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/jicofo](https://github.com/jitsi/docker-jitsi-meet/pkgs/container/jicofo) | ❌ | [Jitsi](https://jitsi.org/) Focus component |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/prosody](https://github.com/jitsi/docker-jitsi-meet/pkgs/container/prosody) | ❌ | [Jitsi](https://jitsi.org/) Prosody XMPP server component |
| [Jitsi](configuring-playbook-jitsi.md) | [jitsi/jvb](https://github.com/jitsi/docker-jitsi-meet/pkgs/container/jvb) | ❌ | [Jitsi](https://jitsi.org/) Video Bridge component |
| [Cactus Comments](configuring-playbook-cactus-comments.md) | [cactuscomments/cactus-appservice](https://hub.docker.com/r/cactuscomments/cactus-appservice/) | ❌ | Federated comment system built on Matrix |
| [Cactus Comments](configuring-playbook-cactus-comments.md) | [joseluisq/static-web-server](https://hub.docker.com/r/joseluisq/static-web-server) | ❌ | Federated comment system built on Matrix |
| [Pantalaimon](configuring-playbook-pantalaimon.md) | [matrixdotorg/pantalaimon](https://hub.docker.com/r/matrixdotorg/pantalaimon) | ❌ | E2EE aware proxy daemon |
@@ -178,6 +180,9 @@ The list of the deprecated or unmaintained services is available [here](configur
| [matrix-appservice-slack](configuring-playbook-bridge-appservice-slack.md) | [matrixdotorg/matrix-appservice-slack](https://hub.docker.com/r/matrixdotorg/matrix-appservice-slack) | ❌ | Bridge to [Slack](https://slack.com/) |
| [matrix-appservice-webhooks](configuring-playbook-bridge-appservice-webhooks.md) | [turt2live/matrix-appservice-webhooks](https://hub.docker.com/r/turt2live/matrix-appservice-webhooks) | ❌ | Bridge for slack compatible webhooks ([ConcourseCI](https://concourse-ci.org/), [Slack](https://slack.com/) etc. pp.) |
| [matrix-chatgpt-bot](configuring-playbook-bot-chatgpt.md) | [matrixgpt/matrix-chatgpt-bot](https://ghcr.io/matrixgpt/matrix-chatgpt-bot) | ❌ | Accessing ChatGPT via your favourite Matrix client |
| [matrix-ldap-registration-proxy](configuring-playbook-matrix-ldap-registration-proxy.md) | [activism.international/matrix_ldap_registration_proxy](https://gitlab.com/activism.international/matrix_ldap_registration_proxy/container_registry) | ❌ | Proxy that handles Matrix registration requests and forwards them to LDAP |
| [matrix-registration](configuring-playbook-matrix-registration.md) | [zeratax/matrix-registration](https://hub.docker.com/r/devture/zeratax-matrix-registration/) | ❌ | Simple python application to have a token based Matrix registration |
| [matrix-registration-bot](configuring-playbook-bot-matrix-registration-bot.md) | [moanos/matrix-registration-bot](https://hub.docker.com/r/moanos/matrix-registration-bot/) | ❌ | Bot for invitations by creating and managing registration tokens |
| [mautrix-facebook](configuring-playbook-bridge-mautrix-facebook.md) | [mautrix/facebook](https://mau.dev/mautrix/facebook/container_registry) | ❌ | Bridge to [Facebook](https://facebook.com/) |
| [mautrix-instagram](configuring-playbook-bridge-mautrix-instagram.md) | [mautrix/instagram](https://mau.dev/mautrix/instagram/container_registry) | ❌ | Bridge to [Instagram](https://instagram.com/) |
| [mx-puppet-discord](configuring-playbook-bridge-mx-puppet-discord.md) | [mx-puppet/discord/mx-puppet-discord](https://gitlab.com/mx-puppet/discord/mx-puppet-discord/container_registry) | ❌ | Bridge to [Discord](https://discordapp.com/) |


+ 6
- 0
docs/faq.md View File

@@ -456,6 +456,12 @@ If it is correctly specified, look Traefik's logs (`journalctl -fu matrix-traefi

## Miscellaneous

### The role to manage the service which I deploy has been removed from the playbook. Does this mean that the service can no longer be used on my server?

Not necessarily. Removing the role from the playbook does not always mean that the service has been deprecated by the upstream developers, so as long as the resource such as the Docker image is available, you should be able to keep running it by reverting the specific commit which has removed the role. This essentially means that you will need to maintain your own version of the playbook.

Please keep in mind that you will occasionally need to fix code conflicts if any.

### I would like to see this favorite service of mine integrated and become available on my Matrix server. How can I request it?

You can freely create an issue for feature request on the repository at GitHub [here](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/new/choose). Note this is a community project with no financial backing, and there is not assurance that your request would be eventually picked up by others and the requested feature would become available. The easiest way to get a feature into this project is to just develop it yourself.


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save