From 88bdbbe88f2db83ef49dea812a25c95596673aee Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 8 May 2026 13:00:53 -0500 Subject: [PATCH] ansible: add 'monitor' role mirroring live monitor.vntx.net (Icinga2 + Web 2) Codifies the bare-metal Icinga2 master + Icinga Web 2 stack on monitor.vntx.net (Ubuntu 22.04, Apache + mod_php, MariaDB 10.6, Icinga 2.16, IDO-MySQL backend). Re-running the role against the live host should produce a near-identical configuration. Role includes: - Icinga apt repo + full package set (icinga2, ido-mysql, icingaweb2, monitoring-plugins, nagios-plugins-contrib, php + apache deps). - MariaDB DB + user provisioning for both icinga2 (IDO daemon) and icingaweb2 (UI), plus a separate read-only `icinga` user that the UI uses to read the IDO. Schema bootstrapped only on first install. - Templated icinga2 config (constants/zones/icinga2.conf), features- enabled symlinks (api/checker/command/ido-mysql/mainlog), and the three secret-bearing conf.d files (api-users, pagerduty x2) wired to vault vars. - 23 dormant conf.d/* host + service definitions copied verbatim under files/. The live install has `include_recursive "conf.d"` commented out (a node-setup CLI artifact); role mirrors that. Set `icinga2_load_confd: true` in host_vars to rehydrate them. - Icinga Web 2 ini files (config/auth/groups/roles/modules) + templated resources.ini for DB credentials. monitoring module enabled via symlink. icingaweb2 admin user bootstrapped on first install via a one-shot insert into icingaweb_user (gated on schema-not-yet-imported). - Apache rewrite + ssl modules. Vhost itself is left to certbot --apache (Let's Encrypt cert is operator-managed, role doesn't manage it). Cluster-wide cleanup: - Gut roles/general/tasks/debian/icinga2.yml down to the uninstall safety net (kept the sweep that removes icinga2 from non-monitoring hosts). The previous master-side install + cert-distribution tasks referenced templates that never existed in the role; the new monitor role replaces them properly. Operator action before first apply: - Create host_vars/monitor.vntx.net/vault.yml with the seven required secrets (see roles/monitor/README.md). Live values can be pulled from /etc/icinga2/conf.d/{api-users,pagerduty-*,ido-mysql}.conf and /etc/icingaweb2/resources.ini on the live host. - Generate the icingaweb2 admin password hash via `php -r 'echo password_hash("plaintext", PASSWORD_DEFAULT);'`. - Run --check --diff before applying; the role is meant to be idempotent but hasn't been verified against the live install. --- ansible/host_vars/monitor.vntx.net.yml | 20 ++ ansible/playbook.yml | 10 + .../roles/general/tasks/debian/icinga2.yml | 135 +-------- ansible/roles/monitor/README.md | 59 ++++ ansible/roles/monitor/defaults/main.yml | 97 +++++++ .../monitor/files/icinga2/conf.d/app.conf | 1 + .../monitor/files/icinga2/conf.d/apt.conf | 7 + .../monitor/files/icinga2/conf.d/checks.conf | 1 + .../files/icinga2/conf.d/commands.conf | 204 +++++++++++++ .../files/icinga2/conf.d/downtimes.conf | 20 ++ .../monitor/files/icinga2/conf.d/groups.conf | 70 +++++ .../files/icinga2/conf.d/hosts-380.conf | 0 .../files/icinga2/conf.d/hosts-494.conf | 17 ++ .../files/icinga2/conf.d/hosts-982.conf | 48 ++++ .../files/icinga2/conf.d/hosts-altoga.conf | 6 + .../files/icinga2/conf.d/hosts-climax.conf | 55 ++++ .../files/icinga2/conf.d/hosts-culleoka.conf | 87 ++++++ .../icinga2/conf.d/hosts-lowrycrossing.conf | 33 +++ .../files/icinga2/conf.d/hosts-newhope.conf | 57 ++++ .../files/icinga2/conf.d/hosts-servers.conf | 12 + .../files/icinga2/conf.d/hosts-verona.conf | 42 +++ .../monitor/files/icinga2/conf.d/hosts.conf | 62 ++++ .../files/icinga2/conf.d/notifications.conf | 33 +++ .../monitor/files/icinga2/conf.d/parents.conf | 5 + .../files/icinga2/conf.d/services.conf | 117 ++++++++ .../files/icinga2/conf.d/templates.conf | 160 +++++++++++ .../files/icinga2/conf.d/timeperiods.conf | 35 +++ .../monitor/files/icinga2/conf.d/users.conf | 23 ++ .../files/icingaweb2/authentication.ini | 3 + .../roles/monitor/files/icingaweb2/config.ini | 11 + .../roles/monitor/files/icingaweb2/groups.ini | 3 + .../modules/monitoring/backends.ini | 3 + .../modules/monitoring/commandtransports.ini | 3 + .../icingaweb2/modules/monitoring/config.ini | 2 + .../roles/monitor/files/icingaweb2/roles.ini | 4 + ansible/roles/monitor/handlers/main.yml | 21 ++ ansible/roles/monitor/tasks/main.yml | 267 ++++++++++++++++++ .../icinga2/conf.d/api-users.conf.j2 | 11 + .../icinga2/conf.d/pagerduty-icinga2.conf.j2 | 91 ++++++ .../conf.d/pagerduty-servers-icinga2.conf.j2 | 91 ++++++ .../templates/icinga2/constants.conf.j2 | 15 + .../features-available/ido-mysql.conf.j2 | 10 + .../monitor/templates/icinga2/icinga2.conf.j2 | 23 ++ .../monitor/templates/icinga2/zones.conf.j2 | 19 ++ .../templates/icingaweb2/resources.ini.j2 | 19 ++ 45 files changed, 1885 insertions(+), 127 deletions(-) create mode 100644 ansible/roles/monitor/README.md create mode 100644 ansible/roles/monitor/defaults/main.yml create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/app.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/apt.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/checks.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/commands.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/downtimes.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/groups.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-380.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-494.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-982.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-altoga.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-climax.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-culleoka.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-lowrycrossing.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-newhope.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-servers.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts-verona.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/hosts.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/notifications.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/parents.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/services.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/templates.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/timeperiods.conf create mode 100644 ansible/roles/monitor/files/icinga2/conf.d/users.conf create mode 100644 ansible/roles/monitor/files/icingaweb2/authentication.ini create mode 100644 ansible/roles/monitor/files/icingaweb2/config.ini create mode 100644 ansible/roles/monitor/files/icingaweb2/groups.ini create mode 100644 ansible/roles/monitor/files/icingaweb2/modules/monitoring/backends.ini create mode 100644 ansible/roles/monitor/files/icingaweb2/modules/monitoring/commandtransports.ini create mode 100644 ansible/roles/monitor/files/icingaweb2/modules/monitoring/config.ini create mode 100644 ansible/roles/monitor/files/icingaweb2/roles.ini create mode 100644 ansible/roles/monitor/handlers/main.yml create mode 100644 ansible/roles/monitor/tasks/main.yml create mode 100644 ansible/roles/monitor/templates/icinga2/conf.d/api-users.conf.j2 create mode 100644 ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-icinga2.conf.j2 create mode 100644 ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-servers-icinga2.conf.j2 create mode 100644 ansible/roles/monitor/templates/icinga2/constants.conf.j2 create mode 100644 ansible/roles/monitor/templates/icinga2/features-available/ido-mysql.conf.j2 create mode 100644 ansible/roles/monitor/templates/icinga2/icinga2.conf.j2 create mode 100644 ansible/roles/monitor/templates/icinga2/zones.conf.j2 create mode 100644 ansible/roles/monitor/templates/icingaweb2/resources.ini.j2 diff --git a/ansible/host_vars/monitor.vntx.net.yml b/ansible/host_vars/monitor.vntx.net.yml index 5fc6964..74545d5 100644 --- a/ansible/host_vars/monitor.vntx.net.yml +++ b/ansible/host_vars/monitor.vntx.net.yml @@ -12,3 +12,23 @@ firewall_allow_rules: - port: 443 proto: tcp comment: HTTPS + - port: 5665 + proto: tcp + comment: Icinga2 API + +# ---- monitor role overrides ---- +icinga2_master_zone_name: master +# Live install has conf.d/* commented out; flip to true to load the +# dormant host/service definitions. +icinga2_load_confd: false + +# Secrets — see roles/monitor/README.md and host_vars/monitor.vntx.net/vault.yml +icinga2_api_user_root_password: "{{ vault_icinga2_api_user_root_password }}" +icinga2_api_user_icingaweb2_password: "{{ vault_icinga2_api_user_icingaweb2_password }}" +icinga2_ido_db_password: "{{ vault_icinga2_ido_db_password }}" +icingaweb2_db_password: "{{ vault_icingaweb2_db_password }}" +icingaweb2_ido_db_password: "{{ vault_icingaweb2_ido_db_password }}" +icinga2_iftraffic_snmp_community: "{{ vault_icinga2_iftraffic_snmp_community }}" +icinga2_pagerduty_key: "{{ vault_icinga2_pagerduty_key }}" +icinga2_pagerduty_servers_key: "{{ vault_icinga2_pagerduty_servers_key }}" +icingaweb2_admin_password_hash: "{{ vault_icingaweb2_admin_password_hash | default('') }}" diff --git a/ansible/playbook.yml b/ansible/playbook.yml index a2edcb9..b33082b 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -42,6 +42,16 @@ roles: - netbox +- name: Install and configure Icinga2 monitor + hosts: monitoring_servers + become: true + gather_facts: true + tags: + - monitor + - icinga2 + roles: + - monitor + - name: Install and configure Caddy hosts: caddy_servers become: true diff --git a/ansible/roles/general/tasks/debian/icinga2.yml b/ansible/roles/general/tasks/debian/icinga2.yml index 912b79b..cec526b 100644 --- a/ansible/roles/general/tasks/debian/icinga2.yml +++ b/ansible/roles/general/tasks/debian/icinga2.yml @@ -1,136 +1,17 @@ -- name: Install icinga2 - apt: - pkg: - - icinga2 - - monitoring-plugins - - nagios-plugins-contrib - update_cache: true - state: latest - cache_valid_time: 3600 - when: "'monitoring_servers' in group_names" - register: icinga2_install - tags: - - icinga2_install +# Master-side install + certificate handling for icinga2 lives in the +# `monitor` role (roles/monitor/). This file used to also include broken +# satellite-cert-distribution tasks (referenced templates that never +# existed); they've been removed. Only the uninstall safety net remains — +# every host outside `monitoring_servers` gets icinga2 removed in case it +# was historically deployed as a client. -- name: Uninstall icinga2 - apt: +- name: Uninstall icinga2 (non-monitor hosts) + ansible.builtin.apt: pkg: - icinga2 - monitoring-plugins - nagios-plugins-contrib state: absent when: "'monitoring_servers' not in group_names" - register: icinga2_uninstall tags: - icinga2_install - -- name: ensure certificate directory exists - file: - path: "{{ base.monitoring.cert_dir }}" - state: directory - owner: 'nagios' - group: 'nagios' - mode: '0700' - when: '"monitoring_servers" in group_names' - tags: - - icinga2_cert_dir - -- name: Check if icinga2 CA certificate exists locally - stat: - path: "{{ playbook_dir }}/roles/general/files/var/lib/icinga2/certs/ca.crt" - delegate_to: localhost - become: false - register: icinga2_ca_cert_local - when: '"monitoring_servers" in group_names' - -- name: install icinga2 CA certificate - copy: - src: var/lib/icinga2/certs/ca.crt - dest: "{{ base.monitoring.cert_dir }}/ca.crt" - owner: 'nagios' - group: 'nagios' - when: - - '"monitoring_servers" in group_names' - - icinga2_ca_cert_local.stat.exists | default(false) - -- name: check for trusted master certificate - stat: - path: "{{ base.monitoring.cert_dir }}/trusted-master.crt }}" - register: trusted_master_cert - when: '"monitoring_servers" in group_names' - -- name: check trusted master certificate hash - shell: - cmd: "openssl x509 -in {{ base.monitoring.cert_dir }}/trusted-master.crt -noout -hash" - register: trusted_master_cert_hash - when: '"monitoring_servers" in group_names and trusted_master_cert.stat.exists' - -- name: delete old certificates - file: - path: "{{ item }}" - state: absent - when: "'monitoring_servers' in group_names and trusted_master_cert.stat.exists and trusted_master_cert_hash.stdout != trusted_master_hash" - loop: - - "{{ base.monitoring.cert_dir }}/trusted-master.crt" - - "{{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.crt" - - "{{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.key" - -- name: get trusted master certificate - shell: - cmd: "icinga2 pki save-cert --trustedcert {{ base.monitoring.cert_dir }}/trusted-master.crt --host {{ base.monitoring.server }}" - when: "'monitoring_servers' in group_names and (not trusted_master_cert.stat.exists or trusted_master_cert_hash.stdout != trusted_master_hash)" - -- name: check for client certificate - stat: - path: "/var/lib/icinga2/certs/{{ inventory_hostname }}.crt" - register: client_certificate - when: '"monitoring_servers" in group_names' - -- name: icinga2 setup - shell: - cmd: "icinga2 node setup --zone {{ inventory_hostname }} --endpoint {{ base.monitoring.server }} --parent_host {{ base.monitoring.server }} --parent_zone master --cn {{ inventory_hostname }} --accept-config --accept-commands --disable-confd --trustedcert {{ base.monitoring.cert_dir }}/trusted-master.crt" - when: "'monitoring_servers' in group_names and not client_certificate.stat.exists" - register: setup - -- name: zones.conf - template: - src: etc/icinga2/zones.conf.j2 - dest: /etc/icinga2/zones.conf - owner: nagios - group: nagios - mode: "0644" - register: zones_config - when: '"monitoring_servers" in group_names' - -- name: icinga2.conf - template: - src: etc/icinga2/icinga2.conf.j2 - dest: /etc/icinga2/icinga2.conf - owner: nagios - group: nagios - mode: "0644" - register: icinga2_config - when: '"monitoring_servers" in group_names' - -- name: checks.conf - template: - src: etc/icinga2/conf.d/checks.conf.j2 - dest: /etc/icinga2/conf.d/checks.conf - owner: nagios - group: nagios - mode: "0644" - register: checks_config - when: '"monitoring_servers" in group_names' - -- name: check if certificate has been signed - shell: - cmd: "openssl x509 -in {{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.crt -noout -issuer_hash -hash | uniq -d | wc -l" - register: signed - when: '"monitoring_servers" in group_names' - -- name: restart icinga2 - service: - name: icinga2 - state: reloaded - enabled: true - when: '"monitoring_servers" in group_names' diff --git a/ansible/roles/monitor/README.md b/ansible/roles/monitor/README.md new file mode 100644 index 0000000..6402b40 --- /dev/null +++ b/ansible/roles/monitor/README.md @@ -0,0 +1,59 @@ +# monitor role + +Builds an Icinga2 master + Icinga Web 2 stack matching the live install on +`monitor.vntx.net`: + +- Ubuntu 22.04 + Apache 2.4 + mod_php + MariaDB 10.6 + Icinga 2.16 +- Single zone, master-only (no satellites configured but `zones.conf` is + templated to add them later) +- IDO-MySQL backend; `icinga2` daemon writes status, `icinga` user + read-only-selects for the Web 2 UI, `icingaweb2` user owns the UI's + own DB +- 25 dormant `conf.d/*` host + service files shipped under `files/` and + copied verbatim. The live install has `include_recursive "conf.d"` + commented out (a node-setup CLI artifact); this role mirrors that. + Set `icinga2_load_confd: true` in host_vars to rehydrate them. + +## Required vault variables + +Encrypt these with `ansible-vault` (e.g. `host_vars/monitor.vntx.net/vault.yml`): + +```yaml +# Icinga API users (api-users.conf) +icinga2_api_user_root_password: "..." +icinga2_api_user_icingaweb2_password: "..." + +# Icinga2 daemon → IDO database +icinga2_ido_db_password: "..." + +# icingaweb2 UI → its own database +icingaweb2_db_password: "..." + +# icingaweb2 UI → IDO database (separate read-only user) +icingaweb2_ido_db_password: "..." + +# Constants +icinga2_iftraffic_snmp_community: "..." +icinga2_ticket_salt: "" # only needed for distributed setups + +# PagerDuty integration keys +icinga2_pagerduty_key: "..." +icinga2_pagerduty_servers_key: "..." + +# icingaweb2 admin user (web UI password). Generate the hash on any host +# with PHP installed: php -r 'echo password_hash("plaintext", PASSWORD_DEFAULT);' +icingaweb2_admin_password_hash: "$2y$10$..." +``` + +## What the role does NOT manage + +- Let's Encrypt certificate provisioning. The live install used `certbot + --apache`; this role assumes the cert already exists at + `/etc/letsencrypt/live//`. Run certbot once by hand. +- The `icingaweb2` schema is imported once on first install. Schema + upgrades after Icinga Web 2 minor version bumps are not handled here — + see `/usr/share/icingaweb2/schema/upgrades/` and run the matching + upgrade SQL by hand. +- Distributed monitoring satellites. The role provisions a single-node + master; add Endpoint/Zone objects in `zones.d/` (or extend + `zones.conf.j2`) when you wire satellites in. diff --git a/ansible/roles/monitor/defaults/main.yml b/ansible/roles/monitor/defaults/main.yml new file mode 100644 index 0000000..9d55f8d --- /dev/null +++ b/ansible/roles/monitor/defaults/main.yml @@ -0,0 +1,97 @@ +--- +# Master Icinga2 + Icinga Web 2 stack. Mirrors the live install on +# monitor.vntx.net (Ubuntu 22.04, Apache + mod_php, MariaDB 10.6, single +# zone, IDO-MySQL backend). Per-host overrides (ALLOWED_HOSTS-equivalent, +# zone names, etc.) live in host_vars; secrets in ansible-vault. + +# Icinga repo + packages +icinga2_apt_key_url: "https://packages.icinga.com/icinga.key" +icinga2_apt_keyring: "/etc/apt/keyrings/icinga-archive-keyring.gpg" +icinga2_apt_repo: "deb [signed-by={{ icinga2_apt_keyring }}] https://packages.icinga.com/ubuntu icinga-{{ ansible_distribution_release }} main" + +icinga2_packages: + - icinga2 + - icinga2-ido-mysql + - monitoring-plugins + - nagios-plugins-contrib + - vim-icinga2 + - icingaweb2 + - icingaweb2-common + - icingacli + - icinga-php-library + - icinga-php-thirdparty + +# Web stack — apache + mod_php (matches live install, not php-fpm). +icinga2_web_packages: + - apache2 + - libapache2-mod-php + - php + - php-curl + - php-gd + - php-intl + - php-ldap + - php-mbstring + - php-mysql + - php-xml + - php-zip + - python3-certbot-apache + +# Database stack +icinga2_db_packages: + - mariadb-server + - mariadb-client + - python3-pymysql # required by community.mysql modules + +# Cluster identity +icinga2_node_name: "{{ inventory_hostname }}" +icinga2_zone_name: "{{ inventory_hostname }}" +icinga2_master_zone_name: "master" + +# Constants — vault-backed +# icinga2_ticket_salt: "" # set in vault if generating signed certs for satellites +# icinga2_iftraffic_snmp_community: "" # vault-only + +# IDO database (icinga2 daemon writes status here) +icinga2_ido_db_host: "localhost" +icinga2_ido_db_name: "icinga2" +icinga2_ido_db_user: "icinga2" +# icinga2_ido_db_password: vault-only + +# icingaweb2 database (UI's own data) +icingaweb2_db_host: "localhost" +icingaweb2_db_name: "icingaweb2" +icingaweb2_db_user: "icingaweb2" +# icingaweb2_db_password: vault-only + +# How icingaweb2 reads the IDO. Live install uses a separate `icinga` user +# rather than reusing `icinga2`; keep that separation. +icingaweb2_ido_db_host: "localhost" +icingaweb2_ido_db_name: "icinga2" +icingaweb2_ido_db_user: "icinga" +# icingaweb2_ido_db_password: vault-only (live install reuses the icingaweb2 +# password; default both the same value in vault unless rotating) + +# Whether to load conf.d/* host/service definitions. Live monitor.vntx.net +# has the include disabled; default to that. Flip to true to rehydrate. +icinga2_load_confd: false + +# IDO schema bootstrap — only runs on first install, gated by a marker. +icinga2_ido_schema_path: /usr/share/icinga2-ido-mysql/schema/mysql.sql + +# Apache vhost (Let's Encrypt managed externally via certbot — this role +# just ensures apache + the icingaweb2 alias config are in place). +icinga2_apache_server_name: "{{ inventory_hostname }}" + +# Features to enable on the master. Order matches live install. +icinga2_enabled_features: + - api + - checker + - command + - ido-mysql + - mainlog + +# icingaweb2 admin user (Web UI password is set as a bcrypt hash directly +# in the icingaweb2 DB; this role bootstraps it on first install). +icingaweb2_admin_user: "graham" +# icingaweb2_admin_password_hash: vault-only — generate with: +# php -r 'echo password_hash("plaintext", PASSWORD_DEFAULT);' diff --git a/ansible/roles/monitor/files/icinga2/conf.d/app.conf b/ansible/roles/monitor/files/icinga2/conf.d/app.conf new file mode 100644 index 0000000..3e4be0d --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/app.conf @@ -0,0 +1 @@ +object IcingaApplication "app" { } diff --git a/ansible/roles/monitor/files/icinga2/conf.d/apt.conf b/ansible/roles/monitor/files/icinga2/conf.d/apt.conf new file mode 100644 index 0000000..6d2bbb9 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/apt.conf @@ -0,0 +1,7 @@ +//apply Service "apt" { +// import "generic-service" +// +// check_command = "apt" +// +// assign where host.name == NodeName +//} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/checks.conf b/ansible/roles/monitor/files/icinga2/conf.d/checks.conf new file mode 100644 index 0000000..c64abf2 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/checks.conf @@ -0,0 +1 @@ +// Managed by Ansible diff --git a/ansible/roles/monitor/files/icinga2/conf.d/commands.conf b/ansible/roles/monitor/files/icinga2/conf.d/commands.conf new file mode 100644 index 0000000..8f56557 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/commands.conf @@ -0,0 +1,204 @@ +/* Command objects */ + +/* Notification Commands + * + * Please check the documentation for all required and + * optional parameters. + */ + +object NotificationCommand "mail-host-notification" { + command = [ ConfigDir + "/scripts/mail-host-notification.sh" ] + + arguments += { + "-4" = "$notification_address$" + "-6" = "$notification_address6$" + "-b" = "$notification_author$" + "-c" = "$notification_comment$" + "-d" = { + required = true + value = "$notification_date$" + } + "-f" = { + value = "$notification_from$" + description = "Set from address. Requires GNU mailutils (Debian/Ubuntu) or mailx (RHEL/SUSE)" + } + "-i" = "$notification_icingaweb2url$" + "-l" = { + required = true + value = "$notification_hostname$" + } + "-n" = { + required = true + value = "$notification_hostdisplayname$" + } + "-o" = { + required = true + value = "$notification_hostoutput$" + } + "-r" = { + required = true + value = "$notification_useremail$" + } + "-s" = { + required = true + value = "$notification_hoststate$" + } + "-t" = { + required = true + value = "$notification_type$" + } + "-v" = "$notification_logtosyslog$" + } + + vars += { + notification_address = "$address$" + notification_address6 = "$address6$" + notification_author = "$notification.author$" + notification_comment = "$notification.comment$" + notification_type = "$notification.type$" + notification_date = "$icinga.long_date_time$" + notification_hostname = "$host.name$" + notification_hostdisplayname = "$host.display_name$" + notification_hostoutput = "$host.output$" + notification_hoststate = "$host.state$" + notification_useremail = "$user.email$" + } +} + +object NotificationCommand "mail-service-notification" { + command = [ ConfigDir + "/scripts/mail-service-notification.sh" ] + + arguments += { + "-4" = "$notification_address$" + "-6" = "$notification_address6$" + "-b" = "$notification_author$" + "-c" = "$notification_comment$" + "-d" = { + required = true + value = "$notification_date$" + } + "-e" = { + required = true + value = "$notification_servicename$" + } + "-f" = { + value = "$notification_from$" + description = "Set from address. Requires GNU mailutils (Debian/Ubuntu) or mailx (RHEL/SUSE)" + } + "-i" = "$notification_icingaweb2url$" + "-l" = { + required = true + value = "$notification_hostname$" + } + "-n" = { + required = true + value = "$notification_hostdisplayname$" + } + "-o" = { + required = true + value = "$notification_serviceoutput$" + } + "-r" = { + required = true + value = "$notification_useremail$" + } + "-s" = { + required = true + value = "$notification_servicestate$" + } + "-t" = { + required = true + value = "$notification_type$" + } + "-u" = { + required = true + value = "$notification_servicedisplayname$" + } + "-v" = "$notification_logtosyslog$" + } + + vars += { + notification_address = "$address$" + notification_address6 = "$address6$" + notification_author = "$notification.author$" + notification_comment = "$notification.comment$" + notification_type = "$notification.type$" + notification_date = "$icinga.long_date_time$" + notification_hostname = "$host.name$" + notification_hostdisplayname = "$host.display_name$" + notification_servicename = "$service.name$" + notification_serviceoutput = "$service.output$" + notification_servicestate = "$service.state$" + notification_useremail = "$user.email$" + notification_servicedisplayname = "$service.display_name$" + } +} + +/* + * If you prefer to use the notification scripts with environment + * variables instead of command line parameters, you can use + * the following commands. They have been updated from < 2.7 + * to support the new notification scripts and should help + * with an upgrade. + * Remove the comment blocks and comment the notification commands above. + */ + +/* + +object NotificationCommand "mail-host-notification" { + command = [ ConfigDir + "/scripts/mail-host-notification.sh" ] + + env = { + NOTIFICATIONTYPE = "$notification.type$" + HOSTDISPLAYNAME = "$host.display_name$" + HOSTNAME = "$host.name$" + HOSTADDRESS = "$address$" + HOSTSTATE = "$host.state$" + LONGDATETIME = "$icinga.long_date_time$" + HOSTOUTPUT = "$host.output$" + NOTIFICATIONAUTHORNAME = "$notification.author$" + NOTIFICATIONCOMMENT = "$notification.comment$" + HOSTDISPLAYNAME = "$host.display_name$" + USEREMAIL = "$user.email$" + } +} + +object NotificationCommand "mail-service-notification" { + command = [ ConfigDir + "/scripts/mail-service-notification.sh" ] + + env = { + NOTIFICATIONTYPE = "$notification.type$" + SERVICENAME = "$service.name$" + HOSTNAME = "$host.name$" + HOSTDISPLAYNAME = "$host.display_name$" + HOSTADDRESS = "$address$" + SERVICESTATE = "$service.state$" + LONGDATETIME = "$icinga.long_date_time$" + SERVICEOUTPUT = "$service.output$" + NOTIFICATIONAUTHORNAME = "$notification.author$" + NOTIFICATIONCOMMENT = "$notification.comment$" + HOSTDISPLAYNAME = "$host.display_name$" + SERVICEDISPLAYNAME = "$service.display_name$" + USEREMAIL = "$user.email$" + } +} + +*/ + +object CheckCommand "check_snmp" { + import "plugin-check-command" + command = [ PluginDir + "/check_snmp" ] + arguments = { + "-H" = "$snmpv3_address$" + "-P" = "$snmp_port$" + "-o" = "$snmpv3_oid$" + "-C" = "$snmp_community$" + "-V" = "$snmp_version$" + "-U" = "$snmpv3_user$" + "-L" = "$snmpv3_seclevel$" + "-a" = "$snmpv3_auth_alg$" + "-x" = "$snmpv3_priv_alg$" + "-A" = "$snmpv3_auth_key$" + "-X" = "$snmpv3_priv_key$" + } +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/downtimes.conf b/ansible/roles/monitor/files/icinga2/conf.d/downtimes.conf new file mode 100644 index 0000000..0bed647 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/downtimes.conf @@ -0,0 +1,20 @@ +/** + * The example downtime apply rule. + */ + +apply ScheduledDowntime "backup-downtime" to Service { + author = "icingaadmin" + comment = "Scheduled downtime for backup" + + ranges = { + monday = service.vars.backup_downtime + tuesday = service.vars.backup_downtime + wednesday = service.vars.backup_downtime + thursday = service.vars.backup_downtime + friday = service.vars.backup_downtime + saturday = service.vars.backup_downtime + sunday = service.vars.backup_downtime + } + + assign where service.vars.backup_downtime != "" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/groups.conf b/ansible/roles/monitor/files/icinga2/conf.d/groups.conf new file mode 100644 index 0000000..dba49f1 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/groups.conf @@ -0,0 +1,70 @@ +/** + * Host group examples. + */ + +object HostGroup "Verona" { + display_name = "Verona" + assign where host.vars.tower == "Verona" +} +object HostGroup "Climax" { + display_name = "Climax" + assign where host.vars.tower == "Climax" +} +object HostGroup "Altoga" { + display_name = "Altoga" + assign where host.vars.tower == "Altoga" +} +object HostGroup "Culleoka" { + display_name = "Culleoka" + assign where host.vars.tower == "Culleoka" +} +object HostGroup "Lowry Crossing" { + display_name = "Lowry Crossing" + assign where host.vars.tower == "Lowry Crossing" +} +object HostGroup "New Hope" { + display_name = "New Hope" + assign where host.vars.tower == "New Hope" +} +object HostGroup "982" { + display_name = "982" + assign where host.vars.tower == "982" +} +object HostGroup "380" { + display_name = "380" + assign where host.vars.tower == "380" +} + +object HostGroup "linux-servers" { + display_name = "Linux Servers" + + assign where host.vars.os == "Linux" +} + +object HostGroup "windows-servers" { + display_name = "Windows Servers" + + assign where host.vars.os == "Windows" +} + +/** + * Service group examples. + */ + +object ServiceGroup "ping" { + display_name = "Ping Checks" + + assign where match("ping*", service.name) +} + +object ServiceGroup "http" { + display_name = "HTTP Checks" + + assign where match("http*", service.check_command) +} + +object ServiceGroup "disk" { + display_name = "Disk Checks" + + assign where match("disk*", service.check_command) +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-380.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-380.conf new file mode 100644 index 0000000..e69de29 diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-494.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-494.conf new file mode 100644 index 0000000..479a408 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-494.conf @@ -0,0 +1,17 @@ +object Host "494-router" { + import "mikrotik" + address = "10.254.254.111" + vars.tower = "494" +} +object Host "494-omni-2.4" { + import "ap-ubnt" + address = "10.10.175.10" + vars.tower = "494" + vars.parents = "10.254.254.111" +} +object Host "494-omni-epmp" { + import "ap-epmp" + address = "10.10.175.11" + vars.tower = "494" + vars.parents = "10.254.254.111" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-982.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-982.conf new file mode 100644 index 0000000..d0486fc --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-982.conf @@ -0,0 +1,48 @@ +object Host "982-router" { + import "mikrotik" + address = "10.254.254.110" + vars.tower = "982" +} + +object Host "982-1" { + import "ap-ubnt" + address = "10.10.63.1" + vars.tower = "982" + vars.parents = "982-router" +} +object Host "982-2" { + import "ap-ubnt" + address = "10.10.63.2" + vars.tower = "982" + vars.parents = "982-router" +} +object Host "982-3" { + import "ap-ubnt" + address = "10.10.63.3" + vars.tower = "982" + vars.parents = "982-router" +} +object Host "982-4" { + import "ap-ubnt" + address = "10.10.63.4" + vars.tower = "982" + vars.parents = "982-router" +} +object Host "982-5" { + import "ap-ubnt" + address = "10.10.63.5" + vars.tower = "982" + vars.parents = "982-router" +} +object Host "982-6" { + import "ap-ubnt" + address = "10.10.63.6" + vars.tower = "982" + vars.parents = "982-router" +} +object Host "982-to-380" { + import "ap-ubnt" + address = "10.250.1.34" + vars.tower = "982" + vars.parents = "982-router" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-altoga.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-altoga.conf new file mode 100644 index 0000000..e7e60da --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-altoga.conf @@ -0,0 +1,6 @@ +//object Host "altoga-verona" { +// import "ap-ubnt" +// address = "10.250.1.149" +// vars.tower = "Altoga" +//} + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-climax.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-climax.conf new file mode 100644 index 0000000..322a5e5 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-climax.conf @@ -0,0 +1,55 @@ +object Host "climax-router" { + import "mikrotik" + address = "10.254.254.102" + vars.tower = "Climax" +} + +object Host "climax-ubnt-nw" { + import "ap-ubnt" + address = "10.10.31.11" + vars.tower = "Climax" + vars.parents = "10.254.254.102" +} +object Host "climax-ubnt-ne" { + import "ap-ubnt" + address = "10.10.31.12" + vars.tower = "Climax" + vars.parents = "10.254.254.102" +} +object Host "climax-ubnt-s" { + import "ap-ubnt" + address = "10.10.31.13" + vars.tower = "Climax" + vars.parents = "10.254.254.102" +} +object Host "climax-epmp-nw" { + import "ap-epmp" + address = "10.10.31.30" + vars.tower = "Climax" + vars.parents = "10.254.254.102" +} +object Host "climax-900-w" { + import "ap-ubnt" + address = "10.10.31.40" + vars.tower = "Climax" + vars.parents = "10.254.254.102" +} + +object Host "climax-core-af24" { + import "af24" + address = "10.250.1.90" + vars.tower = "Climax" + vars.parents = "10.254.254.102" +} +//object Host "climax-verona-af11" { +// import "af11" +// address = "10.250.1.29" +// vars.tower = "Climax" +// vars.parents = "10.254.254.102" +//} +//object Host "climax-culleoka-af11" { +// import "af11" +// address = "10.250.1.13" +// vars.tower = "Climax" +// vars.parents = "10.254.254.102" +//} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-culleoka.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-culleoka.conf new file mode 100644 index 0000000..8477f04 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-culleoka.conf @@ -0,0 +1,87 @@ +object Host "culleoka-router" { + import "mikrotik" + address = "10.254.254.104" + vars.tower = "Culleoka" +} + +object Host "culleoka-ubnt-ac1" { + import "ap-ubnt" + address = "10.10.111.1" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} + +object Host "culleoka-ubnt-ac2" { + import "ap-ubnt" + address = "10.10.111.2" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} + +//object Host "culleoka-ubnt-se" { +// import "ap-ubnt" +// address = "10.10.111.11" +// vars.tower = "Culleoka" +//} +object Host "culleoka-ubnt-sw" { + import "ap-ubnt" + address = "10.10.111.12" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} +object Host "culleoka-n" { + import "ap-ubnt" + address = "10.10.111.14" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} +object Host "culleoka-epmp-n" { + import "ap-epmp" + address = "10.10.111.30" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} +object Host "culleoka-epmp-se" { + import "ap-epmp" + address = "10.10.111.31" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} +object Host "culleoka-epmp-sw" { + import "ap-epmp" + address = "10.10.111.32" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} +object Host "culleoka-epmp-ne" { + import "ap-epmp" + address = "10.10.111.33" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} + +//object Host "culleoka-ac-power" { +// import "generic-host" +// address = "100.64.27.252" +// vars.tower = "Culleoka" +// vars.parents = "10.254.254.104" +//} + +//object Host "culleoka-climax-af11" { +// import "af11" +// address = "10.250.1.10" +// vars.tower = "Culleoka" +// vars.parents = "10.254.254.104" +//} +//object Host "clayton-ap" { +// import "ap-ubnt" +// address = "10.10.111.50" +// vars.tower = "Culleoka" +//} + +object Host "culleoka-clayton-bh" { + import "ap-ubnt" + address = "10.10.111.61" + vars.tower = "Culleoka" + vars.parents = "10.254.254.104" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-lowrycrossing.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-lowrycrossing.conf new file mode 100644 index 0000000..4adedb6 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-lowrycrossing.conf @@ -0,0 +1,33 @@ +object Host "lowrycrossing-router" { + import "mikrotik" + address = "10.254.254.109" + vars.tower = "Lowry Crossing" +} + +object Host "lowrycrossing-omni" { + import "ap-epmp" + address = "10.10.159.10" + vars.tower = "Lowry Crossing" + vars.parents = "10.254.254.109" +} + +object Host "lowrycrossing-ne" { + import "ap-epmp" + address = "10.10.159.11" + vars.tower = "Lowry Crossing" + vars.parents = "10.254.254.109" +} + +object Host "lowrycrossing-n" { + import "ap-epmp" + address = "10.10.159.10" + vars.tower = "Lowry Crossing" + vars.parents = "10.254.254.109" +} + +object Host "lowrycrossing-newhope-af24" { + import "af24" + address = "10.250.1.106" + vars.tower = "Lowry Crossing" + vars.parents = "10.254.254.109" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-newhope.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-newhope.conf new file mode 100644 index 0000000..52a15e6 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-newhope.conf @@ -0,0 +1,57 @@ +object Host "newhope-router" { + import "mikrotik" + address = "10.254.254.108" + vars.tower = "New Hope" +} + +object Host "newhope-se" { + import "ap-epmp" + address = "10.10.143.11" + vars.tower = "New Hope" + vars.parents = "10.254.254.108" +} +object Host "newhope-ne" { + import "ap-epmp" + address = "10.10.143.12" + vars.tower = "New Hope" + vars.parents = "10.254.254.108" +} +object Host "newhope-nw" { + import "ap-epmp" + address = "10.10.143.13" + vars.tower = "New Hope" + vars.parents = "10.254.254.108" +} +object Host "newhope-sw" { + import "ap-epmp" + address = "10.10.143.14" + vars.tower = "New Hope" + vars.parents = "10.254.254.108" +} + +//object Host "newhope-edgepoint" { +// import "edgeswitch" +// address = "100.64.19.250" +// vars.tower = "New Hope" +// vars.parents = "10.254.254.108" +//} +//object Host "newhope-edgepoint2" { +// import "edgeswitch" +// address = "100.64.19.251" +// vars.tower = "New Hope" +// vars.parents = "10.254.254.108" +//} + +object Host "newhope-core-af11" { + import "af11" + address = "10.250.1.58" + vars.tower = "New Hope" + vars.parents = "10.254.254.108" +} + +object Host "newhope-lowrycrossing-af24" { + import "af24" + address = "10.250.1.109" + vars.tower = "New Hope" + vars.parents = "10.254.254.108" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-servers.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-servers.conf new file mode 100644 index 0000000..9cc75b3 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-servers.conf @@ -0,0 +1,12 @@ +//object Host "380power" { +// import "server" +// address = "10.0.0.251" +//} +object Host "t2dallas" { + import "server" + address = "204.110.191.232" +} +object Host "unimus" { + import "server" + address = "204.110.191.238" +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts-verona.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts-verona.conf new file mode 100644 index 0000000..7ea2413 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts-verona.conf @@ -0,0 +1,42 @@ +object Host "verona-router" { + import "mikrotik" + address = "10.254.254.101" + vars.tower = "Verona" +} + +//object Host "verona-nw" { +// import "ap-ubnt" +// address = "10.10.15.11" +// vars.tower = "Verona" +// vars.parents = "10.254.254.101" +//} +//object Host "verona-ne" { +// import "ap-ubnt" +// address = "10.10.15.12" +// vars.tower = "Verona" +// vars.parents = "10.254.254.101" +//} +//object Host "verona-s" { +// import "ap-ubnt" +// address = "10.10.15.13" +// vars.tower = "Verona" +// vars.parents = "10.254.254.101" +//} +//object Host "verona-switch" { +// import "netonix" +// address = "100.64.3.250" +// vars.tower = "Verona" +// vars.parents = "10.254.254.101" +//} +object Host "verona-climax-af11" { + import "af11" + address = "10.250.1.26" + vars.tower = "Verona" + vars.parents = "10.254.254.101" +} +//object Host "verona-altoga" { +// import "ap-ubnt" +// address = "10.250.1.146" +// vars.tower = "Verona" +//} + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/hosts.conf b/ansible/roles/monitor/files/icinga2/conf.d/hosts.conf new file mode 100644 index 0000000..29f0657 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/hosts.conf @@ -0,0 +1,62 @@ +/* + * Host definitions with object attributes + * used for apply rules for Service, Notification, + * Dependency and ScheduledDowntime objects. + * + * Tip: Use `icinga2 object list --type Host` to + * list all host objects after running + * configuration validation (`icinga2 daemon -C`). + */ + +/* + * This is an example host based on your + * local host's FQDN. Specify the NodeName + * constant in `constants.conf` or use your + * own description, e.g. "db-host-1". + */ + +object Host NodeName { + /* Import the default host template defined in `templates.conf`. */ + import "server" + // import "generic-host" + + /* Specify the address attributes for checks e.g. `ssh` or `http`. */ + address = "127.0.0.1" + address6 = "::1" + + vars.pushover_enabled = true + + /* Set custom variable `os` for hostgroup assignment in `groups.conf`. */ + vars.os = "Linux" + + /* Define http vhost attributes for service apply rules in `services.conf`. */ + vars.http_vhosts["http"] = { + http_uri = "/" + } + /* Uncomment if you've sucessfully installed Icinga Web 2. */ + //vars.http_vhosts["Icinga Web 2"] = { + // http_uri = "/icingaweb2" + //} + + /* Define disks and attributes for service apply rules in `services.conf`. */ +// vars.disks["disk"] = { + /* No parameters. */ +// } +// vars.disks["disk /"] = { +// disk_partitions = "/" +// } + + /* Define notification mail attributes for notification apply rules in `notifications.conf`. */ + vars.notification["mail"] = { + /* The UserGroup `icingaadmins` is defined in `users.conf`. */ + groups = [ "icingaadmins" ] + } +} + +/* +apply Dependency “Parent” for (parent in host.vars.parents) to Host { + parent_host_name = parent + assign where host.address && host.vars.parents +} +*/ + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/notifications.conf b/ansible/roles/monitor/files/icinga2/conf.d/notifications.conf new file mode 100644 index 0000000..ac65875 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/notifications.conf @@ -0,0 +1,33 @@ +/** + * The example notification apply rules. + * + * Only applied if host/service objects have + * the custom variable `notification` defined + * and containing `mail` as key. + * + * Check `hosts.conf` for an example. + */ + +apply Notification "mail-icingaadmin" to Host { + import "mail-host-notification" + user_groups = host.vars.notification.mail.groups + users = host.vars.notification.mail.users + + //interval = 2h + + //vars.notification_logtosyslog = true + + assign where host.vars.notification.mail +} + +apply Notification "mail-icingaadmin" to Service { + import "mail-service-notification" + user_groups = host.vars.notification.mail.groups + users = host.vars.notification.mail.users + + //interval = 2h + + //vars.notification_logtosyslog = true + + assign where host.vars.notification.mail +} diff --git a/ansible/roles/monitor/files/icinga2/conf.d/parents.conf b/ansible/roles/monitor/files/icinga2/conf.d/parents.conf new file mode 100644 index 0000000..a686d36 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/parents.conf @@ -0,0 +1,5 @@ +apply Dependency "Parent" for (parent in host.vars.parents) to Host { + parent_host_name = parent + assign where host.address && host.vars.parents +} + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/services.conf b/ansible/roles/monitor/files/icinga2/conf.d/services.conf new file mode 100644 index 0000000..aece77a --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/services.conf @@ -0,0 +1,117 @@ +/* + * Service apply rules. + * + * The CheckCommand objects `ping4`, `ping6`, etc + * are provided by the plugin check command templates. + * Check the documentation for details. + * + * Tip: Use `icinga2 object list --type Service` to + * list all service objects after running + * configuration validation (`icinga2 daemon -C`). + */ + +/* + * This is an example host based on your + * local host's FQDN. Specify the NodeName + * constant in `constants.conf` or use your + * own description, e.g. "db-host-1". + */ + +/* + * These are generic `ping4` and `ping6` + * checks applied to all hosts having the + * `address` resp. `address6` attribute + * defined. + */ +apply Service "ping4" { + import "generic-service" + + check_command = "ping4" + + assign where host.address +} + +apply Service "ping6" { + import "generic-service" + + check_command = "ping6" + + assign where host.address6 +} + +/* + * Apply the `ssh` service to all hosts + * with the `address` attribute defined and + * the custom variable `os` set to `Linux`. + */ +/* +apply Service "ssh" { + import "generic-service" + + check_command = "ssh" + + assign where (host.address || host.address6) && host.vars.os == "Linux" +} +*/ + + + +apply Service for (http_vhost => config in host.vars.http_vhosts) { + import "generic-service" + + check_command = "http" + + vars += config +} + +apply Service for (disk => config in host.vars.disks) { + import "generic-service" + + check_command = "disk" + + vars += config +} + +apply Service "icinga" { + import "generic-service" + + check_command = "icinga" + + assign where host.name == NodeName +} + +apply Service "load" { + import "generic-service" + + check_command = "load" + + /* Used by the ScheduledDowntime apply rule in `downtimes.conf`. */ + vars.backup_downtime = "02:00-03:00" + + assign where host.name == NodeName +} + +//apply Service "procs" { +// import "generic-service" +// +// check_command = "procs" +// +// assign where host.name == NodeName +//} + +apply Service "swap" { + import "generic-service" + + check_command = "swap" + + assign where host.name == NodeName +} + +apply Service "users" { + import "generic-service" + + check_command = "users" + + assign where host.name == NodeName +} + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/templates.conf b/ansible/roles/monitor/files/icinga2/conf.d/templates.conf new file mode 100644 index 0000000..bc52053 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/templates.conf @@ -0,0 +1,160 @@ +/* + * Generic template examples. + */ + + +/** + * Provides default settings for hosts. By convention + * all hosts should import this template. + * + * The CheckCommand object `hostalive` is provided by + * the plugin check command templates. + * Check the documentation for details. + */ +template Host "generic-host" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true + vars.enable_pagerduty_servers = false +} + +template Host "server" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = false + vars.enable_pagerduty_servers = true +} + +template Host "mikrotik" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +template Host "ap-ubnt" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +template Host "netonix" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +template Host "edgeswitch" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +template Host "ap-epmp" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +template Host "af11" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +template Host "af24" { + max_check_attempts = 3 + check_interval = 1m + retry_interval = 30s + + check_command = "hostalive" + vars.enable_pagerduty = true +} + +/** + * Provides default settings for services. By convention + * all services should import this template. + */ +template Service "generic-service" { + max_check_attempts = 5 + check_interval = 1m + retry_interval = 30s + vars.enable_pagerduty = true +} + +/** + * Provides default settings for users. By convention + * all users should inherit from this template. + */ + +template User "generic-user" { + +} + +/** + * Provides default settings for host notifications. + * By convention all host notifications should import + * this template. + */ +template Notification "mail-host-notification" { + command = "mail-host-notification" + + states = [ Up, Down ] + types = [ Problem, Acknowledgement, Recovery, Custom, + FlappingStart, FlappingEnd, + DowntimeStart, DowntimeEnd, DowntimeRemoved ] + + vars += { + // notification_icingaweb2url = "https://www.example.com/icingaweb2" + // notification_from = "Icinga 2 Host Monitoring " + notification_logtosyslog = false + } + + period = "24x7" +} + +/** + * Provides default settings for service notifications. + * By convention all service notifications should import + * this template. + */ +template Notification "mail-service-notification" { + command = "mail-service-notification" + + states = [ OK, Warning, Critical, Unknown ] + types = [ Problem, Acknowledgement, Recovery, Custom, + FlappingStart, FlappingEnd, + DowntimeStart, DowntimeEnd, DowntimeRemoved ] + + vars += { + // notification_icingaweb2url = "https://www.example.com/icingaweb2" + // notification_from = "Icinga 2 Service Monitoring " + notification_logtosyslog = false + } + + period = "24x7" +} + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/timeperiods.conf b/ansible/roles/monitor/files/icinga2/conf.d/timeperiods.conf new file mode 100644 index 0000000..ea162ff --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/timeperiods.conf @@ -0,0 +1,35 @@ +/** + * Sample timeperiods for Icinga 2. + * Check the documentation for details. + */ + +object TimePeriod "24x7" { + display_name = "Icinga 2 24x7 TimePeriod" + ranges = { + "monday" = "00:00-24:00" + "tuesday" = "00:00-24:00" + "wednesday" = "00:00-24:00" + "thursday" = "00:00-24:00" + "friday" = "00:00-24:00" + "saturday" = "00:00-24:00" + "sunday" = "00:00-24:00" + } +} + +object TimePeriod "9to5" { + display_name = "Icinga 2 9to5 TimePeriod" + ranges = { + "monday" = "09:00-17:00" + "tuesday" = "09:00-17:00" + "wednesday" = "09:00-17:00" + "thursday" = "09:00-17:00" + "friday" = "09:00-17:00" + } +} + +object TimePeriod "never" { + display_name = "Icinga 2 never TimePeriod" + ranges = { + } +} + diff --git a/ansible/roles/monitor/files/icinga2/conf.d/users.conf b/ansible/roles/monitor/files/icinga2/conf.d/users.conf new file mode 100644 index 0000000..9dfae03 --- /dev/null +++ b/ansible/roles/monitor/files/icinga2/conf.d/users.conf @@ -0,0 +1,23 @@ +/** + * The example user 'icingaadmin' and the example + * group 'icingaadmins'. + */ + +object User "icingaadmin" { + import "generic-user" + + display_name = "Icinga 2 Admin" + groups = [ "icingaadmins" ] + + email = "root@localhost" +} + +object UserGroup "icingaadmins" { + display_name = "Icinga 2 Admin Group" +} + +object User "graham" { + import "generic-user" + display_name = "Graham" + email = "graham@vntx.net" +} diff --git a/ansible/roles/monitor/files/icingaweb2/authentication.ini b/ansible/roles/monitor/files/icingaweb2/authentication.ini new file mode 100644 index 0000000..6852ece --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/authentication.ini @@ -0,0 +1,3 @@ +[icingaweb2] +backend = "db" +resource = "icingaweb_db" diff --git a/ansible/roles/monitor/files/icingaweb2/config.ini b/ansible/roles/monitor/files/icingaweb2/config.ini new file mode 100644 index 0000000..890a475 --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/config.ini @@ -0,0 +1,11 @@ +[global] +show_stacktraces = "1" +show_application_state_messages = "1" +config_backend = "db" +config_resource = "icingaweb_db" + +[logging] +log = "syslog" +level = "ERROR" +application = "icingaweb2" +facility = "user" diff --git a/ansible/roles/monitor/files/icingaweb2/groups.ini b/ansible/roles/monitor/files/icingaweb2/groups.ini new file mode 100644 index 0000000..6852ece --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/groups.ini @@ -0,0 +1,3 @@ +[icingaweb2] +backend = "db" +resource = "icingaweb_db" diff --git a/ansible/roles/monitor/files/icingaweb2/modules/monitoring/backends.ini b/ansible/roles/monitor/files/icingaweb2/modules/monitoring/backends.ini new file mode 100644 index 0000000..702a1a4 --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/modules/monitoring/backends.ini @@ -0,0 +1,3 @@ +[icinga] +type = "ido" +resource = "icinga_ido" diff --git a/ansible/roles/monitor/files/icingaweb2/modules/monitoring/commandtransports.ini b/ansible/roles/monitor/files/icingaweb2/modules/monitoring/commandtransports.ini new file mode 100644 index 0000000..3d5d591 --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/modules/monitoring/commandtransports.ini @@ -0,0 +1,3 @@ +[icinga2] +transport = "local" +path = "/var/run/icinga2/cmd/icinga2.cmd" diff --git a/ansible/roles/monitor/files/icingaweb2/modules/monitoring/config.ini b/ansible/roles/monitor/files/icingaweb2/modules/monitoring/config.ini new file mode 100644 index 0000000..9b69fe8 --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/modules/monitoring/config.ini @@ -0,0 +1,2 @@ +[security] +protected_customvars = "*pw*,*pass*,community" diff --git a/ansible/roles/monitor/files/icingaweb2/roles.ini b/ansible/roles/monitor/files/icingaweb2/roles.ini new file mode 100644 index 0000000..7fd505d --- /dev/null +++ b/ansible/roles/monitor/files/icingaweb2/roles.ini @@ -0,0 +1,4 @@ +[Administrators] +users = "graham" +permissions = "*" +groups = "Administrators" diff --git a/ansible/roles/monitor/handlers/main.yml b/ansible/roles/monitor/handlers/main.yml new file mode 100644 index 0000000..051d0a2 --- /dev/null +++ b/ansible/roles/monitor/handlers/main.yml @@ -0,0 +1,21 @@ +--- +- name: Restart icinga2 + ansible.builtin.systemd: + name: icinga2 + state: restarted + daemon_reload: true + +- name: Reload apache2 + ansible.builtin.systemd: + name: apache2 + state: reloaded + +- name: Restart apache2 + ansible.builtin.systemd: + name: apache2 + state: restarted + +- name: Restart mariadb + ansible.builtin.systemd: + name: mariadb + state: restarted diff --git a/ansible/roles/monitor/tasks/main.yml b/ansible/roles/monitor/tasks/main.yml new file mode 100644 index 0000000..ed06117 --- /dev/null +++ b/ansible/roles/monitor/tasks/main.yml @@ -0,0 +1,267 @@ +--- +# Builds the Icinga2 master + Icinga Web 2 stack on Ubuntu (matches the +# live install on monitor.vntx.net). Idempotent; safe to re-run. + +- name: Assert required vault values + ansible.builtin.assert: + that: + - icinga2_ido_db_password is defined and icinga2_ido_db_password | length > 0 + - icingaweb2_db_password is defined and icingaweb2_db_password | length > 0 + - icingaweb2_ido_db_password is defined and icingaweb2_ido_db_password | length > 0 + - icinga2_api_user_root_password is defined and icinga2_api_user_root_password | length > 0 + - icinga2_api_user_icingaweb2_password is defined and icinga2_api_user_icingaweb2_password | length > 0 + - icinga2_iftraffic_snmp_community is defined and icinga2_iftraffic_snmp_community | length > 0 + fail_msg: >- + Missing one or more required vault variables for the monitor role. + See roles/monitor/README.md for the full list. + +# ----------- Repo + packages ----------- +- name: Ensure /etc/apt/keyrings exists + ansible.builtin.file: + path: /etc/apt/keyrings + state: directory + mode: "0755" + +- name: Add Icinga apt signing key + ansible.builtin.get_url: + url: "{{ icinga2_apt_key_url }}" + dest: "{{ icinga2_apt_keyring }}" + mode: "0644" + force: false + +- name: Add Icinga apt repository + ansible.builtin.apt_repository: + repo: "{{ icinga2_apt_repo }}" + filename: icinga + state: present + update_cache: true + +- name: Install database stack + ansible.builtin.apt: + name: "{{ icinga2_db_packages }}" + state: present + update_cache: true + +- name: Install web stack + ansible.builtin.apt: + name: "{{ icinga2_web_packages }}" + state: present + +- name: Install Icinga2 + Icinga Web 2 + ansible.builtin.apt: + name: "{{ icinga2_packages }}" + state: present + +# ----------- MariaDB ----------- +- name: Ensure mariadb is started + enabled + ansible.builtin.systemd: + name: mariadb + state: started + enabled: true + +- name: Create IDO database + community.mysql.mysql_db: + name: "{{ icinga2_ido_db_name }}" + state: present + login_unix_socket: /run/mysqld/mysqld.sock + +- name: Create IDO daemon DB user (icinga2) + community.mysql.mysql_user: + name: "{{ icinga2_ido_db_user }}" + host: localhost + password: "{{ icinga2_ido_db_password }}" + priv: "{{ icinga2_ido_db_name }}.*:ALL" + state: present + login_unix_socket: /run/mysqld/mysqld.sock + +- name: Create read-only IDO user for icingaweb2 (icinga) + community.mysql.mysql_user: + name: "{{ icingaweb2_ido_db_user }}" + host: localhost + password: "{{ icingaweb2_ido_db_password }}" + priv: "{{ icingaweb2_ido_db_name }}.*:SELECT,SHOW VIEW" + state: present + login_unix_socket: /run/mysqld/mysqld.sock + +- name: Create icingaweb2 database + community.mysql.mysql_db: + name: "{{ icingaweb2_db_name }}" + state: present + login_unix_socket: /run/mysqld/mysqld.sock + +- name: Create icingaweb2 DB user + community.mysql.mysql_user: + name: "{{ icingaweb2_db_user }}" + host: localhost + password: "{{ icingaweb2_db_password }}" + priv: "{{ icingaweb2_db_name }}.*:ALL" + state: present + login_unix_socket: /run/mysqld/mysqld.sock + +- name: Check whether IDO schema has been imported + community.mysql.mysql_query: + login_db: "{{ icinga2_ido_db_name }}" + query: "SHOW TABLES LIKE 'icinga_dbversion'" + login_unix_socket: /run/mysqld/mysqld.sock + register: ido_schema_check + changed_when: false + +- name: Import IDO schema (first install only) + community.mysql.mysql_db: + name: "{{ icinga2_ido_db_name }}" + state: import + target: "{{ icinga2_ido_schema_path }}" + login_unix_socket: /run/mysqld/mysqld.sock + when: ido_schema_check.rowcount[0] == 0 + notify: Restart icinga2 + +- name: Check whether icingaweb2 schema has been imported + community.mysql.mysql_query: + login_db: "{{ icingaweb2_db_name }}" + query: "SHOW TABLES LIKE 'icingaweb_user'" + login_unix_socket: /run/mysqld/mysqld.sock + register: iweb2_schema_check + changed_when: false + +- name: Import icingaweb2 schema (first install only) + community.mysql.mysql_db: + name: "{{ icingaweb2_db_name }}" + state: import + target: /usr/share/icingaweb2/schema/mysql.schema.sql + login_unix_socket: /run/mysqld/mysqld.sock + when: iweb2_schema_check.rowcount[0] == 0 + +- name: Bootstrap icingaweb2 admin account (first install only) + community.mysql.mysql_query: + login_db: "{{ icingaweb2_db_name }}" + query: >- + INSERT INTO icingaweb_user (name, active, password_hash) VALUES + (%(user)s, 1, %(hash)s) + ON DUPLICATE KEY UPDATE password_hash = VALUES(password_hash) + named_args: + user: "{{ icingaweb2_admin_user }}" + hash: "{{ icingaweb2_admin_password_hash }}" + login_unix_socket: /run/mysqld/mysqld.sock + when: + - iweb2_schema_check.rowcount[0] == 0 + - icingaweb2_admin_password_hash is defined + +# ----------- Icinga2 daemon config ----------- +- name: Render icinga2.conf + ansible.builtin.template: + src: icinga2/icinga2.conf.j2 + dest: /etc/icinga2/icinga2.conf + owner: nagios + group: nagios + mode: "0640" + notify: Restart icinga2 + +- name: Render constants.conf + ansible.builtin.template: + src: icinga2/constants.conf.j2 + dest: /etc/icinga2/constants.conf + owner: nagios + group: nagios + mode: "0640" + notify: Restart icinga2 + +- name: Render zones.conf + ansible.builtin.template: + src: icinga2/zones.conf.j2 + dest: /etc/icinga2/zones.conf + owner: nagios + group: nagios + mode: "0640" + notify: Restart icinga2 + +- name: Render features-available/ido-mysql.conf + ansible.builtin.template: + src: icinga2/features-available/ido-mysql.conf.j2 + dest: /etc/icinga2/features-available/ido-mysql.conf + owner: nagios + group: nagios + mode: "0640" + notify: Restart icinga2 + +- name: Enable Icinga2 features + ansible.builtin.file: + src: "/etc/icinga2/features-available/{{ item }}.conf" + dest: "/etc/icinga2/features-enabled/{{ item }}.conf" + state: link + force: true + loop: "{{ icinga2_enabled_features }}" + notify: Restart icinga2 + +# ----------- conf.d/ host + service definitions ----------- +- name: Sync static conf.d files + ansible.builtin.copy: + src: icinga2/conf.d/ + dest: /etc/icinga2/conf.d/ + owner: nagios + group: nagios + mode: "0640" + notify: Restart icinga2 + +- name: Render templated conf.d files (api-users + pagerduty) + ansible.builtin.template: + src: "icinga2/conf.d/{{ item }}.j2" + dest: "/etc/icinga2/conf.d/{{ item }}" + owner: nagios + group: nagios + mode: "0640" + loop: + - api-users.conf + - pagerduty-icinga2.conf + - pagerduty-servers-icinga2.conf + notify: Restart icinga2 + +# ----------- Icinga Web 2 config ----------- +- name: Sync icingaweb2 ini files (non-secret) + ansible.builtin.copy: + src: icingaweb2/ + dest: /etc/icingaweb2/ + owner: www-data + group: icingaweb2 + mode: "0660" + directory_mode: "02770" + notify: Reload apache2 + +- name: Render icingaweb2 resources.ini (DB credentials) + ansible.builtin.template: + src: icingaweb2/resources.ini.j2 + dest: /etc/icingaweb2/resources.ini + owner: www-data + group: icingaweb2 + mode: "0660" + notify: Reload apache2 + +- name: Enable monitoring module + ansible.builtin.file: + src: /usr/share/icingaweb2/modules/monitoring + dest: /etc/icingaweb2/enabledModules/monitoring + state: link + force: true + notify: Reload apache2 + +# ----------- Apache ----------- +- name: Enable apache modules required by icingaweb2 + community.general.apache2_module: + name: "{{ item }}" + state: present + loop: + - rewrite + - ssl + notify: Restart apache2 + +- name: Ensure apache is started + enabled + ansible.builtin.systemd: + name: apache2 + state: started + enabled: true + +# ----------- Service start ----------- +- name: Ensure icinga2 is started + enabled + ansible.builtin.systemd: + name: icinga2 + state: started + enabled: true diff --git a/ansible/roles/monitor/templates/icinga2/conf.d/api-users.conf.j2 b/ansible/roles/monitor/templates/icinga2/conf.d/api-users.conf.j2 new file mode 100644 index 0000000..93c84f6 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/conf.d/api-users.conf.j2 @@ -0,0 +1,11 @@ +{{ ansible_managed | comment(decoration='// ') }} + +object ApiUser "root" { + password = {{ icinga2_api_user_root_password | to_json }} + permissions = [ "*" ] +} + +object ApiUser "icingaweb2" { + password = {{ icinga2_api_user_icingaweb2_password | to_json }} + permissions = [ "status/query", "actions/*", "objects/modify/*", "objects/query/*" ] +} diff --git a/ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-icinga2.conf.j2 b/ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-icinga2.conf.j2 new file mode 100644 index 0000000..6cad878 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-icinga2.conf.j2 @@ -0,0 +1,91 @@ +object User "pagerduty" { + pager = {{ icinga2_pagerduty_key | to_json }} + groups = [ "icingaadmins" ] + display_name = "PagerDuty Notification User" + states = [ OK, Warning, Critical, Unknown, Up, Down ] + types = [ Problem, Acknowledgement, Recovery ] +} + +object NotificationCommand "notify-service-by-pagerduty" { + import "plugin-notification-command" + command = [ "/usr/share/pdagent-integrations/bin/pd-nagios" ] + arguments = { + "-n" = { + order = 0 + value = "service" + } + "-k" = { + order = 1 + value = "$user.pager$" + } + "-t" = { + order = 2 + value = "$notification.type$" + } + "-f" = { + order = 3 + repeat_key = true + value = "$f_args$" + } + } + + vars.f_args = [ + "SERVICEDESC=$service.name$", + "SERVICEDISPLAYNAME=$service.display_name$", + "HOSTNAME=$host.name$", + "HOSTSTATE=$host.state$", + "HOSTDISPLAYNAME=$host.display_name$", + "SERVICESTATE=$service.state$", + "SERVICEPROBLEMID=$service.state_id$", + "SERVICEOUTPUT=$service.output$" + ] +} + +object NotificationCommand "notify-host-by-pagerduty" { + import "plugin-notification-command" + command = [ "/usr/share/pdagent-integrations/bin/pd-nagios" ] + arguments = { + "-n" = { + order = 0 + value = "host" + } + "-k" = { + order = 1 + value = "$user.pager$" + } + "-t" = { + order = 2 + value = "$notification.type$" + } + "-f" = { + order = 3 + repeat_key = true + value = "$f_args$" + } + } + + vars.f_args = [ + "HOSTNAME=$host.name$", + "HOSTSTATE=$host.state$", + "HOSTPROBLEMID=$host.state_id$", + "HOSTOUTPUT=$host.output$" + ] +} + +apply Notification "pagerduty-service" to Service { + command = "notify-service-by-pagerduty" + states = [ OK, Warning, Critical, Unknown ] + types = [ Problem, Acknowledgement, Recovery ] + period = "24x7" + users = [ "pagerduty" ] + assign where service.vars.enable_pagerduty == true +} + +apply Notification "pagerduty-host" to Host { + command = "notify-host-by-pagerduty" + states = [ Up, Down ] + types = [ Problem, Acknowledgement, Recovery ] + period = "24x7" + users = [ "pagerduty" ] + assign where host.vars.enable_pagerduty == true +} diff --git a/ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-servers-icinga2.conf.j2 b/ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-servers-icinga2.conf.j2 new file mode 100644 index 0000000..4729367 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/conf.d/pagerduty-servers-icinga2.conf.j2 @@ -0,0 +1,91 @@ +object User "pagerduty-servers" { + pager = {{ icinga2_pagerduty_servers_key | to_json }} + groups = [ "icingaadmins" ] + display_name = "PagerDuty Notification User for Servers" + states = [ OK, Warning, Critical, Unknown, Up, Down ] + types = [ Problem, Acknowledgement, Recovery ] +} + +object NotificationCommand "notify-service-by-pagerduty-servers" { + import "plugin-notification-command" + command = [ "/usr/share/pdagent-integrations/bin/pd-nagios" ] + arguments = { + "-n" = { + order = 0 + value = "service" + } + "-k" = { + order = 1 + value = "$user.pager$" + } + "-t" = { + order = 2 + value = "$notification.type$" + } + "-f" = { + order = 3 + repeat_key = true + value = "$f_args$" + } + } + + vars.f_args = [ + "SERVICEDESC=$service.name$", + "SERVICEDISPLAYNAME=$service.display_name$", + "HOSTNAME=$host.name$", + "HOSTSTATE=$host.state$", + "HOSTDISPLAYNAME=$host.display_name$", + "SERVICESTATE=$service.state$", + "SERVICEPROBLEMID=$service.state_id$", + "SERVICEOUTPUT=$service.output$" + ] +} + +object NotificationCommand "notify-host-by-pagerduty-servers" { + import "plugin-notification-command" + command = [ "/usr/share/pdagent-integrations/bin/pd-nagios" ] + arguments = { + "-n" = { + order = 0 + value = "host" + } + "-k" = { + order = 1 + value = "$user.pager$" + } + "-t" = { + order = 2 + value = "$notification.type$" + } + "-f" = { + order = 3 + repeat_key = true + value = "$f_args$" + } + } + + vars.f_args = [ + "HOSTNAME=$host.name$", + "HOSTSTATE=$host.state$", + "HOSTPROBLEMID=$host.state_id$", + "HOSTOUTPUT=$host.output$" + ] +} + +apply Notification "pagerduty-service-servers" to Service { + command = "notify-service-by-pagerduty-servers" + states = [ OK, Warning, Critical, Unknown ] + types = [ Problem, Acknowledgement, Recovery ] + period = "24x7" + users = [ "pagerduty-servers" ] + assign where service.vars.enable_pagerduty_servers == true +} + +apply Notification "pagerduty-host-servers" to Host { + command = "notify-host-by-pagerduty-servers" + states = [ Up, Down ] + types = [ Problem, Acknowledgement, Recovery ] + period = "24x7" + users = [ "pagerduty-servers" ] + assign where host.vars.enable_pagerduty_servers == true +} diff --git a/ansible/roles/monitor/templates/icinga2/constants.conf.j2 b/ansible/roles/monitor/templates/icinga2/constants.conf.j2 new file mode 100644 index 0000000..3075999 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/constants.conf.j2 @@ -0,0 +1,15 @@ +{{ ansible_managed | comment(decoration='// ') }} +// +// Global constants. The TicketSalt and IftrafficSnmpCommunity values come +// from ansible-vault — see roles/monitor/README.md. + +const PluginDir = "/usr/lib/nagios/plugins" +const ManubulonPluginDir = "/usr/lib/nagios/plugins" +const PluginContribDir = "/usr/lib/nagios/plugins" + +const NodeName = {{ icinga2_node_name | to_json }} +const ZoneName = {{ icinga2_zone_name | to_json }} + +const TicketSalt = {{ icinga2_ticket_salt | default("") | to_json }} + +const IftrafficSnmpCommunity = {{ icinga2_iftraffic_snmp_community | to_json }} diff --git a/ansible/roles/monitor/templates/icinga2/features-available/ido-mysql.conf.j2 b/ansible/roles/monitor/templates/icinga2/features-available/ido-mysql.conf.j2 new file mode 100644 index 0000000..da63296 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/features-available/ido-mysql.conf.j2 @@ -0,0 +1,10 @@ +{{ ansible_managed | comment(decoration=' * ', prefix='/**', postfix=' */') }} + +library "db_ido_mysql" + +object IdoMysqlConnection "ido-mysql" { + user = {{ icinga2_ido_db_user | to_json }}, + password = {{ icinga2_ido_db_password | to_json }}, + host = {{ icinga2_ido_db_host | to_json }}, + database = {{ icinga2_ido_db_name | to_json }} +} diff --git a/ansible/roles/monitor/templates/icinga2/icinga2.conf.j2 b/ansible/roles/monitor/templates/icinga2/icinga2.conf.j2 new file mode 100644 index 0000000..9608698 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/icinga2.conf.j2 @@ -0,0 +1,23 @@ +{{ ansible_managed | comment(decoration=' * ', prefix='/**', postfix=' */') }} + +include "constants.conf" +include "zones.conf" + +include +include +include +include +include +include + +include "features-enabled/*.conf" + +{% if icinga2_load_confd %} +// conf.d/ host + service definitions. Live monitor.vntx.net keeps this +// commented out (the node-setup CLI disabled it during a past distributed +// monitoring rework). Set `icinga2_load_confd: true` in host_vars to +// rehydrate the dormant definitions; default mirrors the live empty state. +include_recursive "conf.d" +{% else %} +// include_recursive "conf.d" // disabled to match live state +{% endif %} diff --git a/ansible/roles/monitor/templates/icinga2/zones.conf.j2 b/ansible/roles/monitor/templates/icinga2/zones.conf.j2 new file mode 100644 index 0000000..88c7e12 --- /dev/null +++ b/ansible/roles/monitor/templates/icinga2/zones.conf.j2 @@ -0,0 +1,19 @@ +{{ ansible_managed | comment(decoration='// ') }} +// +// Zone topology. This is currently a single-master setup; satellites can be +// added by appending Endpoint+Zone objects here (and a parent= ref). + +object Endpoint {{ icinga2_node_name | to_json }} { +} + +object Zone {{ icinga2_master_zone_name | to_json }} { + endpoints = [ {{ icinga2_node_name | to_json }} ] +} + +object Zone "global-templates" { + global = true +} + +object Zone "director-global" { + global = true +} diff --git a/ansible/roles/monitor/templates/icingaweb2/resources.ini.j2 b/ansible/roles/monitor/templates/icingaweb2/resources.ini.j2 new file mode 100644 index 0000000..a341542 --- /dev/null +++ b/ansible/roles/monitor/templates/icingaweb2/resources.ini.j2 @@ -0,0 +1,19 @@ +; {{ ansible_managed }} + +[icingaweb_db] +type = "db" +db = "mysql" +host = "{{ icingaweb2_db_host }}" +dbname = "{{ icingaweb2_db_name }}" +username = "{{ icingaweb2_db_user }}" +password = "{{ icingaweb2_db_password }}" +use_ssl = "0" + +[icinga_ido] +type = "db" +db = "mysql" +host = "{{ icingaweb2_ido_db_host }}" +dbname = "{{ icingaweb2_ido_db_name }}" +username = "{{ icingaweb2_ido_db_user }}" +password = "{{ icingaweb2_ido_db_password }}" +use_ssl = "0"