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’s pillar system is the recommended way to supply configuration values — including secrets — to state files without hard-coding them. Pillar data is stored as YAML in the pillar/ directory, served exclusively to the minion that matches the relevant top.sls target, and never written to disk on the minion itself. States read pillar values with the salt['pillar.get']() Jinja call, providing a safe default if the key is absent.
How pillar files are structured
Each service has its own subdirectory under pillar/. The init.sls inside that directory is the shared default file, applied to every minion that matches the service’s glob. Where a specific host needs different values — for example a larger InnoDB buffer pool for a production database — a per-host override file sits alongside init.sls and is assigned to that host individually in pillar/top.sls.
pillar/
├── mariadb/
│ ├── init.sls ← shared defaults for all db* hosts
│ ├── db-c1-us-east-021.sls ← overrides for db-c1-us-east-021 only
│ ├── db-other-us-east-011.sls
│ └── db-pc-us-east-011.sls
├── redis/
│ ├── init.sls ← shared defaults for all redis* hosts
│ ├── redis-us-east-011.sls ← overrides for redis-us-east-011 only
│ ├── redis-us-east-012.sls
│ └── redis-us-east-021.sls
└── metal/
├── init.sls ← shared defaults for all metal* hosts + VMs
├── metal-us-east-01.sls ← overrides for metal-us-east-01 only
└── metal-us-east-02.sls
When Salt compiles the pillar for a minion, all matching files are merged. Keys in per-host files take precedence over keys in init.sls.
Top-level pillar keys
timezone and apt
Defined in pillar/base/init.sls and applied to every minion. These two keys control the system timezone and the APT mirror used in /etc/apt/sources.list.
# pillar/base/init.sls
timezone: Etc/UTC
apt:
mirror: deb.debian.org
haproxy
Applied to proxy* minions. Defines global settings, frontend bindings, backend pools, and per-route hostname matching. The routes list drives a Jinja template that generates HAProxy ACL rules; each entry maps a public hostname to a named backend.
# pillar/haproxy/init.sls (excerpt)
haproxy:
global:
maxconn: 4096
log: /dev/log local0 info
defaults:
mode: http
timeout_connect: 5s
timeout_client: 50s
timeout_server: 50s
stats_socket: /run/haproxy/admin.sock
routes:
- hostname: icinga.wikioasis.org
backend: icinga
active: true
- hostname: grafana.wikioasis.org
backend: grafana
active: true
backends:
mediawiki:
balance: roundrobin
options:
- forwardfor
- httpchk
http_checks:
- send meth GET uri /wiki/Main_Page ver HTTP/1.1 hdr Host wikioasis.org
- expect str wikioasis
servers:
- name: mw-us-east-011
host: mw-us-east-011.ovvin.wonet
port: 80
check: true
weight: 1
depooled: false
Set depooled: true on a server entry to remove it from the pool without deleting it from the config — useful during rolling deploys.
mariadb
Applied to db* minions. Shared defaults set conservative buffer sizes; per-host files override them for production workloads.
# pillar/mariadb/init.sls — shared defaults
mariadb:
datadir: /var/lib/mysql
bind_address: 0.0.0.0
key_buffer_size: 128M
max_allowed_packet: 1G
thread_stack: 192K
thread_cache_size: 8
max_connections: 100
table_cache: 64
expire_logs_days: 10
innodb:
buffer_pool_size: 1G
log_file_size: 256M
flush_log_at_trx_commit: 1
file_per_table: true
# pillar/mariadb/db-c1-us-east-021.sls — key differences from init.sls
mariadb:
server_id: 1021
max_connections: 1000
innodb:
buffer_pool_size: 20G
Applied to mw*, staging*, task*, and proxy* minions. Controls the deployment user, filesystem paths, the HAProxy socket used for canary draining, and the MediaWiki server list used by the deploy tooling.
# pillar/mediawiki/init.sls
mediawiki:
deploy_user: mwdeploy
staging_path: /srv/mediawiki-staging
prod_path: /srv/mediawiki
canary_vhost: test.wikioasis.org
log_file: /var/log/mwdeploy.log
haproxy_backend: mediawiki
haproxy_socket: /run/haproxy/admin.sock
backup_path: /srv/mediawiki-backup
mw_servers:
- task-us-east-011.ovvin.wonet
- mw-us-east-011.ovvin.wonet
- mw-us-east-012.ovvin.wonet
- mw-us-east-021.ovvin.wonet
- mw-us-east-022.ovvin.wonet
proxy_servers:
- proxy-us-east-011.ovvin.wonet
- proxy-us-east-021.ovvin.wonet
deploy_ssh_public_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBw+m6ZQT6Q7MPgfd5STamRLSUADflff/9uKVtbBZluM mwdeploy@staging-us-east-021"
ssh_identity: /home/mwdeploy/.ssh/id_ed25519
webhooks:
discord: ""
slack: ""
Webhook URLs for Discord and Slack deploy notifications are set here (or overridden in the private pillar).
monitoring
Applied to monitoring* minions. Configures Icinga 2 database names, the Grafana admin user, and Prometheus retention. Passwords are not stored here — they live in the private pillar.
# pillar/monitoring/init.sls
monitoring:
icinga_api_user: root
ido_db_name: icingadb
ido_db_user: icingadb
web_db_name: icingaweb
director_db_name: icingaweb
director_db_user: icingadb
grafana:
admin_user: admin
prometheus:
retention: 30d
nginx
Applied to mw*, staging*, and task* minions (the apps* role does not use the shared nginx pillar). Sets the document root, the Content Security Policy header (which covers all WikiOasis and SkyWiki domains), standard server blocks, and per-wiki custom domain mappings for ACME verification tokens.
# pillar/nginx/init.sls (excerpt)
nginx:
doc_root: /srv/mediawiki
csp_header: >-
default-src 'self' https://*.betaoasis.xyz https://*.wikioasis.org;
script-src 'self' blob: 'unsafe-inline' 'unsafe-eval' ...;
...
server_blocks:
- listen:
- "80"
- "[::]:80"
server_name: ".wikioasis.org .skywiki.org .betaoasis.xyz"
custom_domains:
solarpunkwiki:
server_name: 'www.solarpunk.wiki'
listen: 80
location: 'py_SqqfZnDI2q2LQkLUXETagCWz_XKLJfUavp8ncbmFlNaxrJ9RCTR1nt6bBLVdh'
return: 'py_SqqfZnDI2q2LQkLUXETagCWz_XKLJfUavp8ncbmFlNaxrJ9RCTR1nt6bBLVdh.r54qAqCZSs4xyyeamMffaxyR1FWYVb5OvwUh8EcrhpI'
database_name: 'solarpunkwiki'
Each custom_domains entry generates an nginx server block that handles the ACME challenge verification token and rewrites to the wiki’s canonical URL.
opensearch
Applied to opensearch* minions. Names the search cluster, sets the JVM heap size, and lists all nodes in the cluster for transport-layer discovery.
# pillar/opensearch/init.sls
opensearch:
cluster_name: wikioasis-search
heap_size: 3g
http_port: 9200
transport_port: 9300
nodes:
- name: opensearch-us-east-011
host: opensearch-us-east-011.ovvin.wonet
- name: opensearch-us-east-012
host: opensearch-us-east-012.ovvin.wonet
php
Applied to mw*, staging*, task*, and apps* minions. Specifies the PHP version, the list of extensions to install, FPM pool tuning, and monitoring queue thresholds.
# pillar/php/init.sls
php:
version: "8.4"
extensions:
- fpm
- mysql
- xml
- mbstring
- intl
- curl
- gd
- zip
- apcu
- igbinary
- redis
extra_packages:
- php-excimer
- php-luasandbox
fpm:
pool: www
listen: ""
pm: dynamic
pm_max_children: 10
pm_start_servers: 6
pm_min_spare_servers: 6
pm_max_spare_servers: 8
pm_max_requests: 500
request_terminate_timeout: 60
monitoring:
queue_warn: 5
queue_crit: 10
redis
Applied to redis* minions. Shared defaults use noeviction (suitable for sessions). Per-host files for the us-east-011 and us-east-012 nodes switch to allkeys-lru for use as an object cache — us-east-011 sets maxmemory to 12gb and us-east-012 sets it to 3gb.
# pillar/redis/init.sls — shared defaults
redis:
bind: 0.0.0.0
port: 6379
timeout: 0
tcp_keepalive: 300
loglevel: notice
logfile: ""
databases: 16
maxmemory: 0
maxmemory_policy: noeviction
protected_mode: "no"
appendonly: "no"
appendfsync: everysec
save:
- "900 1"
- "300 10"
- "60 10000"
# pillar/redis/redis-us-east-011.sls — larger object-cache node
redis:
bind: 0.0.0.0
maxmemory: 12gb
maxmemory_policy: allkeys-lru
# pillar/redis/redis-us-east-012.sls — smaller object-cache node
redis:
bind: 0.0.0.0
maxmemory: 3gb
maxmemory_policy: allkeys-lru
users and groups
Applied to all minions (via the '*' rule in pillar/top.sls). Defines the system users, their SSH public keys, UIDs/GIDs, and the sudo groups they belong to. User IDs start at 3000 to avoid conflicts with service accounts.
# pillar/users/init.sls (excerpt)
users:
thomas:
fullname: Thomas
ssh-keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBBENCQ1Vgjdl8ux9snbGF4s1SRbcU0EvaYlj7I51LWG zippybonzo@wikioasis.org
uid: 3000
gid: 3000
groups:
ops:
gid: 7000
description: root, on all servers
members: [thomas, unai]
privileges: ['ALL = (ALL) NOPASSWD: ALL']
mediawiki-admins:
gid: 7001
description: elevated permissions on webservers
members: [tali64]
privileges:
- 'ALL = (www-data) NOPASSWD: ALL'
- 'ALL = (www-data) NOPASSWD: /usr/local/bin/mwdeploy *'
- 'ALL = (ALL) NOPASSWD: /usr/sbin/service nginx *'
- 'ALL = (ALL) NOPASSWD: /usr/sbin/service php8.4-fpm *'
- 'ALL = (ALL) NOPASSWD: /bin/journalctl *'
The users/servers/mediawiki.sls file adds a server_groups key that restricts which groups are provisioned on MediaWiki servers:
# pillar/users/servers/mediawiki.sls
server_groups:
- ops
- mediawiki-admins
Applied to metal* minions and all VMs (via the compound metal* or *-us-east-0[0-9][0-9]* rule). Provides the DNS/MAC address table for DHCP, the Proxmox bridge names, public IP addresses, per-hypervisor IPv6 prefixes, and IP forwarding rules.
# pillar/metal/init.sls (excerpt)
apt_bootstrap:
http_cache: http://127.0.0.1:3129
metal_public_ips:
- 40.160.53.92
- 40.160.53.94
dns_hosts:
mw-us-east-011.ovvin.wonet:
ip: 10.0.1.60
mac: bc:24:11:ac:18:e0
proxmox:
public_bridge: "vmbr0"
private_bridge: "vmbr-vrack"
hosts:
metal-us-east-01:
ipv6_prefix: "2604:2dc0:100:295c"
ipv6_gateway: "2604:2dc0:100:29ff:ff:ff:ff:ff"
The apt_bootstrap.http_cache value is an APT proxy address used only during initial VM provisioning, before Salt manages the host. The metal state removes this proxy configuration file once it takes control.
Pillar merging behaviour
Salt merges pillar data from all matching files using a shallow merge by default. For dictionary keys, the last file wins at the top level. Because per-host files are loaded after init.sls, their keys override the shared defaults:
Effective pillar for db-c1-us-east-021
= merge(mariadb/init.sls, mariadb/db-c1-us-east-021.sls)
The mariadb.innodb.buffer_pool_size from the per-host file (20G) replaces the default (1G) because both files define the mariadb top-level key and Salt merges dictionaries recursively when pillar_source_merging_strategy: recurse is set.