From 4af35777b32e82b5579a5778c0281a7608df85a4 Mon Sep 17 00:00:00 2001 From: Catalan Lover <48515417+FSG-Cat@users.noreply.github.com> Date: Thu, 7 May 2026 15:59:53 +0200 Subject: [PATCH] Update Draupnir from 3.0.0 to 3.1.0 and introduce Zero Touch Deployment to mdad. (#5205) --- ...ng-playbook-appservice-draupnir-for-all.md | 57 ++++++++++++++----- docs/configuring-playbook-bot-draupnir.md | 57 ++++++++++++++++--- ...ng-playbook-appservice-draupnir-for-all.po | 2 +- ...ng-playbook-appservice-draupnir-for-all.po | 2 +- .../defaults/main.yml | 24 +++++++- .../tasks/setup_install.yml | 2 +- .../tasks/validate_config.yml | 21 +++++-- .../templates/production-appservice.yaml.j2 | 8 ++- .../matrix-bot-draupnir/defaults/main.yml | 30 +++++++++- .../tasks/validate_config.yml | 7 ++- .../templates/production.yaml.j2 | 8 +++ 11 files changed, 177 insertions(+), 41 deletions(-) diff --git a/docs/configuring-playbook-appservice-draupnir-for-all.md b/docs/configuring-playbook-appservice-draupnir-for-all.md index 36e85eafd..fce711584 100644 --- a/docs/configuring-playbook-appservice-draupnir-for-all.md +++ b/docs/configuring-playbook-appservice-draupnir-for-all.md @@ -1,4 +1,5 @@ +```yaml +matrix_bot_draupnir_configuration_extension_yaml: | + pollReports: true +``` ### Extending the configuration diff --git a/i18n/locales/bg/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po b/i18n/locales/bg/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po index cf34a967b..b83ed0435 100644 --- a/i18n/locales/bg/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po +++ b/i18n/locales/bg/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po @@ -163,7 +163,7 @@ msgid "Granting Users the ability to use D4A" msgstr "" #: ../../../docs/configuring-playbook-appservice-draupnir-for-all.md:97 -msgid "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` recomendation. Using the chat is recomended." +msgid "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` recomendation. Using the chat is recommended." msgstr "" #: ../../../docs/configuring-playbook-appservice-draupnir-for-all.md:99 diff --git a/i18n/locales/jp/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po b/i18n/locales/jp/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po index 6aa8af195..7e8355a4a 100644 --- a/i18n/locales/jp/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po +++ b/i18n/locales/jp/LC_MESSAGES/docs/configuring-playbook-appservice-draupnir-for-all.po @@ -162,7 +162,7 @@ msgid "Granting Users the ability to use D4A" msgstr "" #: ../../../docs/configuring-playbook-appservice-draupnir-for-all.md:97 -msgid "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` recomendation. Using the chat is recomended." +msgid "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` recomendation. Using the chat is recommended." msgstr "" #: ../../../docs/configuring-playbook-appservice-draupnir-for-all.md:99 diff --git a/roles/custom/matrix-appservice-draupnir-for-all/defaults/main.yml b/roles/custom/matrix-appservice-draupnir-for-all/defaults/main.yml index 196992e51..2c8893f87 100644 --- a/roles/custom/matrix-appservice-draupnir-for-all/defaults/main.yml +++ b/roles/custom/matrix-appservice-draupnir-for-all/defaults/main.yml @@ -12,7 +12,7 @@ matrix_appservice_draupnir_for_all_enabled: true # renovate: datasource=docker depName=depName=ghcr.io/the-draupnir-project/draupnir -matrix_appservice_draupnir_for_all_version: "v3.0.0" +matrix_appservice_draupnir_for_all_version: "v3.1.0" matrix_appservice_draupnir_for_all_container_image_self_build: false matrix_appservice_draupnir_for_all_container_image_self_build_repo: "https://github.com/the-draupnir-project/Draupnir.git" @@ -58,14 +58,34 @@ matrix_appservice_draupnir_for_all_force_restart: "{{ matrix_appservice_draupnir_for_all_rolling_tag | bool }}" +# This controls whether Zero Touch Deployment is enabled. +# When enabled, the playbook validates the related settings and only renders +# the configuration values Draupnir expects for this mode. +# This prevents invalid manual combinations from being passed through, since +# Draupnir requires `matrix_appservice_draupnir_for_all_config_adminRoom` to be +# unset and `matrix_appservice_draupnir_for_all_config_initialManager` to be a +# valid user ID. +# Zero Touch Deployment is recommended for all new deployments. +# Deployments that are exempt from this recommendation are assumed to be +# advanced setups with specific needs that require the flexibility of +# non-zero-touch-deployment mode. +# Note that enabling this on an existing deployment will cause the bot to recreate the admin room. +# Manual policy migration has to be done in that case so as not to break when access controls return to working order. +matrix_appservice_draupnir_for_all_zero_touch_deploy: 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 - not a matrix.to URL. -# Note: Draupnir is fairly verbose - expect a lot of messages from it. +# Appservice mode, unlike bot mode, is not verbose in the admin room. # This room is different for Appservice Mode compared to normal mode. # In Appservice mode it provides functions like user management. matrix_appservice_draupnir_for_all_config_adminRoom: "" # noqa var-naming +# This controls the MXID of who is invited to the admin room on its creation when using Zero Touch Deployment. +# This value is mutually exclusive with matrix_appservice_draupnir_for_all_config_adminRoom +# and the bot will crash if you attempt to set both at the same time. +matrix_appservice_draupnir_for_all_config_initialManager: "" # noqa var-naming + # Controls if the room state backing store is activated. # Room state backing store makes restarts of the bot lightning fast as the bot does not suffer from amnesia. # This config option has diminished improvements for bots on extremely fast homeservers or very very small bots on fast homeservers. diff --git a/roles/custom/matrix-appservice-draupnir-for-all/tasks/setup_install.yml b/roles/custom/matrix-appservice-draupnir-for-all/tasks/setup_install.yml index b594d30ba..7c9d582e7 100644 --- a/roles/custom/matrix-appservice-draupnir-for-all/tasks/setup_install.yml +++ b/roles/custom/matrix-appservice-draupnir-for-all/tasks/setup_install.yml @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: 2024 David Mehren # SPDX-FileCopyrightText: 2024 MDAD project contributors -# SPDX-FileCopyrightText: 2024 Catalan Lover +# SPDX-FileCopyrightText: 2024 - 2026 Catalan Lover # SPDX-FileCopyrightText: 2024 Slavi Pantaleev # SPDX-FileCopyrightText: 2024 Suguru Hirahara # diff --git a/roles/custom/matrix-appservice-draupnir-for-all/tasks/validate_config.yml b/roles/custom/matrix-appservice-draupnir-for-all/tasks/validate_config.yml index fcd406246..6383b6487 100644 --- a/roles/custom/matrix-appservice-draupnir-for-all/tasks/validate_config.yml +++ b/roles/custom/matrix-appservice-draupnir-for-all/tasks/validate_config.yml @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2024 MDAD project contributors -# SPDX-FileCopyrightText: 2024 Catalan Lover +# SPDX-FileCopyrightText: 2024 - 2026 Catalan Lover # SPDX-FileCopyrightText: 2024 Slavi Pantaleev # SPDX-FileCopyrightText: 2025 Suguru Hirahara # @@ -25,10 +25,19 @@ - {'old': 'matrix_appservice_draupnir_for_all_docker_src_files_path', 'new': 'matrix_appservice_draupnir_for_all_container_src_files_path'} - {'old': 'matrix_appservice_draupnir_for_all_container_image_force_pull', 'new': ' (No longer needed due to new docker module doing this natively only if needed.)'} -- name: Fail if required matrix-bot-draupnir variables are undefined +- name: Fail if required matrix-appservice-draupnir-for-all variables are undefined ansible.builtin.fail: - msg: "The `{{ item }}` variable must be defined and have a non-null value." + msg: "The `{{ item.name }}` variable must be defined and have a non-null value." with_items: - - "matrix_appservice_draupnir_for_all_config_adminRoom" - - "matrix_bot_draupnir_container_network" - when: "lookup('vars', item, default='') == '' or lookup('vars', item, default='') is none" + - {'name': 'matrix_appservice_draupnir_for_all_config_adminRoom', when: "{{ not matrix_appservice_draupnir_for_all_zero_touch_deploy }}"} + - {'name': 'matrix_appservice_draupnir_for_all_config_initialManager', when: "{{ matrix_appservice_draupnir_for_all_zero_touch_deploy }}"} + - {'name': 'matrix_appservice_draupnir_for_all_container_network', when: true} + when: "item.when | bool and (lookup('vars', item.name, default='') == '' or lookup('vars', item.name, default='') is none)" + +- name: Fail if inappropriate variables are defined + ansible.builtin.fail: + msg: "The `{{ item.name }}` variable must be undefined or have a null value." + with_items: + - {'name': 'matrix_appservice_draupnir_for_all_config_adminRoom', when: "{{ matrix_appservice_draupnir_for_all_zero_touch_deploy }}"} + - {'name': 'matrix_appservice_draupnir_for_all_config_initialManager', when: "{{ not matrix_appservice_draupnir_for_all_zero_touch_deploy }}"} + when: "item.when | bool and not (lookup('vars', item.name, default='') == '' or lookup('vars', item.name, default='') is none)" diff --git a/roles/custom/matrix-appservice-draupnir-for-all/templates/production-appservice.yaml.j2 b/roles/custom/matrix-appservice-draupnir-for-all/templates/production-appservice.yaml.j2 index 019c7ac79..38bce59b9 100644 --- a/roles/custom/matrix-appservice-draupnir-for-all/templates/production-appservice.yaml.j2 +++ b/roles/custom/matrix-appservice-draupnir-for-all/templates/production-appservice.yaml.j2 @@ -17,9 +17,16 @@ db: engine: "postgres" connectionString: "{{ matrix_appservice_draupnir_for_all_database_connection_string }}" +{% if not matrix_appservice_draupnir_for_all_zero_touch_deploy %} # A room you have created that scopes who can access the appservice. # See docs/access_control.md adminRoom: {{ matrix_appservice_draupnir_for_all_config_adminRoom | to_json }} +{% endif %} + +{% if matrix_appservice_draupnir_for_all_zero_touch_deploy %} +# The initial manager to invite if the admin room has to be created. +initialManager: {{ matrix_appservice_draupnir_for_all_config_initialManager | to_json }} +{% endif %} # This is a web api that the widget connects to in order to interact with the appservice. webAPI: @@ -37,6 +44,5 @@ maxDraupnirsPerUser: 1 # Defaults to false when omitted. allowSelfServiceProvisioning: false - roomStateBackingStore: enabled: {{ matrix_appservice_draupnir_for_all_config_roomStateBackingStore_enabled | to_json }} diff --git a/roles/custom/matrix-bot-draupnir/defaults/main.yml b/roles/custom/matrix-bot-draupnir/defaults/main.yml index 465a935d9..7e8184c56 100644 --- a/roles/custom/matrix-bot-draupnir/defaults/main.yml +++ b/roles/custom/matrix-bot-draupnir/defaults/main.yml @@ -12,7 +12,7 @@ matrix_bot_draupnir_enabled: true # renovate: datasource=docker depName=depName=ghcr.io/the-draupnir-project/draupnir -matrix_bot_draupnir_version: "v3.0.0" +matrix_bot_draupnir_version: "v3.1.0" matrix_bot_draupnir_container_image_self_build: false matrix_bot_draupnir_container_image_self_build_repo: "https://github.com/the-draupnir-project/Draupnir.git" @@ -115,12 +115,36 @@ matrix_bot_draupnir_password: "{{ matrix_bot_draupnir_pantalaimon_password }}" # This configuration option does not follow the common naming schema as its not controlling a config key directly. matrix_bot_draupnir_login_native: 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 controls whether Zero Touch Deployment is enabled. +# When enabled, the playbook validates the settings and only +# renders the configuration values Draupnir expects. +# This prevents invalid manual combinations from being passed through, since +# Draupnir requires `matrix_bot_draupnir_config_managementRoom` to be unset and +# `matrix_bot_draupnir_config_initialManager` to be a valid MXID. +# Zero Touch Deployment is recommended for all new deployments. +# Deployments that are exempt from this recommendation are assumed to be +# advanced setups with specific needs for non-zero-touch mode. +# Note that enabling this on an existing deployment will cause the bot to +# recreate the management room. +# Recreating the management room will cause all protections to reset their settings to defaults +# and cause the recreation of secondary rooms like notification rooms. All bot memory will also be wiped. +matrix_bot_draupnir_zero_touch_deploy: false + +# The management room used for administration when Zero Touch +# Deployment is disabled. +# The bot has no access controls, so anyone in this room can use it - secure +# your room! # This should be a room alias or room ID - not a matrix.to URL. # Note: Draupnir is fairly verbose - expect a lot of messages from it. matrix_bot_draupnir_config_managementRoom: "" # noqa var-naming +# The MXID invited as the initial manager when Zero Touch Deployment creates the +# management room. +# This value is mutually exclusive with +# `matrix_bot_draupnir_config_managementRoom`, and the bot will crash if you +# attempt to set both at the same time. +matrix_bot_draupnir_config_initialManager: "" # noqa var-naming + # Endpoint URL that Draupnir uses to interact with the Matrix homeserver (client-server API). # Set this to the Pantalaimon URL if you're using that. matrix_bot_draupnir_config_homeserverUrl: "" # noqa var-naming diff --git a/roles/custom/matrix-bot-draupnir/tasks/validate_config.yml b/roles/custom/matrix-bot-draupnir/tasks/validate_config.yml index 7bc402fc2..df499d680 100644 --- a/roles/custom/matrix-bot-draupnir/tasks/validate_config.yml +++ b/roles/custom/matrix-bot-draupnir/tasks/validate_config.yml @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 - 2025 MDAD project contributors -# SPDX-FileCopyrightText: 2023 - 2025 Catalan Lover +# SPDX-FileCopyrightText: 2023 - 2026 Catalan Lover # SPDX-FileCopyrightText: 2024 - 2025 Slavi Pantaleev # # SPDX-License-Identifier: AGPL-3.0-or-later @@ -45,7 +45,8 @@ with_items: - {'name': 'matrix_bot_draupnir_config_accessToken', when: "{{ not matrix_bot_draupnir_pantalaimon_use and not matrix_bot_draupnir_login_native }}"} - {'name': 'matrix_bot_draupnir_config_accessToken', when: "{{ matrix_bot_draupnir_config_experimentalRustCrypto }}"} - - {'name': 'matrix_bot_draupnir_config_managementRoom', when: true} + - {'name': 'matrix_bot_draupnir_config_managementRoom', when: "{{ not matrix_bot_draupnir_zero_touch_deploy }}"} + - {'name': 'matrix_bot_draupnir_config_initialManager', when: "{{ matrix_bot_draupnir_zero_touch_deploy }}"} - {'name': 'matrix_bot_draupnir_container_network', when: true} - {'name': 'matrix_bot_draupnir_config_homeserverUrl', when: true} - {'name': 'matrix_bot_draupnir_config_rawHomeserverUrl', when: true} @@ -64,6 +65,8 @@ with_items: - {'name': 'matrix_bot_draupnir_config_accessToken', when: "{{ matrix_bot_draupnir_pantalaimon_use }}"} - {'name': 'matrix_bot_draupnir_config_accessToken', when: "{{ matrix_bot_draupnir_login_native }}"} + - {'name': 'matrix_bot_draupnir_config_managementRoom', when: "{{ matrix_bot_draupnir_zero_touch_deploy }}"} + - {'name': 'matrix_bot_draupnir_config_initialManager', when: "{{ not matrix_bot_draupnir_zero_touch_deploy }}"} when: "item.when | bool and not (lookup('vars', item.name, default='') == '' or lookup('vars', item.name, default='') is none)" - name: Fail when matrix_bot_draupnir_config_experimentalRustCrypto is enabled together with matrix_bot_draupnir_pantalaimon_use diff --git a/roles/custom/matrix-bot-draupnir/templates/production.yaml.j2 b/roles/custom/matrix-bot-draupnir/templates/production.yaml.j2 index f0f24cd1c..e700ba118 100644 --- a/roles/custom/matrix-bot-draupnir/templates/production.yaml.j2 +++ b/roles/custom/matrix-bot-draupnir/templates/production.yaml.j2 @@ -63,6 +63,7 @@ autojoinOnlyIfManager: true # Whether Draupnir should report ignored invites to the management room (if autojoinOnlyIfManager is true). recordIgnoredInvites: false +{% if not matrix_bot_draupnir_zero_touch_deploy %} # The room ID (or room alias) of the management room, anyone in this room can issue commands to Draupnir. # # Draupnir has no more granular access controls other than this, be sure you trust everyone in this room - secure it! @@ -72,6 +73,13 @@ recordIgnoredInvites: false # Note: By default, Draupnir is fairly verbose - expect a lot of messages in this room. # (see verboseLogging to adjust this a bit.) managementRoom: {{ matrix_bot_draupnir_config_managementRoom | to_json }} +{% endif %} + +{% if matrix_bot_draupnir_zero_touch_deploy %} +# The initial manager to invite if the management room has to be created. +# Leave this commented out when using a pre-existing management room. +initialManager: {{ matrix_bot_draupnir_config_initialManager | to_json }} +{% endif %} # The log level of terminal (or container) output, # can be one of DEBUG, INFO, WARN and ERROR, in increasing order of importance and severity.