diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index 4f2cfa6a..976a0de1 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -1410,6 +1410,27 @@ matrix_prometheus_container_http_host_bind_port: "{{ '' if matrix_nginx_proxy_en +###################################################################### +# +# matrix-grafana +# +###################################################################### + +matrix_grafana_enabled: false + +# Normally, matrix-nginx-proxy is enabled and nginx can reach Grafana over the container network. +# If matrix-nginx-proxy is not enabled, or you otherwise have a need for it, you can expose +# Grafana's HTTP port to the local host. +matrix_grafana_container_http_host_bind_port: "{{ '' if matrix_nginx_proxy_enabled else '127.0.0.1:3000' }}" + +###################################################################### +# +# /matrix-grafana +# +###################################################################### + + + ###################################################################### # # matrix-registration diff --git a/roles/matrix-grafana/defaults/main.yml b/roles/matrix-grafana/defaults/main.yml new file mode 100644 index 00000000..2257d794 --- /dev/null +++ b/roles/matrix-grafana/defaults/main.yml @@ -0,0 +1,47 @@ +# matrix-grafana is open source visualization and analytics software +# See: https://github.com/matrix-org/synapse/blob/master/docs/metrics-howto.md + +matrix_grafana_enabled: false + +matrix_grafana_docker_image: "docker.io/grafana/grafana:7.3.7" +matrix_grafana_docker_image_force_pull: "{{ matrix_grafana_docker_image.endswith(':latest') }}" + +# Not conditional, because when someone disables metrics +# they might still want to look at the old existing data. +# So it would be silly to delete the dashboard in such case. +matrix_grafana_dashboard_download_urls: +- "https://raw.githubusercontent.com/matrix-org/synapse/master/contrib/grafana/synapse.json" +- "https://raw.githubusercontent.com/rfrail3/grafana-dashboards/master/prometheus/node-exporter-full.json" + +matrix_grafana_base_path: "{{ matrix_base_data_path }}/grafana" +matrix_grafana_config_path: "{{ matrix_grafana_base_path }}/config" +matrix_grafana_data_path: "{{ matrix_grafana_base_path }}/data" + +# Allow viewing Grafana without logging in +matrix_grafana_anonymous_access: false + +# specify organization name that should be used for unauthenticated users +# if you change this in the Grafana admin panel, this needs to be updated +# to match to keep anonymous logins working +matrix_grafana_anonymous_access_org_name: 'Main Org.' + + +# default admin credentials, you are asked to change these on first login +matrix_grafana_default_admin_user: admin +matrix_grafana_default_admin_password: admin + +# A list of extra arguments to pass to the container +matrix_grafana_container_extra_arguments: [] + +# List of systemd services that matrix-grafana.service depends on +matrix_grafana_systemd_required_services_list: ['docker.service'] + +# List of systemd services that matrix-grafana.service wants +matrix_grafana_systemd_wanted_services_list: [] + +# Controls whether the matrix-grafana container exposes its HTTP port (tcp/3000 in the container). +# +# Takes an ":" or "" value (e.g. "127.0.0.1:3000"), or empty string to not expose. +matrix_grafana_container_http_host_bind_port: '' + + diff --git a/roles/matrix-grafana/tasks/init.yml b/roles/matrix-grafana/tasks/init.yml new file mode 100644 index 00000000..8a22e301 --- /dev/null +++ b/roles/matrix-grafana/tasks/init.yml @@ -0,0 +1,5 @@ +- set_fact: + matrix_systemd_services_list: "{{ matrix_systemd_services_list + ['matrix-grafana.service'] }}" + when: matrix_grafana_enabled|bool + + diff --git a/roles/matrix-grafana/tasks/main.yml b/roles/matrix-grafana/tasks/main.yml new file mode 100644 index 00000000..122ec65e --- /dev/null +++ b/roles/matrix-grafana/tasks/main.yml @@ -0,0 +1,14 @@ +- import_tasks: "{{ role_path }}/tasks/init.yml" + tags: + - always + +- import_tasks: "{{ role_path }}/tasks/validate_config.yml" + when: run_setup|bool + tags: + - setup-all + - setup-grafana + +- import_tasks: "{{ role_path }}/tasks/setup.yml" + tags: + - setup-all + - setup-grafana diff --git a/roles/matrix-grafana/tasks/setup.yml b/roles/matrix-grafana/tasks/setup.yml new file mode 100644 index 00000000..581e6617 --- /dev/null +++ b/roles/matrix-grafana/tasks/setup.yml @@ -0,0 +1,115 @@ +--- + +# +# Tasks related to setting up matrix-grafana +# + +- name: Ensure matrix-grafana image is pulled + docker_image: + name: "{{ matrix_grafana_docker_image }}" + source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}" + force_source: "{{ matrix_grafana_docker_image_force_pull if ansible_version.major > 2 or ansible_version.minor >= 8 else omit }}" + force: "{{ omit if ansible_version.major > 2 or ansible_version.minor >= 8 else matrix_grafana_docker_image_force_pull }}" + when: "matrix_grafana_enabled|bool" + +- name: Ensure grafana paths exists + file: + path: "{{ item }}" + state: directory + mode: 0750 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + with_items: + - "{{ matrix_grafana_base_path }}" + - "{{ matrix_grafana_config_path }}" + - "{{ matrix_grafana_config_path }}/provisioning" + - "{{ matrix_grafana_config_path }}/provisioning/datasources" + - "{{ matrix_grafana_config_path }}/provisioning/dashboards" + - "{{ matrix_grafana_config_path }}/dashboards" + - "{{ matrix_grafana_data_path }}" + when: matrix_grafana_enabled|bool + +- name: Ensure grafana.ini present + template: + src: "{{ role_path }}/templates/grafana.ini.j2" + dest: "{{ matrix_grafana_config_path }}/grafana.ini" + mode: 0440 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + when: matrix_grafana_enabled|bool + +- name: Ensure provisioning/datasources/default.yaml present + template: + src: "{{ role_path }}/templates/datasources.yaml.j2" + dest: "{{ matrix_grafana_config_path }}/provisioning/datasources/default.yaml" + mode: 0440 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + when: matrix_grafana_enabled|bool + +- name: Ensure provisioning/dashboards/default.yaml present + template: + src: "{{ role_path }}/templates/dashboards.yaml.j2" + dest: "{{ matrix_grafana_config_path }}/provisioning/dashboards/default.yaml" + mode: 0440 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + when: matrix_grafana_enabled|bool + +- name: Ensure dashboard(s) downloaded + get_url: + url: "{{ item }}" + dest: "{{ matrix_grafana_config_path }}/dashboards/" + force: true + mode: 0440 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + with_items: "{{ matrix_grafana_dashboard_download_urls }}" + when: matrix_grafana_enabled|bool + +- name: Ensure matrix-grafana.service installed + template: + src: "{{ role_path }}/templates/systemd/matrix-grafana.service.j2" + dest: "{{ matrix_systemd_path }}/matrix-grafana.service" + mode: 0644 + register: matrix_grafana_systemd_service_result + when: matrix_grafana_enabled|bool + +- name: Ensure systemd reloaded after matrix-grafana.service installation + service: + daemon_reload: yes + when: "matrix_grafana_enabled|bool and matrix_grafana_systemd_service_result.changed" + +# +# Tasks related to getting rid of matrix-grafana (if it was previously enabled) +# + +- name: Check existence of matrix-grafana service + stat: + path: "{{ matrix_systemd_path }}/matrix-grafana.service" + register: matrix_grafana_service_stat + +- name: Ensure matrix-grafana is stopped + service: + name: matrix-grafana + state: stopped + daemon_reload: yes + register: stopping_result + when: "not matrix_grafana_enabled|bool and matrix_grafana_service_stat.stat.exists" + +- name: Ensure matrix-grafana.service doesn't exist + file: + path: "{{ matrix_systemd_path }}/matrix-grafana.service" + state: absent + when: "not matrix_grafana_enabled|bool and matrix_grafana_service_stat.stat.exists" + +- name: Ensure systemd reloaded after matrix-grafana.service removal + service: + daemon_reload: yes + when: "not matrix_grafana_enabled|bool and matrix_grafana_service_stat.stat.exists" + +- name: Ensure matrix-grafana Docker image doesn't exist + docker_image: + name: "{{ matrix_grafana_docker_image }}" + state: absent + when: "not matrix_grafana_enabled|bool" diff --git a/roles/matrix-grafana/tasks/validate_config.yml b/roles/matrix-grafana/tasks/validate_config.yml new file mode 100644 index 00000000..63d4919a --- /dev/null +++ b/roles/matrix-grafana/tasks/validate_config.yml @@ -0,0 +1,7 @@ +--- + +- name: Fail if Prometheus not enabled + fail: + msg: > + You need to enable `matrix_prometheus_enabled` to use Prometheus as data source for Grafana. + when: "not matrix_prometheus_enabled" diff --git a/roles/matrix-grafana/templates/dashboards.yaml.j2 b/roles/matrix-grafana/templates/dashboards.yaml.j2 new file mode 100644 index 00000000..b6662e59 --- /dev/null +++ b/roles/matrix-grafana/templates/dashboards.yaml.j2 @@ -0,0 +1,9 @@ +apiVersion: 1 + +providers: + - name: {{ matrix_domain }} - Dashboards + folder: '' # The folder where to place the dashboards + type: file + allowUiUpdates: true + options: + path: /etc/grafana/dashboards diff --git a/roles/matrix-grafana/templates/datasources.yaml.j2 b/roles/matrix-grafana/templates/datasources.yaml.j2 new file mode 100644 index 00000000..ffa6046b --- /dev/null +++ b/roles/matrix-grafana/templates/datasources.yaml.j2 @@ -0,0 +1,8 @@ +apiVersion: 1 + +datasources: + - name: {{ matrix_domain }} - Prometheus + type: prometheus + # Access mode - proxy (server in the UI) or direct (browser in the UI). + access: proxy + url: http://matrix-prometheus:9090 diff --git a/roles/matrix-grafana/templates/grafana.ini.j2 b/roles/matrix-grafana/templates/grafana.ini.j2 new file mode 100644 index 00000000..694bf7d7 --- /dev/null +++ b/roles/matrix-grafana/templates/grafana.ini.j2 @@ -0,0 +1,20 @@ +[security] +# default admin user, created on startup +admin_user = {{ matrix_grafana_default_admin_user }} + +# default admin password, can be changed before first start of grafana, or in profile settings +admin_password = {{ matrix_grafana_default_admin_password }} + +[auth.anonymous] +# enable anonymous access +enabled = {{ matrix_grafana_anonymous_access }} + +# specify organization name that should be used for unauthenticated users +org_name = {{ matrix_grafana_anonymous_access_org_name }} + +[dashboards] +{% if matrix_synapse_metrics_enabled %} +default_home_dashboard_path = /etc/grafana/dashboards/synapse.json +{% else %} +default_home_dashboard_path = /etc/grafana/dashboards/node-exporter-full.json +{% endif %} diff --git a/roles/matrix-grafana/templates/systemd/matrix-grafana.service.j2 b/roles/matrix-grafana/templates/systemd/matrix-grafana.service.j2 new file mode 100644 index 00000000..f2ab6642 --- /dev/null +++ b/roles/matrix-grafana/templates/systemd/matrix-grafana.service.j2 @@ -0,0 +1,42 @@ +#jinja2: lstrip_blocks: "True" +[Unit] +Description=matrix-grafana +{% for service in matrix_grafana_systemd_required_services_list %} +Requires={{ service }} +After={{ service }} +{% endfor %} +{% for service in matrix_grafana_systemd_wanted_services_list %} +Wants={{ service }} +{% endfor %} +DefaultDependencies=no + +[Service] +Type=simple +Environment="HOME={{ matrix_systemd_unit_home_path }}" +ExecStartPre=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} kill matrix-grafana 2>/dev/null' +ExecStartPre=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} rm matrix-grafana 2>/dev/null' + + +ExecStart={{ matrix_host_command_docker }} run --rm --name matrix-grafana \ + --log-driver=none \ + --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ + --cap-drop=ALL \ + --network={{ matrix_docker_network }} \ + {% if matrix_grafana_container_http_host_bind_port %} + -p {{ matrix_grafana_container_http_host_bind_port }}:3000 \ + {% endif %} + -v {{ matrix_grafana_config_path }}:/etc/grafana:z \ + -v {{ matrix_grafana_data_path }}:/var/lib/grafana:z \ + {% for arg in matrix_grafana_container_extra_arguments %} + {{ arg }} \ + {% endfor %} + {{ matrix_grafana_docker_image }} + +ExecStop=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} kill matrix-grafana 2>/dev/null' +ExecStop=-{{ matrix_host_command_sh }} -c '{{ matrix_host_command_docker }} rm matrix-grafana 2>/dev/null' +Restart=always +RestartSec=30 +SyslogIdentifier=matrix-grafana + +[Install] +WantedBy=multi-user.target diff --git a/setup.yml b/setup.yml index 838e08c8..e7fdae19 100755 --- a/setup.yml +++ b/setup.yml @@ -30,6 +30,7 @@ - matrix-synapse-admin - matrix-prometheus-node-exporter - matrix-prometheus + - matrix-grafana - matrix-registration - matrix-client-element - matrix-jitsi