--- # roles/monitoring_stack/tasks/main.yml # Deploy and configure the complete monitoring stack on Watchtower - name: Resolve focused deployment selection ansible.builtin.set_fact: monitoring_selected_services: >- {{ [monitoring_focus_service] if (monitoring_focus_mode | bool) else [ 'traefik-kop', 'prometheus', 'grafana', 'uptime-kuma', 'node-exporter', 'watchtower-cadvisor', 'blackbox-exporter', 'dozzle', 'authentik-outpost-dozzle', 'loki', 'promtail', 'portainer' ] }} - name: Show selected monitoring services ansible.builtin.debug: msg: - "Focus mode: {{ monitoring_focus_mode | bool }}" - "Selected service set: {{ monitoring_selected_services }}" - name: Validate supported focused service target ansible.builtin.assert: that: - monitoring_focus_service in ['prometheus', 'node-exporter', 'watchtower-cadvisor', 'blackbox-exporter'] fail_msg: >- Unsupported monitoring_focus_service='{{ monitoring_focus_service }}'. Supported focused services: prometheus, node-exporter, watchtower-cadvisor, blackbox-exporter. when: monitoring_focus_mode | bool - name: Validate Grafana admin password is defined ansible.builtin.assert: that: - grafana_admin_password is defined - grafana_admin_password | length > 0 - grafana_admin_password not in ['change-me-now', 'changeme', 'admin', 'password'] fail_msg: "grafana_admin_password must be defined in inventory with a secure value (not a default placeholder)" success_msg: "Grafana password validation passed" when: "'grafana' in monitoring_selected_services" - name: Validate Authentik outpost token is defined ansible.builtin.assert: that: - authentik_outpost_dozzle_token is defined - authentik_outpost_dozzle_token | trim | length > 0 - authentik_outpost_dozzle_token != 'your-authentik-token-here' fail_msg: "authentik_outpost_dozzle_token is required (vault or environment) and cannot be empty" success_msg: "Authentik outpost token validation passed" when: monitoring_enable_authentik_outpost | bool and 'authentik-outpost-dozzle' in monitoring_selected_services no_log: true - name: Create monitoring directories become: true ansible.builtin.file: path: "{{ item }}" state: directory owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0755' loop: - "{{ stack_dir }}" - "{{ stack_dir }}/prometheus-data" - "{{ stack_dir }}/prometheus-config" - "{{ stack_dir }}/prometheus-config/alerts" - "{{ stack_dir }}/grafana-data" - "{{ stack_dir }}/grafana-provisioning" - "{{ stack_dir }}/grafana-provisioning/datasources" - "{{ stack_dir }}/grafana-provisioning/plugins" - "{{ stack_dir }}/grafana-provisioning/alerting" - "{{ stack_dir }}/grafana-provisioning/dashboards" - "{{ stack_dir }}/grafana-provisioning/dashboards/homelab" - "{{ stack_dir }}/uptime-kuma-data" - "{{ stack_dir }}/dozzle-data" - "{{ stack_dir }}/loki-data" - "{{ stack_dir }}/loki-config" - "{{ stack_dir }}/promtail-data" - "{{ stack_dir }}/promtail-config" - "{{ stack_dir }}/blackbox-config" - "{{ stack_dir }}/portainer-data" - "{{ pve_exporter_config_dir }}" - name: Render Prometheus configuration ansible.builtin.template: src: prometheus.yml.j2 dest: "{{ stack_dir }}/prometheus-config/prometheus.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Prometheus alert rules ansible.builtin.template: src: alert-rules.yml.j2 dest: "{{ stack_dir }}/prometheus-config/alerts/homelab.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Grafana datasource provisioning ansible.builtin.template: src: grafana-datasource.yml.j2 dest: "{{ stack_dir }}/grafana-provisioning/datasources/prometheus.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Grafana dashboard provider provisioning ansible.builtin.template: src: grafana-dashboard-provider.yml.j2 dest: "{{ stack_dir }}/grafana-provisioning/dashboards/homelab-provider.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Grafana homelab overview dashboard ansible.builtin.template: src: grafana-homelab-overview.json.j2 dest: "{{ stack_dir }}/grafana-provisioning/dashboards/homelab/homelab-overview.json" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Grafana swarm health dashboard ansible.builtin.template: src: grafana-swarm-health.json.j2 dest: "{{ stack_dir }}/grafana-provisioning/dashboards/homelab/swarm-health.json" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Grafana blackbox reachability dashboard ansible.builtin.template: src: grafana-blackbox-reachability.json.j2 dest: "{{ stack_dir }}/grafana-provisioning/dashboards/homelab/blackbox-reachability.json" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Grafana monitoring coverage dashboard ansible.builtin.template: src: grafana-monitoring-coverage.json.j2 dest: "{{ stack_dir }}/grafana-provisioning/dashboards/homelab/monitoring-coverage.json" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Loki configuration ansible.builtin.template: src: loki-config.yml.j2 dest: "{{ stack_dir }}/loki-config/loki-config.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Promtail configuration ansible.builtin.template: src: promtail-config.yml.j2 dest: "{{ stack_dir }}/promtail-config/promtail-config.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render Blackbox exporter configuration ansible.builtin.template: src: blackbox.yml.j2 dest: "{{ stack_dir }}/blackbox-config/blackbox.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render pve-exporter configuration ansible.builtin.template: src: pve-exporter.yml.j2 dest: "{{ pve_exporter_config_dir }}/pve.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0600' no_log: true notify: Restart monitoring stack - name: Render watchtower compose specification ansible.builtin.template: src: "{{ 'docker-compose.focus.j2' if (monitoring_focus_mode | bool) else 'docker-compose.yml.j2' }}" dest: "{{ stack_dir }}/docker-compose.yml" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0644' notify: Restart monitoring stack - name: Render watchtower environment file ansible.builtin.template: src: env.j2 dest: "{{ stack_dir }}/.env" owner: "{{ chester_user }}" group: "{{ chester_user }}" mode: '0600' no_log: true notify: Restart monitoring stack - name: Launch watchtower monitoring stack community.docker.docker_compose_v2: project_src: "{{ stack_dir }}" state: present pull: always docker_host: "unix:///run/user/1000/docker.sock" remove_orphans: false register: compose_result - name: Display deployed services ansible.builtin.debug: msg: - "🎯 Monitoring Stack Deployed Successfully!" - " Selected services: {{ monitoring_selected_services }}" - " 📊 Prometheus: http://{{ watchtower_ip }}:{{ prometheus_host_port }}" - " 📈 Grafana: {{ 'enabled' if 'grafana' in monitoring_selected_services else 'skipped in focus mode' }}" - " ✅ Uptime Kuma: {{ 'enabled' if 'uptime-kuma' in monitoring_selected_services else 'skipped in focus mode' }}" - " 📋 Dozzle: {{ 'enabled' if 'dozzle' in monitoring_selected_services else 'skipped in focus mode' }}" - " 📝 Loki: {{ 'enabled' if 'loki' in monitoring_selected_services else 'skipped in focus mode' }}" - " 🌐 Blackbox: {{ 'enabled' if 'blackbox-exporter' in monitoring_selected_services else 'skipped in focus mode' }}" - "" - "🔍 Next Steps:" - " 1. Access Grafana and verify Prometheus + Loki datasources" - " 2. Review the '{{ grafana_dashboards_folder }}' dashboard folder" - " 3. Configure Uptime Kuma health checks"