Merge pull request #962 from aaronraimist/mjolnir

Add mjolnir
master
Slavi Pantaleev 3 years ago committed by GitHub
commit 995c483856
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -93,6 +93,8 @@ Using this playbook, you can get the following services configured on your serve
- (optional) [Go-NEB](https://github.com/matrix-org/go-neb) multi functional bot written in Go - see [docs/configuring-playbook-bot-go-neb.md](docs/configuring-playbook-bot-go-neb.md) for setup documentation
- (optional) [Mjolnir](https://github.com/matrix-org/mjolnir), a moderation tool for Matrix - see [docs/configuring-playbook-bot-mjolnir.md](docs/configuring-playbook-bot-mjolnir.md) for setup documentation
- (optional) [synapse-admin](https://github.com/Awesome-Technologies/synapse-admin), a web UI tool for administrating users and rooms on your Matrix server - see [docs/configuring-playbook-synapse-admin.md](docs/configuring-playbook-synapse-admin.md) for setup documentation
- (optional) [matrix-registration](https://github.com/ZerataX/matrix-registration), a simple python application to have a token based matrix registration - see [docs/configuring-playbook-matrix-registration.md](docs/configuring-playbook-matrix-registration.md) for setup documentation

@ -0,0 +1,119 @@
# Setting up Mjolnir (optional)
The playbook can install and configure the [Mjolnir](https://github.com/matrix-org/mjolnir) moderation bot for you.
See the project's [documentation](https://github.com/matrix-org/mjolnir) to learn what it does and why it might be useful to you.
Note: the playbook does not currently support the Mjolnir Synapse module. The playbook does support another antispam module, see [Setting up Synapse Simple Antispam](configuring-playbook-synapse-simple-antispam.md).
## 1. Registering the bot user
The playbook does not automatically create users for you. The bot requires an access token to be able to connect to your homeserver.
You **need to register the bot user manually** before setting up the bot.
Choose a strong password for the bot. You can generate a good password with a command like this: `pwgen -s 64 1`.
You can use the playbook to [register a new user](registering-users.md):
```
ansible-playbook -i inventory/hosts setup.yml --extra-vars='username=bot.mjolnir password=PASSWORD_FOR_THE_BOT admin=no' --tags=register-user
```
If you would like Mjolnir to be able to deactivate users, move aliases, shutdown rooms, etc then it must be a server admin so you need to change `admin=no` to `admin=yes` in the command above.
## 2. Get an access token
If you use curl, you can get an access token like this:
```
curl -X POST --header 'Content-Type: application/json' -d '{
"identifier": { "type": "m.id.user", "user": "bot.mjolnir" },
"password": "PASSWORD_FOR_THE_BOT",
"type": "m.login.password"
}' 'https://matrix.DOMAIN/_matrix/client/r0/login'
```
Alternatively, you can use a full-featured client (such as Element) to log in and get the access token from there (note: don't log out from the client as that will invalidate the token).
## 3. Make sure the account is free from rate limiting
You will need to prevent Synapse from rate limiting the bot's account. This is not an optional step. If you do not do this step Mjolnir will crash. [Currently there is no Synapse config option for this](https://github.com/matrix-org/synapse/issues/6286) so you have to manually edit the Synapse database. Manually editing the Synapse database is rarely a good idea but in this case it is required. Please ask for help if you are uncomfortable with these steps.
1. Copy the statement below into a text editor.
```
INSERT INTO ratelimit_override VALUES ("@bot.mjolnir:DOMAIN", 0, 0);
```
1. Change the username (`@bot.mjolnir:DOMAIN`) to the username you used when you registered the bot's account. You must change `DOMAIN` to your server's domain.
1. Get a database terminal by following these steps: [maintenance-postgres.md#getting-a-database-terminal](maintenance-postgres.md#getting-a-database-terminal)
1. Connect to Synapse's database by typing `\connect synapse` into the database terminal
1. Paste in the `INSERT INTO` command that you edited and press enter.
You can run `SELECT * FROM ratelimit_override;` to see if it worked. If the output looks like this:
```
user_id | messages_per_second | burst_count
-----------------------+---------------------+-------------
@bot.mjolnir:raim.ist | 0 | 0`
```
then you did it correctly.
## 5. Create a management room
Using your own account, create a new 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.
Once you have created the room you need to copy the room ID so you can tell the bot to use that room. In Element you can do this by going to the room's settings, clicking Advanced, and then coping the internal room ID. The room ID will look something like `!QvgVuKq0ha8glOLGMG:DOMAIN`.
## 4. Adjusting the playbook configuration
Add the following configuration to your `inventory/host_vars/matrix.DOMAIN/vars.yml` file (adapt to your needs):
You must replace `ACCESS_TOKEN_FROM_STEP_2_GOES_HERE` and `ROOM_ID_FROM_STEP_5_GOES_HERE` with the your own values.
```yaml
matrix_bot_mjolnir_enabled: true
matrix_bot_mjolnir_access_token: "ACCESS_TOKEN_FROM_STEP_2_GOES_HERE"
matrix_bot_mjolnir_management_room: "ROOM_ID_FROM_STEP_5_GOES_HERE"
```
## 5. Installing
After configuring the playbook, run the [installation](installing.md) command:
```
ansible-playbook -i inventory/hosts setup.yml --tags=setup-all,start
```
## Usage
You can refer to the upstream [documentation](https://github.com/matrix-org/mjolnir) for additional ways to use and configure mjolnir. Check out their [quickstart guide](https://github.com/matrix-org/mjolnir#quickstart-guide) for some basic commands you can give to the bot.
You can configure additional options by adding the `matrix_bot_mjolnir_configuration_extension_yaml` variable to your `inventory/host_vars/matrix.DOMAIN/vars.yml` file.
For example to change mjolnir's `recordIgnoredInvites` option to `true` you would add the following to your `vars.yml` file.
```yaml
matrix_bot_mjolnir_configuration_extension_yaml: |
# Your custom YAML configuration goes here.
# This configuration extends the default starting configuration (`matrix_bot_mjolnir_configuration_yaml`).
#
# You can override individual variables from the default configuration, or introduce new ones.
#
# If you need something more special, you can take full control by
# completely redefining `matrix_bot_mjolnir_configuration_yaml`.
recordIgnoredInvites: true
```

@ -85,6 +85,8 @@ When you're done with all the configuration you'd like to do, continue with [Ins
- [Setting up Matrix Corporal](configuring-playbook-matrix-corporal.md) (optional, advanced)
- [Setting up Mjolnir](configuring-playbook-bot-mjolnir.md) (optional, advanced)
### Bridging other networks

@ -90,6 +90,8 @@ These services are not part of our default installation, but can be enabled by [
- [matrixdotorg/go-neb](https://hub.docker.com/r/matrixdotorg/go-neb) - the [Go-NEB](https://github.com/matrix-org/go-neb) bot (optional)
- [matrixdotorg/mjolnir](https://hub.docker.com/r/matrixdotorg/mjolnir) - the [mjolnir](https://github.com/matrix-org/mjolnir) moderation bot (optional)
- [awesometechnologies/synapse-admin](https://hub.docker.com/r/awesometechnologies/synapse-admin) - the [synapse-admin](https://github.com/Awesome-Technologies/synapse-admin) web UI tool for administrating users and rooms on your Matrix server (optional)
- [prom/prometheus](https://hub.docker.com/r/prom/prometheus/) - [Prometheus](https://github.com/prometheus/prometheus/) is a systems and service monitoring system

@ -815,6 +815,33 @@ matrix_bot_go_neb_container_http_host_bind_port: "{{ '' if matrix_nginx_proxy_en
######################################################################
######################################################################
#
# matrix-bot-mjolnir
#
######################################################################
# We don't enable bots by default.
matrix_bot_mjolnir_enabled: false
matrix_bot_mjolnir_systemd_required_services_list: |
{{
['docker.service']
+
(['matrix-synapse.service'] if matrix_synapse_enabled else [])
+
(['matrix-postgres.service'] if matrix_postgres_enabled else [])
+
(['matrix-nginx-proxy.service'] if matrix_nginx_proxy_enabled else [])
}}
######################################################################
#
# /matrix-bot-mjolnir
#
######################################################################
######################################################################
#
# matrix-corporal

@ -0,0 +1,52 @@
# A moderation tool for Matrix
# See: https://github.com/matrix-org/mjolnir
matrix_bot_mjolnir_enabled: true
matrix_bot_mjolnir_version: "v0.1.17"
matrix_bot_mjolnir_docker_image: "docker.io/matrixdotorg/mjolnir:{{ matrix_bot_mjolnir_version }}"
matrix_bot_mjolnir_docker_image_force_pull: "{{ matrix_bot_mjolnir_docker_image.endswith(':latest') }}"
matrix_bot_mjolnir_base_path: "{{ matrix_base_data_path }}/mjolnir"
matrix_bot_mjolnir_config_path: "{{ matrix_bot_mjolnir_base_path }}/config"
matrix_bot_mjolnir_data_path: "{{ matrix_bot_mjolnir_base_path }}/data"
# A list of extra arguments to pass to the container
matrix_bot_mjolnir_container_extra_arguments: []
# List of systemd services that matrix-bot-mjolnir.service depends on
matrix_bot_mjolnir_systemd_required_services_list: ['docker.service']
# List of systemd services that matrix-bot-mjolnir.service wants
matrix_bot_mjolnir_systemd_wanted_services_list: []
# The access token for the bot user
matrix_bot_mjolnir_access_token: ""
# The room ID where people can use the bot. The bot has no access controls, so
# anyone in this room can use the bot - secure your room!
# This should be a room alias or room ID - not a matrix.to URL.
# Note: Mjolnir is fairly verbose - expect a lot of messages from it.
matrix_bot_mjolnir_management_room: ""
# Default configuration template which covers the generic use case.
# You can customize it by controlling the various variables inside it.
#
# For a more advanced customization, you can extend the default (see `matrix_bot_mjolnir_configuration_extension_yaml`)
# or completely replace this variable with your own template.
matrix_bot_mjolnir_configuration_yaml: "{{ lookup('template', 'templates/production.yaml.j2') }}"
matrix_bot_mjolnir_configuration_extension_yaml: |
# Your custom YAML configuration goes here.
# This configuration extends the default starting configuration (`matrix_bot_mjolnir_configuration_yaml`).
#
# You can override individual variables from the default configuration, or introduce new ones.
#
# If you need something more special, you can take full control by
# completely redefining `matrix_bot_mjolnir_configuration_yaml`.
matrix_bot_mjolnir_configuration_extension: "{{ matrix_bot_mjolnir_configuration_extension_yaml|from_yaml if matrix_bot_mjolnir_configuration_extension_yaml|from_yaml is mapping else {} }}"
# Holds the final configuration (a combination of the default and its extension).
# You most likely don't need to touch this variable. Instead, see `matrix_bot_mjolnir_configuration_yaml`.
matrix_bot_mjolnir_configuration: "{{ matrix_bot_mjolnir_configuration_yaml|from_yaml|combine(matrix_bot_mjolnir_configuration_extension, recursive=True) }}"

@ -0,0 +1,3 @@
- set_fact:
matrix_systemd_services_list: "{{ matrix_systemd_services_list + ['matrix-bot-mjolnir.service'] }}"
when: matrix_bot_mjolnir_enabled|bool

@ -0,0 +1,21 @@
- import_tasks: "{{ role_path }}/tasks/init.yml"
tags:
- always
- import_tasks: "{{ role_path }}/tasks/validate_config.yml"
when: "run_setup|bool and matrix_bot_mjolnir_enabled|bool"
tags:
- setup-all
- setup-bot-mjolnir
- import_tasks: "{{ role_path }}/tasks/setup_install.yml"
when: "run_setup|bool and matrix_bot_mjolnir_enabled|bool"
tags:
- setup-all
- setup-bot-mjolnir
- import_tasks: "{{ role_path }}/tasks/setup_uninstall.yml"
when: "run_setup|bool and not matrix_bot_mjolnir_enabled|bool"
tags:
- setup-all
- setup-bot-mjolnir

@ -0,0 +1,50 @@
---
- set_fact:
matrix_bot_mjolnir_requires_restart: false
- name: Ensure matrix-bot-mjolnir paths exist
file:
path: "{{ item.path }}"
state: directory
mode: 0750
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
with_items:
- { path: "{{ matrix_bot_mjolnir_base_path }}", when: true }
- { path: "{{ matrix_bot_mjolnir_config_path }}", when: true }
- { path: "{{ matrix_bot_mjolnir_data_path }}", when: true }
when: "item.when|bool"
- name: Ensure mjolnir image is pulled
docker_image:
name: "{{ matrix_bot_mjolnir_docker_image }}"
source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}"
force_source: "{{ matrix_bot_mjolnir_docker_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}"
force: "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_bot_mjolnir_docker_image_force_pull }}"
- name: Ensure matrix-bot-mjolnir config installed
copy:
content: "{{ matrix_bot_mjolnir_configuration|to_nice_yaml }}"
dest: "{{ matrix_bot_mjolnir_config_path }}/production.yaml"
mode: 0644
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
- name: Ensure matrix-bot-mjolnir.service installed
template:
src: "{{ role_path }}/templates/systemd/matrix-bot-mjolnir.service.j2"
dest: "{{ matrix_systemd_path }}/matrix-bot-mjolnir.service"
mode: 0644
register: matrix_bot_mjolnir_systemd_service_result
- name: Ensure systemd reloaded after matrix-bot-mjolnir.service installation
service:
daemon_reload: yes
when: "matrix_bot_mjolnir_systemd_service_result.changed|bool"
- name: Ensure matrix-bot-mjolnir.service restarted, if necessary
service:
name: "matrix-bot-mjolnir.service"
state: restarted
when: "matrix_bot_mjolnir_requires_restart|bool"

@ -0,0 +1,35 @@
---
- name: Check existence of matrix-bot-mjolnir service
stat:
path: "{{ matrix_systemd_path }}/matrix-bot-mjolnir.service"
register: matrix_bot_mjolnir_service_stat
- name: Ensure matrix-bot-mjolnir is stopped
service:
name: matrix-bot-mjolnir
state: stopped
daemon_reload: yes
register: stopping_result
when: "matrix_bot_mjolnir_service_stat.stat.exists|bool"
- name: Ensure matrix-bot-mjolnir.service doesn't exist
file:
path: "{{ matrix_systemd_path }}/matrix-bot-mjolnir.service"
state: absent
when: "matrix_bot_mjolnir_service_stat.stat.exists|bool"
- name: Ensure systemd reloaded after matrix-bot-mjolnir.service removal
service:
daemon_reload: yes
when: "matrix_bot_mjolnir_service_stat.stat.exists|bool"
- name: Ensure matrix-bot-mjolnir paths don't exist
file:
path: "{{ matrix_bot_mjolnir_base_path }}"
state: absent
- name: Ensure mjolnir Docker image doesn't exist
docker_image:
name: "{{ matrix_bot_mjolnir_docker_image }}"
state: absent

@ -0,0 +1,9 @@
---
- name: Fail if required variables are undefined
fail:
msg: "The `{{ item }}` variable must be defined and have a non-null value."
with_items:
- "matrix_bot_mjolnir_access_token"
- "matrix_bot_mjolnir_management_room"
when: "vars[item] == '' or vars[item] is none"

@ -0,0 +1,162 @@
# Where the homeserver is located (client-server URL). This should point at
# pantalaimon if you're using that.
homeserverUrl: "{{ matrix_homeserver_url }}"
# The access token for the bot to use. Do not populate if using Pantalaimon.
accessToken: "{{ matrix_bot_mjolnir_access_token }}"
# Pantalaimon options (https://github.com/matrix-org/pantalaimon)
#pantalaimon:
# # If true, accessToken above is ignored and the username/password below will be
# # used instead. The access token of the bot will be stored in the dataPath.
# use: false
#
# # The username to login with.
# username: mjolnir
#
# # The password to login with. Can be removed after the bot has logged in once and
# # stored the access token.
# password: your_password
# The directory the bot should store various bits of information in
dataPath: "/data"
# If true (the default), only users in the `managementRoom` can invite the bot
# to new rooms.
autojoinOnlyIfManager: true
# If `autojoinOnlyIfManager` is false, only the members in this group can invite
# the bot to new rooms.
#acceptInvitesFromGroup: '+example:example.org'
# If the bot is invited to a room and it won't accept the invite (due to the
# conditions above), report it to the management room. Defaults to disabled (no
# reporting).
recordIgnoredInvites: false
# The room ID where people can use the bot. The bot has no access controls, so
# anyone in this room can use the bot - secure your room!
# This should be a room alias or room ID - not a matrix.to URL.
# Note: Mjolnir is fairly verbose - expect a lot of messages from it.
managementRoom: "{{ matrix_bot_mjolnir_management_room }}"
# Set to false to make the management room a bit quieter.
verboseLogging: false
# The log level for the logs themselves. One of DEBUG, INFO, WARN, and ERROR.
# This should be at INFO or DEBUG in order to get support for Mjolnir problems.
logLevel: "INFO"
# Set to false to disable synchronizing the ban lists on startup. If true, this
# is the same as running !mjolnir sync immediately after startup.
syncOnStartup: true
# Set to false to prevent Mjolnir from checking its permissions on startup. This
# is recommended to be left as "true" to catch room permission problems (state
# resets, etc) before Mjolnir is needed.
verifyPermissionsOnStartup: true
# If true, Mjolnir won't actually ban users or apply server ACLs, but will
# think it has. This is useful to see what it does in a scenario where the
# bot might not be trusted fully, yet. Default false (do bans/ACLs).
noop: false
# Set to true to use /joined_members instead of /state to figure out who is
# in the room. Using /state is preferred because it means that users are
# banned when they are invited instead of just when they join, though if your
# server struggles with /state requests then set this to true.
fasterMembershipChecks: false
# A case-insensitive list of ban reasons to automatically redact a user's
# messages for. Typically this is useful to avoid having to type two commands
# to the bot. Use asterisks to represent globs (ie: "spam*testing" would match
# "spam for testing" as well as "spamtesting").
automaticallyRedactForReasons:
- "spam"
- "advertising"
# A list of rooms to protect (matrix.to URLs)
#protectedRooms:
# - "https://matrix.to/#/#yourroom:example.org"
# Set this option to true to protect every room the bot is joined to. Note that
# this effectively makes the protectedRooms and associated commands useless because
# the bot by nature must be joined to the room to protect it.
#
# Note: the management room is *excluded* from this condition. Add it to the
# protected rooms to protect it.
#
# Note: ban list rooms the bot is watching but didn't create will not be protected.
# Manually add these rooms to the protected rooms list if you want them protected.
protectAllJoinedRooms: false
# Misc options for command handling and commands
commands:
# If true, Mjolnir will respond to commands like !help and !ban instead of
# requiring a prefix. This is useful if Mjolnir is the only bot running in
# your management room.
#
# Note that Mjolnir can be pinged by display name instead of having to use
# the !mjolnir prefix. For example, "my_moderator_bot: ban @spammer:example.org"
# will ban a user.
allowNoPrefix: false
# In addition to the bot's display name, !mjolnir, and optionally no prefix
# above, the bot will respond to these names. The items here can be used either
# as display names or prefixed with exclamation points.
additionalPrefixes:
- "mjolnir_bot"
# If true, ban commands that use wildcard characters require confirmation with
# an extra `--force` argument
confirmWildcardBan: true
# Configuration specific to certain toggleable protections
#protections:
# # Configuration for the wordlist plugin, which can ban users based if they say certain
# # blocked words shortly after joining.
# wordlist:
# # A list of words which should be monitored by the bot. These will match if any part
# # of the word is present in the message in any case. e.g. "hello" also matches
# # "HEllO". Additionally, regular expressions can be used.
# words:
# - "CaSe"
# - "InSeNsAtIve"
# - "WoRd"
# - "LiSt"
#
# # How long after a user joins the server should the bot monitor their messages. After
# # this time, users can say words from the wordlist without being banned automatically.
# # Set to zero to disable (users will always be banned if they say a bad word)
# minutesBeforeTrusting: 20
# Options for monitoring the health of the bot
health:
# healthz options. These options are best for use in container environments
# like Kubernetes to detect how healthy the service is. The bot will report
# that it is unhealthy until it is able to process user requests. Typically
# this means that it'll flag itself as unhealthy for a number of minutes
# before saying "Now monitoring rooms" and flagging itself healthy.
#
# Health is flagged through HTTP status codes, defined below.
healthz:
# Whether the healthz integration should be enabled (default false)
enabled: false
# The port to expose the webserver on. Defaults to 8080.
port: 8080
# The address to listen for requests on. Defaults to all addresses.
address: "0.0.0.0"
# The path to expose the monitoring endpoint at. Defaults to `/healthz`
endpoint: "/healthz"
# The HTTP status code which reports that the bot is healthy/ready to
# process requests. Typically this should not be changed. Defaults to
# 200.
healthyStatus: 200
# The HTTP status code which reports that the bot is not healthy/ready.
# Defaults to 418.
unhealthyStatus: 418

@ -0,0 +1,42 @@
#jinja2: lstrip_blocks: "True"
[Unit]
Description=Matrix Mjolnir bot
{% for service in matrix_bot_mjolnir_systemd_required_services_list %}
Requires={{ service }}
After={{ service }}
{% endfor %}
{% for service in matrix_bot_mjolnir_systemd_required_services_list %}
Wants={{ service }}
{% endfor %}
DefaultDependencies=no
[Service]
Type=simple
Environment="HOME={{ matrix_systemd_unit_home_path }}"
ExecStartPre=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} kill matrix-bot-mjolnir 2>/dev/null'
ExecStartPre=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} rm matrix-bot-mjolnir 2>/dev/null'
# Intentional delay, so that the homeserver (we likely depend on) can manage to start.
ExecStartPre={{ matrix_host_command_sleep }} 5
ExecStart={{ matrix_host_command_docker }} run --rm --name matrix-bot-mjolnir \
--log-driver=none \
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
--cap-drop=ALL \
--read-only \
--network={{ matrix_docker_network }} \
--mount type=bind,src={{ matrix_bot_mjolnir_config_path }},dst=/data/config,ro \
--mount type=bind,src={{ matrix_bot_mjolnir_data_path }},dst=/data \
{% for arg in matrix_bot_mjolnir_container_extra_arguments %}
{{ arg }} \
{% endfor %}
{{ matrix_bot_mjolnir_docker_image }}
ExecStop=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} kill matrix-bot-mjolnir 2>/dev/null'
ExecStop=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} rm matrix-bot-mjolnir 2>/dev/null'
Restart=always
RestartSec=30
SyslogIdentifier=matrix-bot-mjolnir
[Install]
WantedBy=multi-user.target

@ -34,6 +34,7 @@
- matrix-bridge-sms
- matrix-bot-matrix-reminder-bot
- matrix-bot-go-neb
- matrix-bot-mjolnir
- matrix-synapse
- matrix-synapse-admin
- matrix-prometheus-node-exporter

Loading…
Cancel
Save