# group_vars/production.yml
linux_vitals_ram_warning_threshold: 70
linux_vitals_ram_critical_threshold: 90
linux_vitals_boot_warning_threshold: 25
# group_vars/staging.yml
linux_vitals_ram_warning_threshold: 85
linux_vitals_ram_critical_threshold: 97# group_vars/web_tier.yml
linux_vitals_heal_enabled: trueEverything else inherits the default (false), so only hosts in
web_tier are ever restarted.
ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.healthcheck \
--forks 25Reporting tasks (vitals_report) are delegate_to: localhost and
run_once: true, so they execute exactly once regardless of fleet size or
fork count -- only the scan/heal stages parallelize across hosts.
# Just kernel/reboot posture, skip the rest
ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.healthcheck --tags kernel,reporting
# Rebuild the dashboard and resend notifications from the last run's data,
# without re-scanning hosts
ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.healthcheck --tags reporting,notificationsreporting is required alongside any narrower tag if you still want a
dashboard out of the run -- see troubleshooting.md.
Maintenance ids are just strings, so you can run independent baseline/postcheck pairs for different windows without them colliding:
ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.baseline \
-e linux_vitals_maintenance_id=db-cluster-2026-08-01
ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.baseline \
-e linux_vitals_maintenance_id=web-tier-2026-08-03Each writes to its own reports/snapshots/<maintenance_id>/ subtree.
# .github/workflows/ci.yml (excerpt)
- name: Symlink repository as the sameeralam3127.linux_vitals collection
run: |
mkdir -p .dev-collections/ansible_collections/sameeralam3127
ln -s "$GITHUB_WORKSPACE" .dev-collections/ansible_collections/sameeralam3127/linux_vitals
- run: ansible-playbook playbooks/healthcheck.yml --syntax-check
- run: ansible-lint roles/ playbooks/
- run: pytest -qThe report role remains report-only by default. To make a scheduled CI job fail when more than two hosts are unhealthy:
# group_vars/all.yml
linux_vitals_fail_on_status: any_fail
linux_vitals_fail_threshold_count: 2For a maintenance pipeline, gate only on hosts that changed from Pass at
baseline to Fail during the postcheck:
linux_vitals_fail_on_status: regression
linux_vitals_fail_threshold_count: 0ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.postcheck \
-e linux_vitals_maintenance_id=kernel-rollout-2026-09-27The HTML/JSON reports, archives, and configured notifications are written before the final gate task can return a non-zero status.
ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.healthcheck
jq '.hosts[] | select(.status == "Fail") | {hostname, findings}' \
reports/linux_vitals_report.jsonOr ship reports/linux_vitals_report.json directly with Filebeat/Fluent
Bit into ELK/OpenSearch, or scrape it from a CI/AAP job artifact for
downstream alerting on summary.regressed_count after a maintenance
window.
Prefer Vault over .env when your inventory is itself encrypted or
version-controlled with the rest of your infra repo:
# group_vars/all/vault.yml (encrypted with ansible-vault)
linux_vitals_slack_webhook_url: "https://hooks.slack.com/services/..."
linux_vitals_email_password: "..."ansible-playbook -i inventory.ini sameeralam3127.linux_vitals.healthcheck --ask-vault-passRather than writing these from scratch:
| File | What it gives you |
|---|---|
| examples/inventory/hosts.example.ini | A four-host mixed fleet (RHEL, Ubuntu, Fedora, SLES) with ansible_user, become, and a key path already set |
| examples/inventory/large-fleet.example.ini | Ten generated nodes, for exercising the dashboard's search and filter at a realistic host count |
| examples/group_vars/all.yml.example | Every tunable variable, commented out, with the .env-versus-inline guidance for secrets |
| examples/playbooks/custom-thresholds.yml | Overriding thresholds and enabling healing for one ad-hoc run without touching group_vars |
Addresses use the RFC 5737 documentation range (192.0.2.0/24), so nothing
resolves by accident -- replace them before running anything.