Documentation 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.
Salt uses a file called top.sls in both the state tree and the pillar tree to decide what each minion receives. When you run salt '*' state.apply or when a highstate is triggered, the master evaluates both top files and compiles a per-minion list of states and pillar data. Understanding these files is the key to understanding what happens on any server in the WikiOasis fleet.
WikiOasis has two top files:
salt/top.sls — assigns state modules to minions (what software is installed and configured)
pillar/top.sls — assigns pillar data files to minions (the values used by those states)
Matching syntax
Default: glob
Lines without a match: directive use shell glob matching against the minion ID. The * wildcard matches any string; [0-9] matches a single digit in a character class.
'db*': # matches db-c1-us-east-021, db-other-us-east-011, etc.
- mariadb
Compound matching
Add - match: compound as the first item in the state list to unlock Boolean logic with or, and, and not keywords. The compound matcher evaluates the full minion ID.
'mw* or staging*':
- match: compound
- php
- nginx
- sentry_relay
match: compound must be the first item in the list. Salt treats it as a directive, not a state name — it will not try to load a state called compound.
Ranged glob
A character-class range like 0[0-9][0-9] targets numbered hosts without listing each one:
'*-us-east-0[0-9][0-9]*':
- metal.vm_ipv6
This matches every VM whose ID follows the <role>-us-east-0NN convention (e.g. mw-us-east-011, redis-us-east-021) and applies IPv6 routing configuration managed by the metal state.
salt/top.sls
The state top file determines which Salt state trees are applied to each minion. States are cumulative — a mw-us-east-011 minion matches '*', 'mw*', 'mw* or staging*', and '*-us-east-0[0-9][0-9]*' and receives all states from every matching block.
base:
# ── Applied to every minion ────────────────────────────────────────────
'*':
- base # timezone, APT sources
- users # system users, SSH keys, sudo groups
- monitoring.nrpe # Icinga NRPE daemon
- monitoring.nrpe_common # common NRPE check scripts
- monitoring.nrpe_salt # NRPE checks for the Salt minion itself
- monitoring.node_exporter # Prometheus Node Exporter
# ── Applications server ────────────────────────────────────────────────
'apps*':
- php
- nginx
- monitoring.nrpe_nginx
- monitoring.nrpe_php
- monitoring.phpfpm_exporter
# ── Database servers ───────────────────────────────────────────────────
'db*':
- mariadb # MariaDB server + my.cnf
- mariadb.monitoring_user # Icinga check user
- mariadb.prometheus_user # mysqld_exporter user
- mariadb.backup # backup user + rsync cron
- mariadb.nrpe_backup # NRPE checks for backup age
- monitoring.mysqld_exporter # Prometheus mysqld_exporter
# ── Bare-metal hypervisors ─────────────────────────────────────────────
'metal*':
- metal # DNS/DHCP, IP forwarding, bridges
- monitoring.nrpe_metal
# ── HAProxy load balancers ─────────────────────────────────────────────
'proxy*':
- haproxy # HAProxy config & service
- monitoring.nrpe_haproxy
- monitoring.haproxy_exporter
- mediawiki.proxy # deploy-user SSH key on proxy nodes
# ── Monitoring server ──────────────────────────────────────────────────
'monitoring*':
- monitoring # Icinga 2, Icinga Web 2
- monitoring.director # Icinga Director module
- monitoring.nrpe_nginx
- monitoring.prometheus # Prometheus server
- monitoring.grafana # Grafana dashboards
- monitoring.statsd_exporter # StatsD → Prometheus bridge
# ── Staging / canary server ────────────────────────────────────────────
'staging*':
- mediawiki # mwdeploy user, SSH keys, deploy scripts
# ── MediaWiki application servers ─────────────────────────────────────
'mw*':
- mediawiki.target # deploy target configuration
# ── MediaWiki + staging (compound) ────────────────────────────────────
'mw* or staging*':
- match: compound
- php
- nginx
- sentry_relay
- monitoring.nrpe_nginx
- monitoring.nrpe_php
- monitoring.nrpe_mediawiki
- monitoring.phpfpm_exporter
# ── Task / job runner ──────────────────────────────────────────────────
'task*':
- php
- nginx
- mediawiki.target
- mediawiki.jobrunner # job queue runner configuration
- monitoring.nrpe_nginx
- monitoring.nrpe_php
- monitoring.phpfpm_exporter
# ── OpenSearch nodes ──────────────────────────────────────────────────
'opensearch*':
- opensearch
- monitoring.nrpe_opensearch
- monitoring.opensearch_exporter
# ── Redis cache servers ────────────────────────────────────────────────
'redis*':
- redis
- monitoring.nrpe_redis
- monitoring.redis_exporter
# ── Salt master (self-monitoring only) ────────────────────────────────
'salt*':
- monitoring.nrpe_salt_master
# ── All VMs with numbered names (IPv6 routing) ────────────────────────
'*-us-east-0[0-9][0-9]*':
- metal.vm_ipv6
State counts per role
| Minion pattern | States received |
|---|
Every minion (*) | base, users, monitoring.nrpe, monitoring.nrpe_common, monitoring.nrpe_salt, monitoring.node_exporter |
mw* | All of * + mediawiki.target + compound block (php, nginx, sentry_relay, monitoring checks) + metal.vm_ipv6 |
staging* | All of * + mediawiki + compound block + metal.vm_ipv6 |
task* | All of * + php, nginx, mediawiki.target, mediawiki.jobrunner, monitoring checks + metal.vm_ipv6 |
proxy* | All of * + haproxy, monitoring.nrpe_haproxy, haproxy_exporter, mediawiki.proxy + metal.vm_ipv6 |
db* | All of * + mariadb stack + mysqld_exporter + metal.vm_ipv6 |
redis* | All of * + redis, nrpe_redis, redis_exporter + metal.vm_ipv6 |
opensearch* | All of * + opensearch, nrpe_opensearch, opensearch_exporter + metal.vm_ipv6 |
monitoring* | All of * + full monitoring stack + metal.vm_ipv6 |
metal* | All of * + metal, nrpe_metal |
apps* | All of * + php, nginx, monitoring checks + metal.vm_ipv6 |
salt* | All of * + monitoring.nrpe_salt_master + metal.vm_ipv6 |
pillar/top.sls
The pillar top file controls which pillar data files are merged and sent to each minion. Unlike state assignments, pillar assignments directly affect what values are available to Jinja templates in states.
base:
# ── All minions receive base config, users, and secrets ───────────────
'*':
- base # timezone, apt mirror
- users # user/group definitions
- private # secrets (passwords, API keys)
# ── Applications server ────────────────────────────────────────────────
'apps*':
- php
- private
# ── Bastion SSH gateway ────────────────────────────────────────────────
'bastion*':
- users.servers.bastion # bastion-specific SSH key overrides
# ── Database servers ───────────────────────────────────────────────────
'db*':
- mariadb # shared MariaDB defaults
- private # backup credentials
# Per-host MariaDB overrides (larger buffer pools, server IDs, etc.)
'db-other-us-east-011*':
- mariadb.db-other-us-east-011
'db-pc-us-east-011*':
- mariadb.db-pc-us-east-011
'db-c1-us-east-021*':
- mariadb.db-c1-us-east-021
# ── Bare-metal + all numbered VMs (compound) ──────────────────────────
'metal* or *-us-east-0[0-9][0-9]*':
- match: compound
- metal # DNS table, Proxmox config, public IPs
# Per-hypervisor overrides (public IP, IP forwarding rules)
'metal-us-east-01*':
- metal.metal-us-east-01
'metal-us-east-02*':
- metal.metal-us-east-02
# ── MediaWiki + staging (compound) ────────────────────────────────────
'mw* or staging*':
- match: compound
- users.servers.mediawiki # mediawiki-admins group enabled
- php
- nginx
- mediawiki
# ── HAProxy load balancers ─────────────────────────────────────────────
'proxy*':
- haproxy
- mediawiki # needed for deploy user + proxy list
# ── Monitoring server ──────────────────────────────────────────────────
'monitoring*':
- monitoring
- metal # needs DNS host table for check targets
- private # Icinga/Grafana passwords
# ── Task / job runner ──────────────────────────────────────────────────
'task*':
- users.servers.mediawiki
- php
- nginx
- mediawiki
- mediawiki.jobrunner
# ── OpenSearch nodes ──────────────────────────────────────────────────
'opensearch*':
- opensearch
# ── Redis cache servers ────────────────────────────────────────────────
'redis*':
- redis
# Per-host Redis overrides (maxmemory, eviction policy)
'redis-us-east-011*':
- redis.redis-us-east-011
'redis-us-east-012*':
- redis.redis-us-east-012
The private pillar is assigned to '*' as a catch-all so that every minion can access cross-cutting secrets such as the monitoring API host. Ensure pillar/private/init.sls exists on the master before running any highstate, or Salt will error on missing pillar keys.
Debugging pillar and state assignment
To inspect what pillar data a specific minion would receive:
# Show compiled pillar for a single minion
salt 'mw-us-east-011' pillar.items
# Show a single pillar key
salt 'db-c1-us-east-021' pillar.get mariadb:innodb:buffer_pool_size
To preview what states would be applied without actually running them:
# Dry-run highstate (shows changes that would be made)
salt 'proxy-us-east-011' state.apply test=True
# Show which state SLS files the top file assigns
salt 'proxy-us-east-011' state.show_top