--- # Both exporters listen on all addresses; host_firewall limits who reaches them. # Its recommends (smartmontools, nvme-cli, ipmitool) start units that fail on hosts without such hardware. - name: Install the node exporter ansible.builtin.apt: name: prometheus-node-exporter install_recommends: false state: present - name: Enable the node exporter ansible.builtin.systemd: name: prometheus-node-exporter enabled: true state: started # Check mode does not install the package. ignore_errors: "{{ ansible_check_mode }}" - name: Install the smartctl exporter when: host_exporters_smart block: - name: Look for an existing backports source ansible.builtin.shell: >- grep -rEqs '^[^#]*{{ ansible_distribution_release }}-backports' --include='*.list' --include='*.sources' --exclude=host-exporters-backports.sources /etc/apt register: host_exporters_backports changed_when: false failed_when: host_exporters_backports.rc > 1 check_mode: false # Backports stay at priority 100, so only packages named with default_release come from there. - name: Add the backports source ansible.builtin.copy: dest: /etc/apt/sources.list.d/host-exporters-backports.sources mode: "0644" content: | Types: deb URIs: http://deb.debian.org/debian Suites: {{ ansible_distribution_release }}-backports Components: main Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg register: host_exporters_source when: host_exporters_backports.rc == 1 # The module rejects default_release while the release is missing from its package cache. - name: Look for the backports release in the package lists ansible.builtin.shell: apt-cache policy | grep -q 'n={{ ansible_distribution_release }}-backports' register: host_exporters_lists changed_when: false failed_when: false check_mode: false - name: Refresh the package lists for the backports source ansible.builtin.apt: update_cache: true when: host_exporters_lists.rc != 0 - name: Install the smartctl exporter from backports ansible.builtin.apt: name: prometheus-smartctl-exporter default_release: "{{ ansible_distribution_release }}-backports" state: present # Check mode does not write the backports source. ignore_errors: "{{ ansible_check_mode }}" # The packaged unit runs as root, which smartctl needs for the disks. - name: Enable the smartctl exporter ansible.builtin.systemd: name: smartctl_exporter enabled: true state: started ignore_errors: "{{ ansible_check_mode }}" # Reads the BMC through /dev/ipmi0, read-only: no raw commands, no configuration. # FreeIPMI refuses in-band access for any uid but 0, so the exporter runs as the packaged # unprivileged user prometheus and starts the FreeIPMI tools it needs through sudo. - name: Install the IPMI exporter when: host_exporters_ipmi block: - name: Install ipmitool and the IPMI exporter ansible.builtin.apt: name: - ipmitool - sudo - prometheus-ipmi-exporter install_recommends: false state: present - name: Allow the exporter user to run the FreeIPMI tools ansible.builtin.copy: dest: /etc/sudoers.d/prometheus-ipmi-exporter mode: "0440" validate: visudo -cf %s content: | Defaults:prometheus !log_allowed, !pam_session {% for collector in host_exporters_ipmi_collectors %} prometheus ALL = (root) NOPASSWD: /usr/sbin/{{ host_exporters_ipmi_tools[collector].tool }} {{ host_exporters_ipmi_tools[collector].args }} --config-file /tmp/ipmi_exporter-{{ '[0-9a-f]' * 32 }} {% endfor %} register: host_exporters_ipmi_sudo # collector_cmd replaces the tool itself, so each collector gets a wrapper that adds sudo. - name: Create the sudo wrappers directory ansible.builtin.file: path: /usr/local/libexec/ipmi-exporter state: directory mode: "0755" - name: Write the sudo wrappers ansible.builtin.copy: dest: /usr/local/libexec/ipmi-exporter/{{ item.key }} mode: "0755" content: | #!/bin/sh exec sudo -n /usr/sbin/{{ item.value.tool }} "$@" loop: "{{ host_exporters_ipmi_tools | dict2items | selectattr('key', 'in', host_exporters_ipmi_collectors) | list }}" loop_control: label: "{{ item.key }}" register: host_exporters_ipmi_wrappers - name: Write the IPMI exporter configuration ansible.builtin.copy: dest: /etc/prometheus/ipmi-local.yml mode: "0644" content: | modules: default: collectors: {% for collector in host_exporters_ipmi_collectors %} - {{ collector }} {% endfor %} collector_cmd: {% for collector in host_exporters_ipmi_collectors %} {{ collector }}: /usr/local/libexec/ipmi-exporter/{{ collector }} {% endfor %} register: host_exporters_ipmi_config - name: Create the IPMI exporter unit drop-in directory ansible.builtin.file: path: /etc/systemd/system/prometheus-ipmi-exporter.service.d state: directory mode: "0755" # sudo needs setuid, so NoNewPrivileges stays off. - name: Run the IPMI exporter with that configuration ansible.builtin.copy: dest: /etc/systemd/system/prometheus-ipmi-exporter.service.d/local.conf mode: "0644" content: | [Service] ExecStart= ExecStart=/usr/bin/prometheus-ipmi-exporter --config.file=/etc/prometheus/ipmi-local.yml register: host_exporters_ipmi_unit - name: Enable the IPMI exporter ansible.builtin.systemd: name: prometheus-ipmi-exporter enabled: true state: "{{ 'restarted' if (host_exporters_ipmi_config.changed or host_exporters_ipmi_unit.changed or host_exporters_ipmi_wrappers.changed) else 'started' }}" daemon_reload: true ignore_errors: "{{ ansible_check_mode }}"