diff --git a/README.md b/README.md index 5fada48..d56ab62 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Roles for deploying matrix infrastructure using ansible. ## Roles +- [`alertmanager_receiver`](roles/alertmanager_receiver/README.md): a matrix-based receiver for alertmanager - [`cinny`](roles/cinny/README.md): [Cinny](https://cinny.in/) Web Client - [`element`](roles/element/README.md): [Element](https://element.io/) Web Client - [`hydrogen`](roles/hydrogen/README.md): [Hydrogen](https://matrix.org/ecosystem/clients/hydrogen/) lightweight web client diff --git a/galaxy.yml b/galaxy.yml index 8a71097..5bd363b 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -20,3 +20,4 @@ tags: - element - hydrogen - cinny + - matrix_alertmanager_receiver diff --git a/playbooks/alertmanager_receiver.yml b/playbooks/alertmanager_receiver.yml new file mode 100644 index 0000000..e7cfb4a --- /dev/null +++ b/playbooks/alertmanager_receiver.yml @@ -0,0 +1,7 @@ +--- +- name: Deploy matrix-alertmanager-receiver + hosts: "{{ matrix_alertmanager_receiver_hosts | default('matrix_alertmanager_receiver') }}" + become: "{{ matrix_alertmanager_receiver_become | default(false) }}" + gather_facts: "{{ matrix_alertmanager_receiver_gather_facts | default(false) }}" + roles: + - role: finallycoffee.matrix.alertmanager_receiver diff --git a/roles/alertmanager_receiver/README.md b/roles/alertmanager_receiver/README.md new file mode 100644 index 0000000..4b68c5d --- /dev/null +++ b/roles/alertmanager_receiver/README.md @@ -0,0 +1,17 @@ +# `finallycoffee.matrix.alertmanager_receiver` ansible role + +This ansible role deploys and configures +[`matrix-alertmanager-receiver`](https://github.com/metio/matrix-alertmanager-receiver), +a fork of [https://git.sr.ht/~fnux/matrix-alertmanager-receiver] with more features. +For futher information, see [the project's `README`](https://github.com/metio/matrix-alertmanager-receiver?tab=readme-ov-file#matrix-alertmanager-receiver-). + +## Configuration + +### Required configuration + +The following variables *must* be populated or else the role will be unable to +set up the service successfully: + +- `alertmanager_receiver_config_matrix_homeserver_url` - matrix homeserver URL +- `alertmanager_receiver_config_matrix_user_id` - full userid (`@user:instance.tld`) +- `alertmanager_receiver_config_matrix_access_token` - access token for that user diff --git a/roles/alertmanager_receiver/defaults/main/config.yml b/roles/alertmanager_receiver/defaults/main/config.yml new file mode 100644 index 0000000..7be1368 --- /dev/null +++ b/roles/alertmanager_receiver/defaults/main/config.yml @@ -0,0 +1,52 @@ +--- +alertmanager_receiver_config_log_level: "info" +alertmanager_receiver_config_http_address: 127.0.0.1 +alertmanager_receiver_config_http_port: 12345 +alertmanager_receiver_config_http_alerts_path_prefix: "/alerts" +alertmanager_receiver_config_http_metrics_path: "/metrics" +alertmanager_receiver_config_http_metric_enabled: true +alertmanager_receiver_config_http_basic_username: "alertmanager" +alertmanager_receiver_config_http_basic_password: ~ +alertmanager_receiver_config_http: + address: "{{ alertmanager_receiver_config_http_address }}" + port: "{{ alertmanager_receiver_config_http_port }}" + "alerts-path-prefix": "{{ alertmanager_receiver_config_http_alerts_path_prefix }}" + "metrics-path": "{{ alertmanager_receiver_config_http_metrics_path }}" + "metrics-enabled": "{{ alertmanager_receiver_config_http_metric_enabled }}" + "basic-username": "{{ alertmanager_receiver_config_http_basic_username }}" + "basic-password": "{{ alertmanager_receiver_config_http_basic_password }}" +alertmanager_receiver_config_matrix_homeserver_url: ~ +alertmanager_receiver_config_matrix_user_id: ~ +alertmanager_receiver_config_matrix_access_token: ~ +alertmanager_receiver_config_matrix_proxy: "" +alertmanager_receiver_config_matrix_room_mapping: {} +alertmanager_receiver_config_matrix: + "homeserver-url": "{{ alertmanager_receiver_config_matrix_homeserver_url }}" + "user-id": "{{ alertmanager_receiver_config_matrix_user_id }}" + "access-token": "{{ alertmanager_receiver_config_matrix_access_token }}" + proxy: "{{ alertmanager_receiver_config_matrix_proxy }}" + "room-mapping": "{{ alertmanager_receiver_config_matrix_room_mapping }}" +alertmanager_receiver_config_templating_external_url_mapping: {} +alertmanager_receiver_config_templating_generator_url_mapping: {} +alertmanager_receiver_config_templating_computed_values: >-2 + {{ alertmanager_receiver_config_templating_computed_values_default }} +alertmanager_receiver_config_templating_firing_template: >-2 + {{ alertmanager_receiver_config_templating_firing_template_default }} +alertmanager_receiver_config_templating_resolved_template: >-2 + {{ alertmanager_receiver_config_templating_resolved_template_default }} +alertmanager_receiver_config_templating: + "external-url-mapping": >-2 + {{ alertmanager_receiver_config_templating_external_url_mapping }} + "generator-url-mapping": >-2 + {{ alertmanager_receiver_config_templating_generator_url_mapping }} + "computed-values": "{{ alertmanager_receiver_config_templating_computed_values }}" + "firing-template": "{{ alertmanager_receiver_config_templating_firing_template }}" + "resolved-template": "{{ alertmanager_receiver_config_templating_resolved_template }}" +alertmanager_receiver_default_config: + http: "{{ alertmanager_receiver_config_http }}" + matrix: "{{ alertmanager_receiver_config_matrix }}" + templating: "{{ alertmanager_receiver_config_templating }}" +alertmanager_receiver_config: {} +alertmanager_receiver_merged_config: >-2 + {{ (alertmanager_receiver_default_config | default({})) + | combine(alertmanager_receiver_config | default({}), recursive=True) }} diff --git a/roles/alertmanager_receiver/defaults/main/container.yml b/roles/alertmanager_receiver/defaults/main/container.yml new file mode 100644 index 0000000..5caf1cc --- /dev/null +++ b/roles/alertmanager_receiver/defaults/main/container.yml @@ -0,0 +1,54 @@ +--- +alertmanager_receiver_container_image_registry: "docker.io" +alertmanager_receiver_container_image_namespace: "metio" +alertmanager_receiver_container_image_repository: "matrix-alertmanager-receiver" +alertmanager_receiver_container_image_name: >-2 + {{ [ + alertmanager_receiver_container_image_registry | default([]), + alertmanager_receiver_container_image_namespace | default([]), + alertmanager_receiver_container_image_repository + ] | flatten | join('/') }} +alertmanager_receiver_container_image_tag: ~ +alertmanager_receiver_container_image: >-2 + {{ [ + alertmanager_receiver_container_image_name, + (alertmanager_receiver_container_image_tag | default( + alertmanager_receiver_version, true + )) + ] | join(':') }} +alertmanager_receiver_container_image_source: "pull" +alertmanager_receiver_container_image_force_source: >-2 + {{ alertmanager_receiver_container_image_tag | default(false, true) | bool }} + +alertmanager_receiver_container_config_file_path: >-2 + {{ alertmanager_receiver_config_file_path }} + +alertmanager_receiver_container_name: "matrix-alertmanager-receiver" +alertmanager_receiver_container_env: ~ +alertmanager_receiver_container_user: >-2 + {{ alertmanager_receiver_user_uid }}:{{ alertmanager_receiver_user_gid }} +alertmanager_receiver_container_ports: ~ +alertmanager_receiver_container_labels: ~ +alertmanager_receiver_container_command: +# - "/matrix-alertmanager-receiver" + - "--config-path" + - "{{ alertmanager_receiver_container_config_file_path }}" + - "--log-level" + - "{{ alertmanager_receiver_config_log_level }}" +alertmanager_receiver_container_volumes: [] +alertmanager_receiver_container_base_volumes: + - >-2 + {{ [ + alertmanager_receiver_config_file_path, + alertmanager_receiver_container_config_file_path, + 'ro' + ] | join(':') }} +alertmanager_receiver_container_merged_volumes: >-2 + {{ (alertmanager_receiver_container_base_volumes | default([], true)) + + (alertmanager_receiver_container_volumes | default([], true)) }} +alertmanager_receiver_container_networks: ~ +alertmanager_receiver_container_etc_hosts: ~ +alertmanager_receiver_container_dns_servers: ~ +alertmanager_receiver_container_restart_policy: "on-failure" +alertmanager_receiver_container_state: >-2 + {{ (alertmanager_receiver_state == 'present') | ternary('started', 'absent') }} diff --git a/roles/alertmanager_receiver/defaults/main/main.yml b/roles/alertmanager_receiver/defaults/main/main.yml new file mode 100644 index 0000000..0248a31 --- /dev/null +++ b/roles/alertmanager_receiver/defaults/main/main.yml @@ -0,0 +1,9 @@ +--- +alertmanager_receiver_user: "matrix-alertmanager-receiver" +alertmanager_receiver_version: "2025.8.6" +alertmanager_receiver_config_file_path: "/etc/matrix-alertmanager-receiver/config.yaml" +alertmanager_receiver_config_path: >-2 + {{ alertmanager_receiver_config_file_path | dirname }} + +alertmanager_receiver_state: present +alertmanager_receiver_deployment_method: docker diff --git a/roles/alertmanager_receiver/defaults/main/templates.yml b/roles/alertmanager_receiver/defaults/main/templates.yml new file mode 100644 index 0000000..eaf1b9f --- /dev/null +++ b/roles/alertmanager_receiver/defaults/main/templates.yml @@ -0,0 +1,51 @@ +--- +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 + +alertmanager_receiver_config_templating_firing_template_default: |+2 + {% 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 }} + Runbook | + {{ end }} + {{ if .Alert.Annotations.dashboard }} + Dashboard | + {{ end }} + Silence +
+ {%- endraw %} + +alertmanager_receiver_config_templating_resolved_template_default: |+2 + {% raw -%} + + {{ .Alert.Status | ToUpper }} + {{ .Alert.Labels.name }} + {%- endraw %} diff --git a/roles/alertmanager_receiver/defaults/main/user.yml b/roles/alertmanager_receiver/defaults/main/user.yml new file mode 100644 index 0000000..fc7b1c9 --- /dev/null +++ b/roles/alertmanager_receiver/defaults/main/user.yml @@ -0,0 +1,11 @@ +--- +alertmanager_receiver_user_create_home: false +alertmanager_receiver_user_system: true +alertmanager_receiver_user_groups: [] +alertmanager_receiver_user_append: >-2 + {{ alertmanager_receiver_user_groups | length > 0 }} + +alertmanager_receiver_user_uid: >-2 + {{ alertmanager_receiver_user_info.uid | default(alertmanager_receiver_user) }} +alertmanager_receiver_user_gid: >-2 + {{ alertmanager_receiver_user_info.group | default(alertmanager_receiver_user) }} diff --git a/roles/alertmanager_receiver/meta/main.yml b/roles/alertmanager_receiver/meta/main.yml new file mode 100644 index 0000000..165bb2e --- /dev/null +++ b/roles/alertmanager_receiver/meta/main.yml @@ -0,0 +1,14 @@ +--- +allow_duplicates: true +dependencies: [] +galaxy_info: + role_name: alertmanager_receiver + description: >-2 + `matrix-alertmanager-receiver` is a receiver for alerts generated by alertmanager. + This role supports both `docker` and `podman` based deployments. + galaxy_tags: + - matrix + - alertmanager + - metio + - docker + - podman diff --git a/roles/alertmanager_receiver/tasks/check.yml b/roles/alertmanager_receiver/tasks/check.yml new file mode 100644 index 0000000..ddd64bd --- /dev/null +++ b/roles/alertmanager_receiver/tasks/check.yml @@ -0,0 +1,28 @@ +--- +- name: Ensure valid alertmanager_receiver_state + ansible.builtin.fail: + msg: >-2 + Unsupported value '{{ alertmanager_receiver_state }}' for + alertmanager_receiver_state. Supported values are + {{ alertmanager_receiver_states | map(quote) | join(', ') + when: alertmanager_receiver_state not in alertmanager_receiver_states + +- name: Ensure valid alertmanager_receiver_deployment_method + ansible.builtin.fail: + msg: >-2 + Unsupported value '{{ alertmanager_receiver_deployment_method }}' for + alertmanager_receiver_deployment_method. Supported values are + {{ alertmanager_receiver_deployment_methods | map(quote) | join(', ') + when: alertmanager_receiver_deployment_method not in alertmanager_receiver_deployment_methods + +- name: Ensure role fails when required configuration is missing + ansible.builtin.fail: + msg: >-2 + Required configuration key '{{ _config_key }}' is undefined + when: hostvars[inventory_hostname][_config_key] is undefined + loop: + - "alertmanager_receiver_config_matrix_homeserver_url" + - "alertmanager_receiver_config_matrix_user_id" + - "alertmanager_receiver_config_matrix_access_token" + loop_control: + loop_var: "_config_key" diff --git a/roles/alertmanager_receiver/tasks/configure.yml b/roles/alertmanager_receiver/tasks/configure.yml new file mode 100644 index 0000000..9e1cf05 --- /dev/null +++ b/roles/alertmanager_receiver/tasks/configure.yml @@ -0,0 +1,12 @@ +--- +- name: Ensure configuration folder '{{ alertmanager_receiver_config_path }}' is {{ alertmanager_receiver_state }} + ansible.builtin.file: + path: "{{ alertmanager_receiver_config_path }}" + state: >-2 + {{ (alertmanager_receiver_state == 'present') | ternary('directory', 'absent') }} + +- name: Ensure configuration file '{{ alertmanager_receiver_config_file_path }}' is written + ansible.builtin.copy: + dest: "{{ alertmanager_receiver_config_file_path }}" + content: "{{ alertmanager_receiver_merged_config | to_nice_yaml(indent=2, width=200) }}" + when: alertmanager_receiver_state == 'present' diff --git a/roles/alertmanager_receiver/tasks/deploy-docker.yml b/roles/alertmanager_receiver/tasks/deploy-docker.yml new file mode 100644 index 0000000..1bb8a01 --- /dev/null +++ b/roles/alertmanager_receiver/tasks/deploy-docker.yml @@ -0,0 +1,23 @@ +--- +- name: Ensure container image '{{ alertmanager_receiver_container_image }}' is {{ alertmanager_receiver_state }} + community.docker.docker_image: + name: "{{ alertmanager_receiver_container_image }}" + state: "{{ alertmanager_receiver_state }}" + source: "{{ alertmanager_receiver_container_image_source }}" + force_source: "{{ alertmanager_receiver_container_image_force_source }}" + +- name: Ensure container '{{ alertmanager_receiver_container_name }}' is {{ alertmanager_receiver_container_state }} + community.docker.docker_container: + name: "{{ alertmanager_receiver_container_name }}" + image: "{{ alertmanager_receiver_container_image }}" + env: "{{ alertmanager_receiver_container_env | default(omit, true) }}" + user: "{{ alertmanager_receiver_container_user | default(omit, true) }}" + ports: "{{ alertmanager_receiver_container_ports }}" + labels: "{{ alertmanager_receiver_container_labels }}" + command: "{{ alertmanager_receiver_container_command | default(omit, true) }}" + volumes: "{{ alertmanager_receiver_container_merged_volumes }}" + networks: "{{ alertmanager_receiver_container_networks | default(omit, true) }}" + etc_hosts: "{{ alertmanager_receiver_container_etc_hosts }}" + dns_servers: "{{ alertmanager_receiver_container_dns_servers }}" + restart_policy: "{{ alertmanager_receiver_container_restart_policy }}" + state: "{{ alertmanager_receiver_container_state }}" diff --git a/roles/alertmanager_receiver/tasks/deploy-podman.yml b/roles/alertmanager_receiver/tasks/deploy-podman.yml new file mode 100644 index 0000000..6b88f72 --- /dev/null +++ b/roles/alertmanager_receiver/tasks/deploy-podman.yml @@ -0,0 +1,23 @@ +--- +- name: Ensure container image '{{ alertmanager_receiver_container_image }}' is {{ alertmanager_receiver_state }} + containers.podman.podman_image: + name: "{{ alertmanager_receiver_container_image }}" + state: "{{ alertmanager_receiver_state }}" + pull: "{{ alertmanager_receiver_container_image_source == 'pull' }}" + force: "{{ alertmanager_receiver_container_image_force_source }}" + +- name: Ensure container '{{ alertmanager_receiver_container_name }}' is {{ alertmanager_receiver_container_state }} + containers.podman.podman_container: + name: "{{ alertmanager_receiver_container_name }}" + image: "{{ alertmanager_receiver_container_image }}" + env: "{{ alertmanager_receiver_container_env | default(omit, true) }}" + user: "{{ alertmanager_receiver_container_user | default(omit, true) }}" + ports: "{{ alertmanager_receiver_container_ports }}" + labels: "{{ alertmanager_receiver_container_labels }}" + command: "{{ alertmanager_receiver_container_command | default(omit, true) }}" + volumes: "{{ alertmanager_receiver_container_merged_volumes }}" + network: "{{ alertmanager_receiver_container_networks | default(omit, true) }}" + etc_hosts: "{{ alertmanager_receiver_container_etc_hosts }}" + dns_servers: "{{ alertmanager_receiver_container_dns_servers }}" + restart_policy: "{{ alertmanager_receiver_container_restart_policy }}" + state: "{{ alertmanager_receiver_container_state }}" diff --git a/roles/alertmanager_receiver/tasks/main.yml b/roles/alertmanager_receiver/tasks/main.yml new file mode 100644 index 0000000..6622990 --- /dev/null +++ b/roles/alertmanager_receiver/tasks/main.yml @@ -0,0 +1,22 @@ +--- +- name: Ensure preconditions are met + ansible.builtin.include_tasks: + file: "check.yml" + +- name: Ensure user '{{ alertmanager_receiver_user }}' is {{ alertmanager_receiver_state }} + ansible.builtin.user: + name: "{{ alertmanager_receiver_user }}" + state: "{{ alertmanager_receiver_state }}" + system: "{{ alertmanager_receiver_user_system }}" + create_home: "{{ alertmanager_receiver_user_create_home }}" + groups: "{{ alertmanager_receiver_user_groups | default(omit, true) }}" + append: "{{ alertmanager_receiver_user_append | default(omit) }}" + register: alertmanager_receiver_user_info + +- name: Ensure configuration is up to date + ansible.builtin.include_tasks: + file: "configure.yml" + +- name: Deploy using {{ alertmanager_receiver_deployment_method }} + ansible.builtin.include_tasks: + file: "deploy-{{ alertmanager_receiver_deployment_method }}.yml" diff --git a/roles/alertmanager_receiver/vars/main.yml b/roles/alertmanager_receiver/vars/main.yml new file mode 100644 index 0000000..3a54316 --- /dev/null +++ b/roles/alertmanager_receiver/vars/main.yml @@ -0,0 +1,7 @@ +--- +alertmanager_receiver_states: + - "present" + - "absent" +alertmanager_receiver_deployment_methods: + - "docker" + - "podman"