TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/wikioasis/salt/llms.txt
Use this file to discover all available pages before exploring further.
monitoring state provisions the dedicated monitoring server with the full WikiOasis observability stack — Icinga2 for active checks and alerting, Prometheus for metrics collection, and Grafana for dashboards. It is applied exclusively to hosts matching monitoring* in top.sls, alongside monitoring.prometheus, monitoring.grafana, monitoring.nrpe_nginx, and monitoring.statsd_exporter.
Icinga2 + Icingaweb2
Active checks, IDO-MySQL backend, Director module, and Nginx/PHP-FPM front-end
Prometheus
Metric scraping with
file_sd auto-discovery. All targets registered from the dns_hosts pillarGrafana
Dashboard server pre-configured with a Prometheus datasource and served behind Nginx
Packages installed
monitoring/init.sls installs the following packages after adding the official Icinga apt repository and running apt-get install -f to fix any broken dependencies.
Full package list
Full package list
| Package | Purpose |
|---|---|
icinga2 | Monitoring and alerting engine |
icinga2-ido-mysql | IDO MySQL back-end for Icinga2 |
icingaweb2 | Web UI for Icinga2 |
icingacli | CLI tool for Icingaweb2 management |
icinga-director | Config management module for Icingaweb2 |
mariadb-server / mariadb-client | Local database for IDO and Icingaweb2 |
nginx | Reverse proxy for Icingaweb2 and Grafana |
php-fpm | PHP FastCGI process manager |
php-mysql, php-intl, php-curl, php-gd, php-mbstring, php-xml | PHP extensions required by Icingaweb2 |
nagios-nrpe-plugin | NRPE check runner on the monitoring server itself |
jq, curl | Used by notification scripts |
On Debian Trixie the state falls back to the
icinga-bookworm repository because Icinga does not yet publish a Trixie-specific repository. The icinga_dist variable is resolved at render time from grains['oscodename'].Icinga2 configuration
APT repository
The GPG key is fetched from
https://packages.icinga.com/icinga.key, dearmored into /usr/share/keyrings/icinga-archive-keyring.gpg, and the source line is written to /etc/apt/sources.list.d/icinga.list. A cmd.run guard (creates:) ensures the key is only imported once.zones.conf
/etc/icinga2/zones.conf is rendered from salt://monitoring/files/icinga2/zones.conf.jinja. It creates a single Endpoint and Zone named master using the minion ID (grains['id']).zones.conf.jinja
API feature (api.conf)
/etc/icinga2/features-available/api.conf is rendered from api.conf.jinja. It creates an ApiUser with full permissions and enables command/config acceptance. The feature is enabled with icinga2 feature enable api.api.conf.jinja
IDO-MySQL feature (ido-mysql.conf)
/etc/icinga2/features-available/ido-mysql.conf is rendered from ido-mysql.conf.jinja. Pillar values for ido_db_name, ido_db_user, and the IDO password (from private pillar) are injected. The feature is enabled with icinga2 feature enable ido-mysql.ido-mysql.conf.jinja
Notification feature
The
notification feature is enabled via icinga2 feature enable notification. A creates: guard prevents re-running once /etc/icinga2/features-enabled/notification.conf exists.Default conf.d cleanup
The four default configuration files that ship with
icinga2 are removed to prevent conflicts with the Salt-managed host and service objects:/etc/icinga2/conf.d/hosts.conf/etc/icinga2/conf.d/services.conf/etc/icinga2/conf.d/users.conf/etc/icinga2/conf.d/notifications.conf
notification-commands.conf
Four
NotificationCommand objects are written to /etc/icinga2/conf.d/notification-commands.conf — one each for Discord and Slack host/service notifications. Each command invokes a shell script under /etc/icinga2/scripts/ and passes context via environment variables.notification-commands.conf (excerpt)
salt-hosts.conf (dynamic host objects)
/etc/icinga2/conf.d/salt-hosts.conf is rendered from salt-hosts.conf.jinja. It iterates the dns_hosts pillar and generates Host, Service, and Notification objects for every registered server. Host role is inferred from the hostname prefix (e.g. proxy*, db*, mw*) and role-specific services are added automatically.salt-hosts.conf.jinja (excerpt)
Notification objects for each service, so alerts fire on both channels without manual configuration.Notification webhook scripts
The notification scripts live in/etc/icinga2/scripts/ and are deployed by the state. All four scripts (discord_host, discord_service, slack_host, slack_service) source a shared config file that injects the webhook URLs from pillar.
webhook_config.sh.jinja
/etc/icinga2/scripts/webhook_config.sh with mode 0640 (readable only by root and the nagios group) and each notification script requires it before running.
Icingaweb2 configuration
The Icingaweb2 configuration directory/etc/icingaweb2 is owned by www-data:icingaweb2 with mode 2770 (setgid so new files inherit the group). Four INI files are templated into it:
| File | Purpose |
|---|---|
config.ini | Global Icingaweb2 settings; points config_resource at the icingaweb2 DB resource |
resources.ini | Database resource definitions — icinga2, icingadb, icinga_director, icingaweb2 all pointing at the remote MariaDB host |
authentication.ini | Sets up an autologin backend and a DB-backed auth_db backend, both using the icingaweb2 resource |
roles.ini | Grants all users (*) full permissions (*) under the Administrators role |
resources.ini (rendered example)
Director module
The Director module is configured directly withinmonitoring/init.sls (not a separate state file). It:
- Creates
/etc/icingaweb2/modules/director/with ownershipwww-data:icingaweb2and mode2770. - Writes
/etc/icingaweb2/modules/director/config.inipointing the Director at the Icinga2 API on127.0.0.1:5665. - Enables the module via
icingacli module enable director(runs aswww-data, idempotent withunless:guard).
modules/director/config.ini.jinja
Prometheus state
monitoring/prometheus.sls installs and configures the Prometheus metrics server. It manages four categories of resources: the package, the defaults file (retention), the prometheus.yml configuration, and the file_sd target files.
Retention
Retention is controlled viaARGS in /etc/default/prometheus. The pillar key monitoring:prometheus:retention defaults to 15d in the state itself, but the public pillar default (pillar/monitoring/init.sls) sets it to 30d.
/etc/default/prometheus
prometheus.yml
The configuration file at/etc/prometheus/prometheus.yml defines a global scrape interval of 30s and one scrape_config per exporter type, all backed by file_sd_configs pointing at JSON files under /etc/prometheus/file_sd/. Prometheus watches the directory and reloads targets every 5 minutes.
prometheus.yml
file_sd auto-discovery
Thefile_sd directory at /etc/prometheus/file_sd/ contains one JSON file per exporter type. Each file is rendered from a Jinja template that iterates the dns_hosts pillar, filters by hostname prefix, and writes one target entry per matching host. Adding a host to dns_hosts and re-applying monitoring.prometheus is all that is required to register it as a new scrape target.
file_sd/node.json.jinja — all hosts
file_sd/mysqld.json.jinja — db* hosts only
| Job | Port | Target filter (dns_hosts prefix) |
|---|---|---|
node | 9100 | All hosts |
mysqld | 9104 | db* |
haproxy | 9101 | proxy* |
redis | 9121 | redis* |
statsd | 9102 | monitoring* |
phpfpm | 9253 | apps*, mw*, staging* |
opensearch | 9114 | opensearch* |
Grafana state
monitoring/grafana.sls installs Grafana from the official APT repository and configures it with a pre-provisioned Prometheus datasource.
grafana.ini
The main configuration file is rendered fromgrafana.ini.jinja. It sets the HTTP port to 3000, locks down sign-ups and anonymous access, and injects the admin credentials from pillar.
grafana.ini.jinja
Prometheus datasource provisioning
/etc/grafana/provisioning/datasources/prometheus.yml is written from datasource.yml.jinja at apply time. This means Grafana starts with the Prometheus datasource already registered — no manual UI steps required.
Nginx vhost
A dedicated Nginx sitegrafana.conf is enabled (symlinked into sites-enabled/) and triggers an Nginx reload on change via watch_in.
Pillar reference
The following keys from the public pillar (pillar/monitoring/init.sls) are consumed by the monitoring state. Passwords and other secrets are stored in the private pillar and are not listed here — see the private pillar reference for those values.
monitoring namespace (public pillar)
monitoring namespace (public pillar)
| Pillar key | Default | Description |
|---|---|---|
monitoring:icinga_api_user | root | Username for the Icinga2 API user object |
monitoring:ido_db_name | icingadb | MariaDB database name for IDO |
monitoring:ido_db_user | icingadb | MariaDB user for IDO |
monitoring:web_db_name | icingaweb | MariaDB database for Icingaweb2 session/config |
monitoring:director_db_name | icingaweb | MariaDB database for Director module |
monitoring:director_db_user | icingadb | MariaDB user for Director |
monitoring:grafana:admin_user | admin | Grafana admin username |
monitoring:prometheus:retention | 30d | TSDB retention period passed to --storage.tsdb.retention.time |
notifications namespace
notifications namespace
| Pillar key | Description |
|---|---|
notifications:discord_webhook_url | Discord incoming webhook URL for Icinga2 alerts |
notifications:slack_webhook_url | Slack incoming webhook URL for Icinga2 alerts |
pillar/monitoring/init.sls (defaults)
Apply commands
- Full monitoring stack
- Monitoring init only
- Prometheus only
- Grafana only
Apply everything assigned to the monitoring server (monitoring state + all sub-states via
top.sls):