diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d3bec193..0011dac45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # 2024-07-06 +## matrix-alertmanager-receiver support + +For those wishing to more easily integrate [Prometheus](https://prometheus.io/)' alerting service ([Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/)) with Matrix, the playbook can now set up [matrix-alertmanager-receiver](https://github.com/metio/matrix-alertmanager-receiver). + +See [Setting up Prometheus Alertmanager integration via matrix-alertmanager-receiver](./docs/configuring-playbook-alertmanager-receiver.md) for more details. + + ## Traefik v3 and HTTP/3 are here now **TLDR**: Traefik was migrated from v2 to v3. Minor changes were done to the playbook. Mostly everything else worked out of the box. Most people will not have to do any tweaks to their configuration. In addition, [HTTP/3](https://en.wikipedia.org/wiki/HTTP/3) support is now auto-enabled for the `web-secure` (port 443) and `matrix-federation` (port `8448`) entrypoints. If you have a firewall in front of your server and you wish to benefit from `HTTP3`, you will need to open the `443` and `8448` UDP ports in it. diff --git a/docs/configuring-playbook-alertmanager-receiver.md b/docs/configuring-playbook-alertmanager-receiver.md new file mode 100644 index 000000000..f85facefe --- /dev/null +++ b/docs/configuring-playbook-alertmanager-receiver.md @@ -0,0 +1,93 @@ +# Setting up matrix-alertmanager-receiver (optional) + +The playbook can install and configure the [matrix-alertmanager-receiver](https://github.com/metio/matrix-alertmanager-receiver) service for you. It's a [client](https://prometheus.io/docs/alerting/latest/clients/) for Prometheus' [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/), allowing you to deliver alerts to Matrix rooms. + +See the project's [documentation](https://github.com/metio/matrix-alertmanager-receiver) to learn more about what this component does and why it might be useful to you. + +At the moment, **setting up this service's bot requires some manual actions** as described below in [Account and room preparation](#account-and-room-preparation). + +This service is meant to be used with an external [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) instance. It's **not** meant to be integrated with the [Prometheus & Grafana stack](./configuring-playbook-prometheus-grafana.md) installed by this playbook, because the Alertmanager component is not installed by it. + + +## Configuration + +```yml +matrix_alertmanager_receiver_enabled: true + +# This exposes matrix-alertmanager-receiver on the `matrix.` domain. +# Adjust, if necessary. +matrix_alertmanager_receiver_hostname: "{{ matrix_server_fqn_matrix }}" + +# This exposes matrix-alertmanager-receiver under a path prefix containing a random (secret) value. +# Adjust the `RANDOM_VALUE_HERE` part with a long and secure value. +matrix_alertmanager_receiver_path_prefix: /matrix-alertmanager-receiver-RANDOM_VALUE_HERE + +# If you'd like to change the username for this bot, uncomment and adjust. Otherwise, remove. +# matrix_alertmanager_receiver_config_matrix_user_id_localpart: "bot.alertmanager.receiver" + +# Specify the bot user's access token here. +# See the "Account and room preparation" section below. +matrix_alertmanager_receiver_config_matrix_access_token: '' + +# Optionally, configure some mappings (URL-friendly room name -> actual Matrix room ID). +# +# If you don't configure mappings, you can still deliver alerts using URLs like this: +# https://matrix.DOMAIN/matrix-alertmanager-receiver-RANDOM_VALUE_HERE/alert/!some-room-id:example.com +# +# If a mapping like the one below is configured, you can deliver alerts using friendlier URLs like this: +# https://matrix.DOMAIN/matrix-alertmanager-receiver-RANDOM_VALUE_HERE/alert/some-room-name +matrix_alertmanager_receiver_config_matrix_room_mapping: + some-room-name: "!some-room-id:{{ matrix_domain }}" +``` + +See `roles/custom/matrix-alertmanager-receiver/defaults/main.yml` for additional configuration variables. + + +## Account and room preparation + +The playbook can automatically create users, but it cannot automatically obtain access tokens, nor perform any of the other manual actions below. + +`matrix-alertmanager-receiver` uses a bot (with a username specified in `matrix_alertmanager_receiver_config_matrix_user_id_localpart` - see above) for delivering messages. You need to **manually register this bot acccount and obtain an access token for it**. + +1. [Register a new user](registering-users.md): `ansible-playbook -i inventory/hosts setup.yml --extra-vars='username=bot.alertmanager.receiver password=PASSWORD_FOR_THE_BOT admin=no' --tags=register-user` +2. [Obtain an access token](obtaining-access-tokens.md) for the bot's user account +3. Invite the bot to a room where you'd like to alerts to be delivered +4. Log in as the bot using any Matrix client of your choosing, accept the room invitation from the bot's account and log out +5. (Optionally) Adjust `matrix_alertmanager_receiver_config_matrix_room_mapping` to create a mapping between the new room and its id + +Steps 1 and 2 above only need to be done once, while preparing your [configuration](#configuration). + +Steps 3 and 4 need to be done for each new room you'd like the bot to deliver alerts to. Step 5 is optional and provides cleaner `/alert/` URLs. + + +## Installation + +Now that you've [prepared the bot account and room](#account-and-room-preparation) and have [configured the playbook](#configuration), you can re-run the [installation](./installing.md) process (`just install-all`). + +Then, you can proceed to [Usage](#usage). + + +## Usage + +Configure your Prometheus Alertmanager with configuration like this: + +```yml + receivers: + - name: matrix + webhook_configs: + - send_resolved: true + url: URL_HERE + route: + group_by: + - namespace + group_interval: 5m + group_wait: 30s + receiver: "matrix" + repeat_interval: 12h + routes: + - receiver: matrix +``` + +.. where `URL_HERE` looks like `https://matrix.DOMAIN/matrix-alertmanager-receiver-RANDOM_VALUE_HERE/alert/some-room-name` or `https://matrix.DOMAIN/matrix-alertmanager-receiver-RANDOM_VALUE_HERE/alert/!some-room-id:DOMAIN`. + +This bot does **not** accept room invitations automatically (like many other bots do). To deliver messages to rooms, **the bot must be joined to all rooms manually** - see Step 5 of the [Account and room preparation](#account-and-room-preparation) section. diff --git a/docs/configuring-playbook.md b/docs/configuring-playbook.md index 708367083..64c47fbe6 100644 --- a/docs/configuring-playbook.md +++ b/docs/configuring-playbook.md @@ -224,3 +224,5 @@ When you're done with all the configuration you'd like to do, continue with [Ins - [Setting up a Cactus Comments server](configuring-playbook-cactus-comments.md) - a federated comment system built on Matrix (optional) - [Setting up the Rageshake bug report server](configuring-playbook-rageshake.md) (optional) + +- [Setting up Prometheus Alertmanager integration via matrix-alertmanager-receiver](configuring-playbook-alertmanager-receiver.md) (optional) diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index bd851c675..3746d26cc 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -267,6 +267,8 @@ devture_systemd_service_manager_services_list_auto: | {{ ([{'name': (backup_borg_identifier + '.timer'), 'priority': 5000, 'groups': ['matrix', 'backup', 'borg']}] if backup_borg_enabled else []) + + ([{'name': 'matrix-alertmanager-receiver.service', 'priority': 2200, 'groups': ['matrix', 'alertmanager-receiver']}] if matrix_alertmanager_receiver_enabled else []) + + ([{'name': 'matrix-bot-buscarron.service', 'priority': 2200, 'groups': ['matrix', 'bots', 'buscarron', 'bot-buscarron']}] if matrix_bot_buscarron_enabled else []) + ([{'name': 'matrix-bot-go-neb.service', 'priority': 2200, 'groups': ['matrix', 'bots', 'go-neb', 'bot-go-neb']}] if matrix_bot_go_neb_enabled else []) @@ -558,6 +560,54 @@ matrix_integration_manager_ui_url: "{{ matrix_dimension_integrations_ui_url if m ###################################################################### +###################################################################### +# +# matrix-alertmanager-receiver +# +###################################################################### + +# We don't enable this by default. +matrix_alertmanager_receiver_enabled: false + +matrix_alertmanager_receiver_container_image_self_build: "{{ matrix_architecture != 'amd64' }}" + +matrix_alertmanager_receiver_container_network: "{{ matrix_addons_container_network }}" + +matrix_alertmanager_receiver_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_alertmanager_receiver_container_labels_traefik_enabled) else []) + ) | unique + }} + +matrix_alertmanager_receiver_container_labels_traefik_enabled: "{{ matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] }}" +matrix_alertmanager_receiver_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}" +matrix_alertmanager_receiver_container_labels_traefik_entrypoints: "{{ devture_traefik_entrypoint_primary }}" +matrix_alertmanager_receiver_container_labels_traefik_tls_certResolver: "{{ devture_traefik_certResolver_primary }}" + +matrix_alertmanager_receiver_container_labels_metrics_middleware_basic_auth_enabled: "{{ matrix_metrics_exposure_http_basic_auth_enabled }}" +matrix_alertmanager_receiver_container_labels_metrics_middleware_basic_auth_users: "{{ matrix_metrics_exposure_http_basic_auth_users }}" + +matrix_alertmanager_receiver_systemd_required_services_list_auto: "{{ matrix_addons_homeserver_systemd_services_list }}" + +matrix_alertmanager_receiver_config_matrix_homeserver_url: "{{ matrix_addons_homeserver_client_api_url }}" + +matrix_alertmanager_receiver_metrics_enabled: "{{ prometheus_enabled or matrix_metrics_exposure_enabled }}" + +matrix_alertmanager_receiver_metrics_proxying_enabled: "{{ matrix_alertmanager_receiver_config_http_metrics_enabled and matrix_metrics_exposure_enabled }}" +matrix_alertmanager_receiver_metrics_proxying_hostname: "{{ matrix_metrics_exposure_hostname }}" +matrix_alertmanager_receiver_metrics_proxying_path: "{{ matrix_metrics_exposure_path_prefix }}/matrix-alertmanager-receiver" + +###################################################################### +# +# /matrix-alertmanager-receiver +# +###################################################################### + + + ###################################################################### # # matrix-bridge-appservice-discord diff --git a/roles/custom/matrix-alertmanager-receiver/defaults/main.yml b/roles/custom/matrix-alertmanager-receiver/defaults/main.yml new file mode 100644 index 000000000..d802c9c77 --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/defaults/main.yml @@ -0,0 +1,236 @@ +--- + +# matrix-alertmanager-receiver is a service which receives webhook payloads from Prometheus' Alertmanager and forwards them to a Matrix room. +# Project source code URL: https://github.com/metio/matrix-alertmanager-receiver + +matrix_alertmanager_receiver_enabled: true + +# renovate: datasource=docker depName=docker.io/metio/matrix-alertmanager-receiver +matrix_alertmanager_receiver_version: 2024.7.3 + +matrix_alertmanager_receiver_scheme: https + +# The hostname at which matrix-alertmanager-receiver is served. +matrix_alertmanager_receiver_hostname: '' + +# The path at which matrix-alertmanager-receiver is served. +# This value must either be `/` or not end with a slash (e.g. `/matrix-alertmanager-receiver`). +matrix_alertmanager_receiver_path_prefix: / + +matrix_alertmanager_receiver_base_path: "{{ matrix_base_data_path }}/alertmanager-receiver" +matrix_alertmanager_receiver_config_path: "{{ matrix_alertmanager_receiver_base_path }}/config" + +matrix_alertmanager_receiver_container_image_self_build: false +matrix_alertmanager_receiver_container_image_self_build_repo: https://github.com/metio/matrix-alertmanager-receiver +matrix_alertmanager_receiver_container_image_self_build_repo_version: "{{ 'main' if matrix_alertmanager_receiver_version == 'main' else matrix_alertmanager_receiver_version }}" +matrix_alertmanager_receiver_container_src_path: "{{ matrix_alertmanager_receiver_base_path }}/container-src" + +matrix_alertmanager_receiver_container_image: "{{ matrix_alertmanager_receiver_container_image_name_prefix }}metio/matrix-alertmanager-receiver:{{ matrix_alertmanager_receiver_container_image_tag }}" +matrix_alertmanager_receiver_container_image_name_prefix: "{{ 'localhost/' if matrix_alertmanager_receiver_container_image_self_build else matrix_alertmanager_receiver_container_image_registry_prefix }}" +matrix_alertmanager_receiver_container_image_tag: "{{ matrix_alertmanager_receiver_version }}" +matrix_alertmanager_receiver_container_image_force_pull: "{{ matrix_alertmanager_receiver_container_image.endswith(':main') }}" +matrix_alertmanager_receiver_container_image_registry_prefix: docker.io/ + +# The base container network. It will be auto-created by this role if it doesn't exist already. +matrix_alertmanager_receiver_container_network: '' + +# A list of additional container networks that the container would be connected to. +# The role does not create these networks, so make sure they already exist. +matrix_alertmanager_receiver_container_additional_networks: "{{ matrix_alertmanager_receiver_container_additional_networks_default + matrix_alertmanager_receiver_container_additional_networks_auto + matrix_alertmanager_receiver_container_additional_networks_custom }}" +matrix_alertmanager_receiver_container_additional_networks_default: [] +matrix_alertmanager_receiver_container_additional_networks_auto: [] +matrix_alertmanager_receiver_container_additional_networks_custom: [] + +# Controls whether matrix-alertmanager-receiver metrics should be proxied (exposed) on `matrix.DOMAIN/metrics/matrix-alertmanager-receiver` +matrix_alertmanager_receiver_metrics_proxying_enabled: false +matrix_alertmanager_receiver_metrics_proxying_hostname: '' +matrix_alertmanager_receiver_metrics_proxying_path: /metrics/matrix-alertmanager-receiver + +# matrix_alertmanager_receiver_container_labels_traefik_enabled controls whether labels to assist a Traefik reverse-proxy will be attached to the container. +# See `../templates/labels.j2` for details. +# +# To inject your own other container labels, see `matrix_alertmanager_receiver_container_labels_additional_labels`. +matrix_alertmanager_receiver_container_labels_traefik_enabled: true +matrix_alertmanager_receiver_container_labels_traefik_docker_network: "{{ matrix_alertmanager_receiver_container_network }}" +matrix_alertmanager_receiver_container_labels_traefik_hostname: "{{ matrix_alertmanager_receiver_hostname }}" +# The path prefix must either be `/` or not end with a slash (e.g. `/matrix-alertmanager-receiver`). +matrix_alertmanager_receiver_container_labels_traefik_path_prefix: "{{ matrix_alertmanager_receiver_path_prefix }}" +matrix_alertmanager_receiver_container_labels_traefik_rule: "Host(`{{ matrix_alertmanager_receiver_container_labels_traefik_hostname }}`){% if matrix_alertmanager_receiver_container_labels_traefik_path_prefix != '/' %} && PathPrefix(`{{ matrix_alertmanager_receiver_container_labels_traefik_path_prefix }}`){% endif %}" +matrix_alertmanager_receiver_container_labels_traefik_priority: 0 +matrix_alertmanager_receiver_container_labels_traefik_entrypoints: web-secure +matrix_alertmanager_receiver_container_labels_traefik_tls: "{{ matrix_alertmanager_receiver_container_labels_traefik_entrypoints != 'web' }}" +matrix_alertmanager_receiver_container_labels_traefik_tls_certResolver: default # noqa var-naming + +# Controls whether labels will be added that expose metrics (see `matrix_alertmanager_receiver_metrics_proxying_enabled`) for matrix-alertmanager-receiver +matrix_alertmanager_receiver_container_labels_public_metrics_enabled: "{{ matrix_alertmanager_receiver_metrics_enabled and matrix_alertmanager_receiver_metrics_proxying_enabled }}" +matrix_alertmanager_receiver_container_labels_public_metrics_traefik_path: "{{ matrix_alertmanager_receiver_metrics_proxying_path }}" +matrix_alertmanager_receiver_container_labels_public_metrics_traefik_rule: "Host(`{{ matrix_alertmanager_receiver_metrics_proxying_hostname }}`) && Path(`{{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_path }}`)" +matrix_alertmanager_receiver_container_labels_public_metrics_traefik_priority: 0 +matrix_alertmanager_receiver_container_labels_public_metrics_traefik_entrypoints: "{{ matrix_alertmanager_receiver_container_labels_traefik_entrypoints }}" +matrix_alertmanager_receiver_container_labels_public_metrics_traefik_tls: "{{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_entrypoints != 'web' }}" +matrix_alertmanager_receiver_container_labels_public_metrics_traefik_tls_certResolver: "{{ matrix_alertmanager_receiver_container_labels_traefik_tls_certResolver }}" # noqa var-naming +matrix_alertmanager_receiver_container_labels_public_metrics_middleware_basic_auth_enabled: false +# See: https://doc.traefik.io/traefik/middlewares/http/basicauth/#users +matrix_alertmanager_receiver_container_labels_public_metrics_middleware_basic_auth_users: '' + +# matrix_alertmanager_receiver_container_labels_additional_labels contains a multiline string with additional labels to add to the container label file. +# See `../templates/labels.j2` for details. +# +# Example: +# matrix_alertmanager_receiver_container_labels_additional_labels: | +# my.label=1 +# another.label="here" +matrix_alertmanager_receiver_container_labels_additional_labels: '' + +# A list of extra arguments to pass to the container +matrix_alertmanager_receiver_container_extra_arguments: [] + +# Controls the `--log-level` argument passed to the container process. +# Valid values: error, warn, info, debug +matrix_alertmanager_receiver_container_process_argument_log_level: info + +# A list of extra arguments to pass to the container process. +matrix_alertmanager_receiver_container_process_extra_arguments: [] + +# List of systemd services that matrix-alertmanager-receiver-proxy.service depends on +matrix_alertmanager_receiver_systemd_required_services_list: "{{ matrix_alertmanager_receiver_systemd_required_services_list_default + matrix_alertmanager_receiver_systemd_required_services_list_auto + matrix_alertmanager_receiver_systemd_required_services_list_custom }}" +matrix_alertmanager_receiver_systemd_required_services_list_default: "{{ [devture_systemd_docker_base_docker_service_name] if devture_systemd_docker_base_docker_service_name else [] }}" +matrix_alertmanager_receiver_systemd_required_services_list_auto: [] +matrix_alertmanager_receiver_systemd_required_services_list_custom: [] + +# List of systemd services that matrix-alertmanager-receiver-proxy.service wants +matrix_alertmanager_receiver_systemd_wanted_services_list: [] + +# Controls the `http.port` configuration setting. +matrix_alertmanager_receiver_config_http_port: 12345 + +# Controls the `http.alerts-path-prefix` configuration setting. +matrix_alertmanager_receiver_config_http_alerts_path_prefix: /alerts + +# Controls the `http.metrics-enabled` configuration setting. +matrix_alertmanager_receiver_config_http_metrics_enabled: false + +# Controls the `http.metrics-path` configuration setting. +matrix_alertmanager_receiver_config_http_metrics_path: /metrics + +# Controls the `matrix.homeserver-url` configuration setting. +matrix_alertmanager_receiver_config_matrix_homeserver_url: '' + +# Controls the `matrix.user-id` configuration setting. +matrix_alertmanager_receiver_config_matrix_user_id: "@{{ matrix_alertmanager_receiver_config_matrix_user_id_localpart }}:{{ matrix_domain }}" +matrix_alertmanager_receiver_config_matrix_user_id_localpart: "bot.alertmanager.receiver" + +# Controls the `matrix.access-token` configuration setting. +matrix_alertmanager_receiver_config_matrix_access_token: '' + +# Controls the `matrix.room-mapping` configuration setting. +# +# Example: +# matrix_alertmanager_receiver_config_matrix_room: +# simple-name: "!qohfwef7qwerf:example.com" +# another-name: "!bf3zfio3wbanw:example.com" +matrix_alertmanager_receiver_config_matrix_room_mapping: {} + +# Controls the `templating.external-url-mapping` configuration setting. +# +# The key is the original value taken from the Alertmanager payload +# The value is the mapped value which will be available as '.ExternalURL' in templates +# +# Example: +# matrix_alertmanager_receiver_config_templating_external_url_mapping: +# "http://alertmanager:9093": https://alertmanager.example.com +# "http://alertmanager:9094": https://another.alertmanager.example.com +matrix_alertmanager_receiver_config_templating_external_url_mapping: {} + +# Controls the `templating.generator-url-mapping` configuration setting. +# +# The key is the original value taken from the Alertmanager payload +# The value is the mapped value which will be available as '.ExternalURL' in templates +# +# Example: +# matrix_alertmanager_receiver_config_templating_generator_url_mapping: +# "http://prometheus:8080": https://prometheus.example.com +# "http://prometheus:8081": https://another.prometheus.example.com +matrix_alertmanager_receiver_config_templating_generator_url_mapping: {} + +# Controls the `templating.computed-values` configuration setting. +matrix_alertmanager_receiver_config_templating_computed_values: "{{ matrix_alertmanager_receiver_config_templating_computed_values_default + matrix_alertmanager_receiver_config_templating_computed_values_auto + matrix_alertmanager_receiver_config_templating_computed_values_custom }}" +matrix_alertmanager_receiver_config_templating_computed_values_default: + - values: # always set 'color' to 'yellow' + color: yellow + - values: # set 'color' to 'orange' when alert label 'severity' is 'warning' + color: orange + when-matching-labels: + severity: warning + - values: # set 'color' to 'red' when alert label 'severity' is 'critical' + color: red + when-matching-labels: + severity: critical + - values: # set 'color' to 'green' when alert status is 'resolved' + color: green + when-matching-status: resolved +matrix_alertmanager_receiver_config_templating_computed_values_auto: [] +matrix_alertmanager_receiver_config_templating_computed_values_custom: [] + +# Controls the `templating.firing-template` configuration setting. +matrix_alertmanager_receiver_config_templating_firing_template: |- + {% raw %} +

+ {{ .Alert.Status | ToUpper }} + {{ if .Alert.Labels.name }} + {{ .Alert.Labels.name }} + {{ else if .Alert.Labels.alertname }} + {{ .Alert.Labels.alertname }} + {{ end }} + >> + {{ if .Alert.Labels.severity }} + {{ .Alert.Labels.severity | ToUpper }}: + {{ end }} + {{ if .Alert.Annotations.description }} + {{ .Alert.Annotations.description }} + {{ else if .Alert.Annotations.summary }} + {{ .Alert.Annotations.summary }} + {{ end }} + >> + {{ if .Alert.Annotations.runbook_url }} + Runbook | + {{ end }} + {{ if .Alert.Annotations.dashboard }} + Dashboard | + {{ end }} + Silence +

+ {% endraw %} + +# Controls the `templating.resolved-template` configuration setting. +matrix_alertmanager_receiver_config_templating_resolved_template: |- + {% raw %} + {{ .Alert.Status | ToUpper }}{{ .Alert.Labels.name }}' + {% endraw %} + +# Default matrix-alertmanager-receiver 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_alertmanager_receiver_configuration_extension_yaml`) +# or completely replace this variable with your own template. +matrix_alertmanager_receiver_configuration_yaml: "{{ lookup('template', 'templates/config.yml.j2') }}" + +matrix_alertmanager_receiver_configuration_extension_yaml: | + # Your custom YAML configuration for matrix-alertmanager-receiver goes here. + # This configuration extends the default starting configuration (`matrix_alertmanager_receiver_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_alertmanager_receiver_configuration_yaml`. + # + # Example configuration extension follows: + # + # http: + # address: '' + +matrix_alertmanager_receiver_configuration_extension: "{{ matrix_alertmanager_receiver_configuration_extension_yaml | from_yaml if matrix_alertmanager_receiver_configuration_extension_yaml | from_yaml is mapping else {} }}" + +# Holds the final matrix-alertmanager-receiver configuration (a combination of the default and its extension). +# You most likely don't need to touch this variable. Instead, see `matrix_alertmanager_receiver_configuration_yaml`. +matrix_alertmanager_receiver_configuration: "{{ matrix_alertmanager_receiver_configuration_yaml | from_yaml | combine(matrix_alertmanager_receiver_configuration_extension, recursive=True) }}" diff --git a/roles/custom/matrix-alertmanager-receiver/tasks/install.yml b/roles/custom/matrix-alertmanager-receiver/tasks/install.yml new file mode 100644 index 000000000..de946bb5a --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/tasks/install.yml @@ -0,0 +1,80 @@ +--- + +- name: Ensure matrix-alertmanager-receiver paths exist + ansible.builtin.file: + path: "{{ item.path }}" + state: directory + mode: 0750 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + with_items: + - path: "{{ matrix_alertmanager_receiver_base_path }}" + when: true + - path: "{{ matrix_alertmanager_receiver_config_path }}" + when: true + - path: "{{ matrix_alertmanager_receiver_container_src_path }}" + when: "{{ matrix_alertmanager_receiver_container_image_self_build }}" + when: item.when | bool + +- name: Ensure matrix-alertmanager-receiver configuration installed + ansible.builtin.copy: + content: "{{ matrix_alertmanager_receiver_configuration | to_nice_yaml(indent=2, width=999999) }}" + dest: "{{ matrix_alertmanager_receiver_config_path }}/config.yml" + mode: 0644 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + +- name: Ensure matrix-alertmanager-receiver support files installed + ansible.builtin.template: + src: "{{ role_path }}/templates/{{ item }}.j2" + dest: "{{ matrix_alertmanager_receiver_base_path }}/{{ item }}" + mode: 0640 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + with_items: + - labels + +- name: Ensure matrix-alertmanager-receiver container image is pulled + community.docker.docker_image: + name: "{{ matrix_alertmanager_receiver_container_image }}" + source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}" + force_source: "{{ matrix_alertmanager_receiver_container_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_alertmanager_receiver_container_image_force_pull }}" + when: "not matrix_alertmanager_receiver_container_image_self_build | bool" + register: result + retries: "{{ devture_playbook_help_container_retries_count }}" + delay: "{{ devture_playbook_help_container_retries_delay }}" + until: result is not failed + +- when: matrix_alertmanager_receiver_container_image_self_build | bool + block: + - name: Ensure matrix-alertmanager-receiver repository is present on self-build + ansible.builtin.git: + repo: "{{ matrix_alertmanager_receiver_container_image_self_build_repo }}" + version: "{{ matrix_alertmanager_receiver_container_image_self_build_repo_version }}" + dest: "{{ matrix_alertmanager_receiver_container_src_path }}" + force: "yes" + become: true + become_user: "{{ matrix_user_username }}" + register: matrix_alertmanager_receiver_git_pull_results + + - name: Ensure matrix-alertmanager-receiver container image is built + ansible.builtin.command: + cmd: |- + {{ devture_systemd_docker_base_host_command_docker }} buildx build + --tag={{ matrix_alertmanager_receiver_container_image }} + --file={{ matrix_alertmanager_receiver_container_src_path }}/contrib/Dockerfile + {{ matrix_alertmanager_receiver_container_src_path }} + changed_when: true + +- name: Ensure matrix-alertmanager-receiver container network is created + community.general.docker_network: + enable_ipv6: "{{ devture_systemd_docker_base_ipv6_enabled }}" + name: "{{ matrix_alertmanager_receiver_container_network }}" + driver: bridge + +- name: Ensure matrix-alertmanager-receiver.service installed + ansible.builtin.template: + src: "{{ role_path }}/templates/systemd/matrix-alertmanager-receiver.service.j2" + dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-alertmanager-receiver.service" + mode: 0644 diff --git a/roles/custom/matrix-alertmanager-receiver/tasks/main.yml b/roles/custom/matrix-alertmanager-receiver/tasks/main.yml new file mode 100644 index 000000000..b6ff76aca --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/tasks/main.yml @@ -0,0 +1,20 @@ +--- + +- tags: + - setup-all + - setup-alertmanager-receiver + - install-all + - install-alertmanager-receiver + block: + - when: matrix_alertmanager_receiver_enabled | bool + ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml" + + - when: matrix_alertmanager_receiver_enabled | bool + ansible.builtin.include_tasks: "{{ role_path }}/tasks/install.yml" + +- tags: + - setup-all + - setup-alertmanager-receiver + block: + - when: not matrix_alertmanager_receiver_enabled | bool + ansible.builtin.include_tasks: "{{ role_path }}/tasks/uninstall.yml" diff --git a/roles/custom/matrix-alertmanager-receiver/tasks/uninstall.yml b/roles/custom/matrix-alertmanager-receiver/tasks/uninstall.yml new file mode 100644 index 000000000..f0a82acbf --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/tasks/uninstall.yml @@ -0,0 +1,25 @@ +--- + +- name: Check existence of matrix-alertmanager-receiver service + ansible.builtin.stat: + path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-alertmanager-receiver.service" + register: matrix_alertmanager_receiver_service_stat + +- when: matrix_alertmanager_receiver_service_stat.stat.exists | bool + block: + - name: Ensure matrix-alertmanager-receiver is stopped + ansible.builtin.service: + name: matrix-alertmanager-receiver + state: stopped + enabled: false + daemon_reload: true + + - name: Ensure matrix-alertmanager-receiver.service doesn't exist + ansible.builtin.file: + path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-alertmanager-receiver.service" + state: absent + + - name: Ensure matrix-alertmanager-receiver paths don't exist + ansible.builtin.file: + path: "{{ matrix_alertmanager_receiver_base_path }}" + state: absent diff --git a/roles/custom/matrix-alertmanager-receiver/tasks/validate_config.yml b/roles/custom/matrix-alertmanager-receiver/tasks/validate_config.yml new file mode 100644 index 000000000..83591a956 --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/tasks/validate_config.yml @@ -0,0 +1,14 @@ +--- +- name: Fail if required matrix-alertmanager-receiver settings not defined + ansible.builtin.fail: + msg: > + You need to define a required configuration setting (`{{ item.name }}`). + when: "item.when | bool and vars[item.name] == ''" + with_items: + - {'name': 'matrix_alertmanager_receiver_hostname', when: true} + - {'name': 'matrix_alertmanager_receiver_path_prefix', when: true} + - {'name': 'matrix_alertmanager_receiver_config_matrix_homeserver_url', when: true} + - {'name': 'matrix_alertmanager_receiver_config_matrix_access_token', when: true} + - {'name': 'matrix_alertmanager_receiver_container_network', when: true} + - {'name': 'matrix_alertmanager_receiver_metrics_proxying_hostname', when: "{{ matrix_alertmanager_receiver_metrics_proxying_enabled }}"} + - {'name': 'matrix_alertmanager_receiver_metrics_proxying_path_prefix', when: "{{ matrix_alertmanager_receiver_metrics_proxying_enabled }}"} diff --git a/roles/custom/matrix-alertmanager-receiver/templates/config.yml.j2 b/roles/custom/matrix-alertmanager-receiver/templates/config.yml.j2 new file mode 100644 index 000000000..40d37f9b7 --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/templates/config.yml.j2 @@ -0,0 +1,37 @@ +#jinja2: lstrip_blocks: "True" +# configuration of the HTTP server +http: + address: 0.0.0.0 # bind address for this service. Can be left unspecified to bind on all interfaces + port: {{ matrix_alertmanager_receiver_config_http_port | to_json }} # port used by this service + alerts-path-prefix: {{ matrix_alertmanager_receiver_config_http_alerts_path_prefix | to_json }} # URL path for the webhook receiver called by an Alertmanager. Defaults to /alerts + metrics-path: {{ matrix_alertmanager_receiver_config_http_metrics_path | to_json }} # URL path to collect metrics. Defaults to /metrics + metrics-enabled: {{ matrix_alertmanager_receiver_config_http_metrics_enabled | to_json }} # Whether to enable metrics or not. Defaults to false + +# configuration for the Matrix connection +matrix: + homeserver-url: {{ matrix_alertmanager_receiver_config_matrix_homeserver_url | to_json }} # FQDN of the homeserver + user-id: {{ matrix_alertmanager_receiver_config_matrix_user_id | to_json }} # ID of the user used by this service + access-token: {{ matrix_alertmanager_receiver_config_matrix_access_token | to_json }} # Access token for the user ID + # define short names for Matrix room ID + room-mapping: {{ matrix_alertmanager_receiver_config_matrix_room_mapping | to_json }} + +# configuration of the templating features +templating: + # mapping of ExternalURL values + # key is the original value taken from the Alertmanager payload + # value is the mapped value which will be available as '.ExternalURL' in templates + external-url-mapping: {{ matrix_alertmanager_receiver_config_templating_external_url_mapping | to_json }} + # mapping of GeneratorURL values + # key is the original value taken from the Alertmanager payload + # value is the mapped value which will be available as '.GeneratorURL' in templates + generator-url-mapping: {{ matrix_alertmanager_receiver_config_templating_generator_url_mapping | to_json }} + + # computation of arbitrary values based on matching alert annotations, labels, or status + # values will be evaluated top to bottom, last entry wins + computed-values: {{ matrix_alertmanager_receiver_config_templating_computed_values | to_json }} + + # template for alerts in status 'firing' + firing-template: {{ matrix_alertmanager_receiver_config_templating_firing_template | to_json }} + + # template for alerts in status 'resolved', if not specified will use the firing-template + resolved-template: {{ matrix_alertmanager_receiver_config_templating_resolved_template | to_json }} diff --git a/roles/custom/matrix-alertmanager-receiver/templates/labels.j2 b/roles/custom/matrix-alertmanager-receiver/templates/labels.j2 new file mode 100644 index 000000000..8bf7d22b9 --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/templates/labels.j2 @@ -0,0 +1,69 @@ +{% if matrix_alertmanager_receiver_container_labels_traefik_enabled %} +traefik.enable=true + +{% if matrix_alertmanager_receiver_container_labels_traefik_docker_network %} +traefik.docker.network={{ matrix_alertmanager_receiver_container_labels_traefik_docker_network }} +{% endif %} + +traefik.http.services.matrix-alertmanager-receiver.loadbalancer.server.port={{ matrix_alertmanager_receiver_config_http_port }} + +{% set middlewares = [] %} + +{% if matrix_alertmanager_receiver_container_labels_traefik_path_prefix != '/' %} +traefik.http.middlewares.matrix-alertmanager-receiver-slashless-redirect.redirectregex.regex=({{ matrix_alertmanager_receiver_container_labels_traefik_path_prefix | quote }})$ +traefik.http.middlewares.matrix-alertmanager-receiver-slashless-redirect.redirectregex.replacement=${1}/ +{% set middlewares = middlewares + ['matrix-alertmanager-receiver-slashless-redirect'] %} +{% endif %} + +{% if matrix_alertmanager_receiver_container_labels_traefik_path_prefix != '/' %} +traefik.http.middlewares.matrix-alertmanager-receiver-strip-prefix.stripprefix.prefixes={{ matrix_alertmanager_receiver_container_labels_traefik_path_prefix }} +{% set middlewares = middlewares + ['matrix-alertmanager-receiver-strip-prefix'] %} +{% endif %} + +traefik.http.routers.matrix-alertmanager-receiver.rule={{ matrix_alertmanager_receiver_container_labels_traefik_rule }} +{% if matrix_alertmanager_receiver_container_labels_traefik_priority | int > 0 %} +traefik.http.routers.matrix-alertmanager-receiver.priority={{ matrix_alertmanager_receiver_container_labels_traefik_priority }} +{% endif %} +traefik.http.routers.matrix-alertmanager-receiver.service=matrix-alertmanager-receiver +{% if middlewares | length > 0 %} +traefik.http.routers.matrix-alertmanager-receiver.middlewares={{ middlewares | join(',') }} +{% endif %} +traefik.http.routers.matrix-alertmanager-receiver.entrypoints={{ matrix_alertmanager_receiver_container_labels_traefik_entrypoints }} +traefik.http.routers.matrix-alertmanager-receiver.tls={{ matrix_alertmanager_receiver_container_labels_traefik_tls | to_json }} +{% if matrix_alertmanager_receiver_container_labels_traefik_tls %} +traefik.http.routers.matrix-alertmanager-receiver.tls.certResolver={{ matrix_alertmanager_receiver_container_labels_traefik_tls_certResolver }} +{% endif %} + +{% if matrix_alertmanager_receiver_container_labels_public_metrics_enabled %} +{% set metrics_middlewares = [] %} + +{% if matrix_alertmanager_receiver_container_labels_public_metrics_middleware_basic_auth_enabled %} +{% set metrics_middlewares = metrics_middlewares + ['matrix-alertmanager-receiver-metrics-basic-auth'] %} +traefik.http.middlewares.matrix-alertmanager-receiver-metrics-basic-auth.basicauth.users={{ matrix_alertmanager_receiver_container_labels_public_metrics_middleware_basic_auth_users }} +{% endif %} + +{% set metrics_middlewares = metrics_middlewares + ['matrix-alertmanager-receiver-metrics-replacepath'] %} +traefik.http.middlewares.matrix-alertmanager-receiver-metrics-replacepath.replacepath.path={{ matrix_alertmanager_receiver_config_http_metrics_path }} + +traefik.http.routers.matrix-alertmanager-receiver-metrics.rule={{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_rule }} + +{% if metrics_middlewares | length > 0 %} +traefik.http.routers.matrix-alertmanager-receiver-metrics.middlewares={{ metrics_middlewares | join(',') }} +{% endif %} + +{% if matrix_alertmanager_receiver_container_labels_public_metrics_traefik_priority | int > 0 %} +traefik.http.routers.matrix-alertmanager-receiver-metrics.priority={{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_priority }} +{% endif %} + +traefik.http.routers.matrix-alertmanager-receiver-metrics.service=matrix-alertmanager-receiver +traefik.http.routers.matrix-alertmanager-receiver-metrics.entrypoints={{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_entrypoints }} + +traefik.http.routers.matrix-alertmanager-receiver-metrics.tls={{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_tls | to_json }} +{% if matrix_alertmanager_receiver_container_labels_public_metrics_traefik_tls %} +traefik.http.routers.matrix-alertmanager-receiver-metrics.tls.certResolver={{ matrix_alertmanager_receiver_container_labels_public_metrics_traefik_tls_certResolver }} +{% endif %} +{% endif %} + +{% endif %} + +{{ matrix_alertmanager_receiver_container_labels_additional_labels }} diff --git a/roles/custom/matrix-alertmanager-receiver/templates/systemd/matrix-alertmanager-receiver.service.j2 b/roles/custom/matrix-alertmanager-receiver/templates/systemd/matrix-alertmanager-receiver.service.j2 new file mode 100644 index 000000000..4d7e43c54 --- /dev/null +++ b/roles/custom/matrix-alertmanager-receiver/templates/systemd/matrix-alertmanager-receiver.service.j2 @@ -0,0 +1,50 @@ +#jinja2: lstrip_blocks: "True" +[Unit] +Description=matrix-alertmanager-receiver +{% for service in matrix_alertmanager_receiver_systemd_required_services_list %} +Requires={{ service }} +After={{ service }} +{% endfor %} +{% for service in matrix_alertmanager_receiver_systemd_wanted_services_list %} +Wants={{ service }} +{% endfor %} +DefaultDependencies=no + +[Service] +Type=simple +Environment="HOME={{ devture_systemd_docker_base_systemd_unit_home_path }}" +ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-alertmanager-receiver 2>/dev/null || true' +ExecStartPre=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-alertmanager-receiver 2>/dev/null || true' + +ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \ + --rm \ + --name=matrix-alertmanager-receiver \ + --log-driver=none \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + --cap-drop=ALL \ + --read-only \ + --network={{ matrix_alertmanager_receiver_container_network }} \ + --mount type=bind,src={{ matrix_alertmanager_receiver_config_path }},dst=/config,ro \ + --label-file={{ matrix_alertmanager_receiver_base_path }}/labels \ + {% for arg in matrix_alertmanager_receiver_container_extra_arguments %} + {{ arg }} \ + {% endfor %} + {{ matrix_alertmanager_receiver_container_image }} \ + --config-path=/config/config.yml {{ matrix_alertmanager_receiver_container_process_extra_arguments | join(' ') }} \ + --log-level={{ matrix_alertmanager_receiver_container_process_argument_log_level }} + +{% for network in matrix_alertmanager_receiver_container_additional_networks %} +ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-alertmanager-receiver +{% endfor %} + +ExecStart={{ devture_systemd_docker_base_host_command_docker }} start --attach matrix-alertmanager-receiver + +ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} stop --time={{ devture_systemd_docker_base_container_stop_grace_time_seconds }} matrix-alertmanager-receiver 2>/dev/null || true' +ExecStop=-{{ devture_systemd_docker_base_host_command_sh }} -c '{{ devture_systemd_docker_base_host_command_docker }} rm matrix-alertmanager-receiver 2>/dev/null || true' + +Restart=always +RestartSec=30 +SyslogIdentifier=matrix-alertmanager-receiver + +[Install] +WantedBy=multi-user.target diff --git a/setup.yml b/setup.yml index f284ec88c..c0551b7fe 100644 --- a/setup.yml +++ b/setup.yml @@ -51,6 +51,7 @@ - galaxy/keydb - custom/matrix-corporal - custom/matrix-appservice-draupnir-for-all + - custom/matrix-alertmanager-receiver - custom/matrix-bridge-appservice-discord - custom/matrix-bridge-appservice-slack - custom/matrix-bridge-appservice-webhooks