Daily backup freshness and weekly coverage audit with Codex, NetBox and rConfig MCP
Every playbook that reads rConfig assumes the configs are current. When a backup quietly stops (a changed password, a retired jump host, a device moved to a new group without a schedule), the device simply stops changing in rConfig, and every check that reads it reports good news. This job runs every morning, lists devices whose backups have gone stale, and looks for what they have in common. On Mondays it also compares rConfig with NetBox, to find devices that are in production but not backed up at all.
Best for: NCM owners, the morning operations check, MSPs proving backup coverage per customer, pre-audit hygiene.
Tools: rConfig, Codex CLI (codex exec) from cron, optionally the NetBox MCP server, a chat webhook.
rConfig tools used: get_devices.
rConfig docsAutomated Network Task Scheduling in rConfig V8Scheduled tasks for network automation in rConfig V8: device backups, compliance checks, SNMP polling, and automated device management workflows.Read the docs
How it flows
flowchart TB
C["cron 07:00 daily"] --> D["Freshness check"]
D -- "get_devices<br/>(last_config_at)" --> R["rConfig MCP"]
D --> O["Stale devices,<br/>grouped by likely cause"]
W["cron 07:15 Monday"] --> V["Coverage check"]
V -- "devices" --> R
V -- "active devices" --> N["NetBox MCP"]
V --> G["In NetBox, not in rConfig<br/>In rConfig, not in NetBox"]
O --> P["Ops channel"]
G --> P
Connect both servers
[mcp_servers.rconfig]url = "https://rconfig.example.net/mcp"bearer_token_env_var = "RCONFIG_MCP_TOKEN"default_tools_approval_mode = "writes"The rConfig settings are the ones in the Codex CLI guide. For the weekly coverage check, add the NetBox MCP server as a second [mcp_servers.netbox] table, using the launch settings from that server’s README and a read-only NetBox API token. Keep both tokens out of the file where you can, in the job’s environment file readable only by the job account.
The daily freshness check
#!/usr/bin/env bashset -euo pipefail# CODEX_API_KEY, RCONFIG_MCP_TOKEN and CHAT_WEBHOOK_URL come from /etc/netops/backup-audit.env.
codex exec --skip-git-repo-check -o freshness.json "Using rConfig's tools only:list every device (page through get_devices until there are no more) with itsgroup, vendor and last_config_at. A device is stale if last_config_at is morethan 26 hours ago, or empty. For stale devices, look for what they share:same group, same vendor, or a last_config_at that stopped at the same time. A cluster that stopped together usually has one cause.
Output only JSON:{\"total\": <n>, \"stale\": [{\"device\", \"group\", \"vendor\", \"last_config_at\"}], \"clusters\": [{\"description\", \"devices\": [...], \"likely_cause\"}]}If rConfig's tools fail, output {\"error\": \"<detail>\"}."
jq -e 'has("error") | not' freshness.json > /dev/null || { echo "rConfig check failed"; exit 1; }[ "$(jq '.stale | length' freshness.json)" -eq 0 ] && exit 0
text=$(jq -r '"Stale backups: " + (.stale|length|tostring) + " of " + (.total|tostring) + " devices\n" + ([.clusters[] | "• " + .description + " (" + (.devices|length|tostring) + "): " + .likely_cause] | join("\n"))' freshness.json)curl -fsS -X POST -H 'Content-Type: application/json' \ -d "$(jq -n --arg t "$text" '{text: $t}')" "$CHAT_WEBHOOK_URL"An illustrative post:
Stale backups: 23 of 1,412 devices• All 19 devices in group "Cork-Access" stopped at 2026-11-09 22:00 (19): one cause, likely the group's schedule or a shared credential changed that evening• 3 Juniper SRX devices at different sites, stale for 4 to 6 days (3): same vendor, different times; check the connection settings used for SRX• ams-wan-01, no backup ever recorded (1): newly added, likely never scheduledThe clusters are the useful part. Nineteen stale devices that stopped at the same minute is one fix, not nineteen.
The weekly coverage check
codex exec --skip-git-repo-check -o coverage.json "Compare two inventories.From NetBox: every device with status Active and a role of core, distribution,access, wan or firewall. From rConfig: every device (page through get_devices).Match on hostname, case-insensitive, ignoring any domain suffix.Output only JSON: {\"in_netbox_not_rconfig\": [{\"device\", \"site\", \"role\"}],\"in_rconfig_not_netbox\": [{\"device\", \"group\"}], \"matched\": <n>}.If either server fails, output {\"error\": \"<which and why>\"}."Post the two lists the same way. The first list is the risk: production devices with no backup. The second is usually decommissioned devices that rConfig still tries to back up every night.
Limits to know
- Paging.
get_devicesreturns 50 devices a page, so a 1,400-device estate is about 28 calls. The prompt tells the agent to page to the end; check thattotalmatches the device count in rConfig. - Hostname matching is fuzzy. NetBox names and rConfig names can differ by case, domain suffix or a site prefix. Tell the agent your naming convention in the prompt, or run Device Sync so the names come from one place.
- The agent sees stale, not why. Backup errors aren’t available over MCP. Use the device’s page in rConfig for the actual failure.
Guardrails
- Both tokens are read-only: rConfig’s always are; create the NetBox token without write permissions.
- The job posts through the script’s webhook call. The agent has no posting tool.
- For MSPs, run one job per customer with a token scoped to that customer’s devices, so one customer’s report never lists another’s devices.
Variations
- Freshness SLA per group. Core devices stale after 26 hours, access after a week. Put the thresholds in the prompt as a table.
- Open a ticket per cluster instead of a chat post, assigned to the team that owns the group.
- Monthly coverage evidence. Keep each Monday’s
coverage.json. A month of them shows an auditor that coverage is checked, and how gaps were closed.
Related reference
- Scheduled Tasks
- Device Sync for NetBox
- Connect an AI agent over MCP
- Codex CLI
- NetBox intent vs config
Frequently asked questions
Why does a stale backup matter if nothing is failing?
Every other check reads rConfig's stored configs. A device whose last backup is a week old looks unchanged, compliant and unexposed, whatever has happened on it since. Freshness is the check the others depend on.
Can the agent tell me why a backup failed?
Not over MCP. The tools return devices, configs and compliance, not backup error logs. The agent can spot patterns, such as every stale device sharing a vendor or a group, which usually points at a credential, template or schedule. The device page in rConfig shows the actual error.
Does this need NetBox?
Only for the weekly coverage check. The daily freshness check uses rConfig alone. Nautobot or Infrahub work the same way if they have an MCP server.