mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-09-12 19:03:14 +00:00
Add support for Meowlnir
Meowlnir (https://github.com/maunium/meowlnir) is a Matrix moderation bot which speaks the same policy-list protocol as Mjolnir and Draupnir, but runs as an appservice and can override individual policies coming from ban lists you do not control. Bots and their management rooms live only in Meowlnir's own database — nothing in its configuration file can declare one — so the role provisions them through the management API from a declarative roster (matrix_bot_meowlnir_bots_custom), applied under the ensure-matrix-users-created tag. Management rooms may be declared or created for you; bots and rooms no longer declared get pruned. Wrapper scripts for driving the management API by hand are installed to /matrix/meowlnir/bin. Meowlnir re-runs its configuration upgrader in memory on every start, so a literal `generate` value yields a new secret per restart. All secrets are therefore rendered explicitly, validation rejects `generate`, and the configuration directory is mounted read-only. Draupnir and Meowlnir both want synapse-http-antispam, which the playbook wires up to a single consumer. The wiring prefers Draupnir, and both roles fail the run when each claims it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
bed7bddf4a
commit
f9222dc70c
+119
-6
@@ -98,6 +98,8 @@ matrix_homeserver_container_extra_arguments_auto: |
|
||||
+
|
||||
(['--mount type=bind,src=' + matrix_appservice_draupnir_for_all_config_path + '/draupnir-for-all-registration.yaml,dst=/matrix-appservice-draupnir-for-all-registration.yaml,ro'] if matrix_appservice_draupnir_for_all_enabled else [])
|
||||
+
|
||||
(['--mount type=bind,src=' + matrix_bot_meowlnir_config_path + '/registration.yaml,dst=/matrix-bot-meowlnir-registration.yaml,ro'] if matrix_bot_meowlnir_enabled else [])
|
||||
+
|
||||
(['--mount type=bind,src=' + matrix_appservice_double_puppet_config_path + '/registration.yaml,dst=/matrix-appservice-double-puppet-registration.yaml,ro'] if matrix_appservice_double_puppet_enabled else [])
|
||||
+
|
||||
(['--mount type=bind,src=' + matrix_bridge_appservice_irc_config_path + '/registration.yaml,dst=/matrix-appservice-irc-registration.yaml,ro'] if matrix_bridge_appservice_irc_enabled else [])
|
||||
@@ -161,6 +163,8 @@ matrix_homeserver_app_service_config_files_auto: |
|
||||
+
|
||||
(['/matrix-appservice-draupnir-for-all-registration.yaml'] if matrix_appservice_draupnir_for_all_enabled else [])
|
||||
+
|
||||
(['/matrix-bot-meowlnir-registration.yaml'] if matrix_bot_meowlnir_enabled else [])
|
||||
+
|
||||
(['/matrix-appservice-double-puppet-registration.yaml'] if matrix_appservice_double_puppet_enabled else [])
|
||||
+
|
||||
(['/matrix-appservice-irc-registration.yaml'] if matrix_bridge_appservice_irc_enabled else [])
|
||||
@@ -357,6 +361,13 @@ devture_systemd_service_manager_services_list_auto: |
|
||||
'groups': ['matrix', 'bots', 'draupnir', 'bot-draupnir'],
|
||||
}] if matrix_bot_draupnir_enabled else [])
|
||||
+
|
||||
([{
|
||||
'name': 'matrix-bot-meowlnir.service',
|
||||
'priority': 4000,
|
||||
'restart_necessary': (matrix_bot_meowlnir_restart_necessary | bool),
|
||||
'groups': ['matrix', 'bots', 'meowlnir', 'bot-meowlnir'],
|
||||
}] if matrix_bot_meowlnir_enabled else [])
|
||||
+
|
||||
([{
|
||||
'name': 'matrix-appservice-discord.service',
|
||||
'priority': 2000,
|
||||
@@ -3350,6 +3361,91 @@ matrix_bot_draupnir_config_web_synapseHTTPAntispam_authorization: "{{ (matrix_ho
|
||||
######################################################################
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# matrix-bot-meowlnir
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# We don't enable bots by default.
|
||||
matrix_bot_meowlnir_enabled: false
|
||||
|
||||
matrix_bot_meowlnir_container_http_host_bind_port: "{{ (matrix_playbook_service_host_bind_interface_prefix ~ '8772') if matrix_playbook_service_host_bind_interface_prefix else '' }}"
|
||||
|
||||
matrix_bot_meowlnir_systemd_required_services_list_auto: |
|
||||
{{
|
||||
matrix_addons_homeserver_systemd_services_list
|
||||
+
|
||||
([postgres_identifier ~ '.service'] if (postgres_enabled and matrix_bot_meowlnir_database_hostname == postgres_connection_hostname) else [])
|
||||
}}
|
||||
|
||||
matrix_bot_meowlnir_container_image_registry_prefix_upstream: "{{ matrix_container_global_registry_prefix_override if matrix_container_global_registry_prefix_override else matrix_bot_meowlnir_container_image_registry_prefix_upstream_default }}"
|
||||
|
||||
matrix_bot_meowlnir_container_image_self_build: "{{ matrix_architecture not in ['amd64', 'arm64'] }}"
|
||||
|
||||
matrix_bot_meowlnir_container_network: "{{ matrix_addons_container_network }}"
|
||||
|
||||
matrix_bot_meowlnir_container_additional_networks_auto: |-
|
||||
{{
|
||||
(
|
||||
([] if matrix_addons_homeserver_container_network == '' else
|
||||
[matrix_addons_homeserver_container_network])
|
||||
+
|
||||
([matrix_playbook_reverse_proxyable_services_additional_network] if
|
||||
(matrix_playbook_reverse_proxyable_services_additional_network and matrix_bot_meowlnir_container_labels_traefik_enabled) else [])
|
||||
+
|
||||
([postgres_container_network] if (postgres_enabled and matrix_bot_meowlnir_database_hostname == postgres_connection_hostname and matrix_bot_meowlnir_container_network != postgres_container_network) else [])
|
||||
) | unique
|
||||
}}
|
||||
|
||||
matrix_bot_meowlnir_config_homeserver_address: "{{ matrix_addons_homeserver_client_api_url }}"
|
||||
matrix_bot_meowlnir_config_homeserver_domain: "{{ matrix_domain }}"
|
||||
|
||||
# Only consulted by bots configured with `management_room_auto_create`, and only as the
|
||||
# default for those which do not carry their own `initial_managers` list.
|
||||
# May legitimately be empty, in which case such bots fail validation and ask to be told who
|
||||
# their initial managers should be.
|
||||
matrix_bot_meowlnir_initial_managers: "{{ [matrix_admin] if matrix_admin else [] }}"
|
||||
|
||||
matrix_bot_meowlnir_appservice_token: "{{ (matrix_homeserver_generic_secret_key + ':meowlnir.as.token') | hash('sha512') | to_uuid }}"
|
||||
matrix_bot_meowlnir_homeserver_token: "{{ (matrix_homeserver_generic_secret_key + ':meowlnir.hs.token') | hash('sha512') | to_uuid }}"
|
||||
matrix_bot_meowlnir_config_meowlnir_management_secret: "{{ (matrix_homeserver_generic_secret_key + ':meowlnir.management') | hash('sha512') | to_uuid }}"
|
||||
matrix_bot_meowlnir_config_meowlnir_data_secret: "{{ (matrix_homeserver_generic_secret_key + ':meowlnir.data') | hash('sha512') | to_uuid }}"
|
||||
matrix_bot_meowlnir_config_antispam_secret: "{{ (matrix_homeserver_generic_secret_key + ':meowlnir.antispam') | hash('sha512') | to_uuid }}"
|
||||
|
||||
# Meowlnir expects a Synapse-style ed25519 private key: `<algorithm> <key ID> <unpadded-base64 32-byte seed>`.
|
||||
#
|
||||
# Only the seed is stored in this format — Meowlnir derives the actual keypair from it
|
||||
# via `ed25519.NewKeyFromSeed`, so no elliptic curve arithmetic happens here. The 32
|
||||
# hexadecimal characters sliced out of the hash below serve as the seed's 32 bytes.
|
||||
#
|
||||
# The key ID is cosmetic: Meowlnir always signs with the hardcoded `ed25519:policy_server`
|
||||
# (see `PolicyServerKeyID` upstream), so we use a matching name to avoid confusion.
|
||||
#
|
||||
# Note that slicing hex text gives the seed 128 bits of entropy, not a full 256.
|
||||
# That matches ed25519's own security level, so it is not a practical weakness, but you can
|
||||
# override this variable with an independently generated key if you would prefer one.
|
||||
matrix_bot_meowlnir_config_policy_server_signing_key: "ed25519 policy_server {{ ((matrix_homeserver_generic_secret_key + ':meowlnir.policy_server.signing_key') | hash('sha512'))[:32] | b64encode | regex_replace('=+$', '') }}"
|
||||
|
||||
matrix_bot_meowlnir_database_hostname: "{{ postgres_connection_hostname if postgres_enabled else '' }}"
|
||||
matrix_bot_meowlnir_database_password: "{{ (matrix_homeserver_generic_secret_key + ':bot.meowlnir.db') | hash('sha512') | to_uuid }}"
|
||||
|
||||
matrix_bot_meowlnir_synapse_database_uri: "{{ ('postgresql://' + matrix_synapse_database_user + ':' + matrix_synapse_database_password + '@' + matrix_synapse_database_host + ':' + (matrix_synapse_database_port | string) + '/' + matrix_synapse_database_database + '?sslmode=disable') if (matrix_bot_meowlnir_synapse_database_integration_enabled and matrix_synapse_enabled) else '' }}"
|
||||
|
||||
matrix_bot_meowlnir_container_labels_traefik_enabled: "{{ (matrix_bot_meowlnir_config_reporting_enabled or matrix_bot_meowlnir_policy_server_enabled) and matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] }}"
|
||||
matrix_bot_meowlnir_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}"
|
||||
matrix_bot_meowlnir_container_labels_reporting_traefik_entrypoints: "{{ traefik_entrypoint_primary }}"
|
||||
matrix_bot_meowlnir_container_labels_reporting_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}" # noqa var-naming
|
||||
matrix_bot_meowlnir_container_labels_policy_server_traefik_entrypoints: "{{ traefik_entrypoint_primary }}"
|
||||
matrix_bot_meowlnir_container_labels_policy_server_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}" # noqa var-naming
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# /matrix-bot-meowlnir
|
||||
#
|
||||
######################################################################
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# matrix-appservice-draupnir-for-all
|
||||
@@ -4226,6 +4322,12 @@ postgres_managed_databases_auto: |
|
||||
'password': matrix_appservice_draupnir_for_all_database_password,
|
||||
}] if (matrix_appservice_draupnir_for_all_enabled and matrix_appservice_draupnir_for_all_database_hostname == postgres_connection_hostname) else [])
|
||||
+
|
||||
([{
|
||||
'name': matrix_bot_meowlnir_database_name,
|
||||
'username': matrix_bot_meowlnir_database_username,
|
||||
'password': matrix_bot_meowlnir_database_password,
|
||||
}] if (matrix_bot_meowlnir_enabled and matrix_bot_meowlnir_database_engine == 'postgres' and matrix_bot_meowlnir_database_hostname == postgres_connection_hostname) else [])
|
||||
+
|
||||
([{
|
||||
'name': matrix_bridge_appservice_irc_database_name,
|
||||
'username': matrix_bridge_appservice_irc_database_username,
|
||||
@@ -5023,12 +5125,18 @@ matrix_synapse_app_service_config_files_auto: "{{ matrix_homeserver_app_service_
|
||||
# Disable creation of media repository Synapse worker when using media-repo
|
||||
matrix_synapse_ext_media_repo_enabled: "{{ matrix_media_repo_enabled }}"
|
||||
|
||||
matrix_synapse_ext_synapse_http_antispam_enabled: "{{ matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_base_url: "{{ matrix_bot_draupnir_synapse_http_antispam_config_base_url if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else '' }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_authorization: "{{ matrix_bot_draupnir_config_web_synapseHTTPAntispam_authorization if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else '' }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_enabled_callbacks: "{{ matrix_bot_draupnir_synapse_http_antispam_config_enabled_callbacks if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else [] }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_fail_open: "{{ matrix_bot_draupnir_synapse_http_antispam_config_fail_open if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else {} }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_async: "{{ matrix_bot_draupnir_synapse_http_antispam_config_async if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else {} }}"
|
||||
# The synapse-http-antispam module reports to a single consumer, so at most one of
|
||||
# Draupnir and Meowlnir may claim it. Each role's validation fails the run if both do.
|
||||
matrix_synapse_ext_synapse_http_antispam_enabled: "{{ matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled or matrix_bot_meowlnir_synapse_http_antispam_enabled }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_base_url: "{{ matrix_bot_draupnir_synapse_http_antispam_config_base_url if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else (matrix_bot_meowlnir_synapse_http_antispam_config_base_url if matrix_bot_meowlnir_synapse_http_antispam_enabled else '') }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_authorization: "{{ matrix_bot_draupnir_config_web_synapseHTTPAntispam_authorization if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else (matrix_bot_meowlnir_config_antispam_secret if matrix_bot_meowlnir_synapse_http_antispam_enabled else '') }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_enabled_callbacks: "{{ matrix_bot_draupnir_synapse_http_antispam_config_enabled_callbacks if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else (matrix_bot_meowlnir_synapse_http_antispam_config_enabled_callbacks if matrix_bot_meowlnir_synapse_http_antispam_enabled else []) }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_fail_open: "{{ matrix_bot_draupnir_synapse_http_antispam_config_fail_open if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else (matrix_bot_meowlnir_synapse_http_antispam_config_fail_open if matrix_bot_meowlnir_synapse_http_antispam_enabled else {}) }}"
|
||||
matrix_synapse_ext_synapse_http_antispam_config_async: "{{ matrix_bot_draupnir_synapse_http_antispam_config_async if matrix_bot_draupnir_config_web_synapseHTTPAntispam_enabled else (matrix_bot_meowlnir_synapse_http_antispam_config_async if matrix_bot_meowlnir_synapse_http_antispam_enabled else {}) }}"
|
||||
|
||||
# Meowlnir's bots need these to support end-to-end encryption.
|
||||
matrix_synapse_experimental_features_msc2409_to_device_messages_enabled: "{{ matrix_bot_meowlnir_enabled and matrix_bot_meowlnir_config_encryption_enable }}"
|
||||
matrix_synapse_experimental_features_msc3202_transaction_extensions_enabled: "{{ matrix_bot_meowlnir_enabled and matrix_bot_meowlnir_config_encryption_enable }}"
|
||||
|
||||
# Enable Synapse statistics reporting when using synapse-usage-exporter
|
||||
matrix_synapse_report_stats: "{{ matrix_synapse_usage_exporter_enabled }}"
|
||||
@@ -5171,6 +5279,11 @@ matrix_ketesa_config_asManagedUsers_auto: |
|
||||
'^@'+(matrix_appservice_draupnir_for_all_user_prefix | default('') | regex_escape) +'_[a-zA-Z0-9]+:'+(matrix_domain | regex_escape)+'$',
|
||||
] if matrix_appservice_draupnir_for_all_enabled else [])
|
||||
+
|
||||
([
|
||||
matrix_bot_meowlnir_user_regex,
|
||||
matrix_bot_meowlnir_appservice_sender_regex,
|
||||
] if matrix_bot_meowlnir_enabled else [])
|
||||
+
|
||||
([
|
||||
'^@'+(matrix_bot_baibot_config_user_mxid_localpart | default('') | regex_escape) +':'+(matrix_domain | regex_escape)+'$',
|
||||
] if matrix_bot_baibot_enabled else [])
|
||||
|
||||
Reference in New Issue
Block a user