When managing backups with restic, knowing what changed between snapshots is crucial for auditing, detecting anomalies, or understanding data growth. I use restic diff --json combined with jq to turn raw diff output into actionable insights — especially to see which directories are changing the most.
Getting a JSON diff between two snapshots
The core command is simple: run restic diff with the --json flag between two snapshots, identified by their tags, timestamps, or IDs. I usually compare the latest two snapshots unless I’m investigating a specific window.
restic diff --json latest2 latest1
This outputs a JSON array where each object describes a file change: added, modified, deleted, or type-changed. Each entry includes the path, size change, and blob IDs. While machine-readable, it’s hard to interpret directly.
Parsing and summarizing with jq
I pipe the output to jq to aggregate changes by directory. This helps me spot hotspots — for example, if /var/log or /home/user/data keeps showing up, I know where to focus retention or exclusion rules.
Here’s the one-liner I use:
restic diff --json latest2 latest1 | jq -s 'group_by(.path | split("/")[0:2] | join("/")) | map({dir: .[0].path | split("/")[0:2] | join("/"), count: length, total_size_change: map(.size_change) | add}) | sort_by(.count) | reverse | .[0:10]'
This groups changes by the first two path components (e.g., home/user, var/log), counts how many files changed in each directory, sums the size change, and returns the top 10 most active directories.
Example output
After running the command, I might see:
[
{
"dir": "home/user",
"count": 142,
"total_size_change": 2048576
},
{
"dir": "var/log",
"count": 89,
"total_size_change": 10485760
},
{
"dir": "etc",
"count": 12,
"total_size_change": -4096
}
]
This tells me that home/user had the most file changes (142), while var/log had the largest growth in size — useful for tuning backup pruning or investigating unexpected log rotation.
Automating the report
I save this as a script called restic-change-report.sh and run it weekly via cron. The output gets emailed or sent to a monitoring system. I’ve found it especially helpful in shared environments where users unexpectedly start dumping large files into backed-up directories.
As I mentioned before in my post about auditd and crontab monitoring (https://furkanikkan.com/urun/auditd-ile-yetkisiz-crontab-degisikliklerini-anlik-siem-e-aktarma-78), proactive visibility prevents surprises.
Tips and warnings
- Always test diff commands on a small repo first — large histories can take time.
- Use --host and --paths flags if you’re backing up multiple sources to avoid noise.
- Remember that restic diff shows logical changes; if a file is rewritten identically, it may not appear.
- For encrypted repos, ensure your RESTIC_PASSWORD is set — the command will fail silently otherwise.
Why this approach works
Instead of guessing what’s driving backup growth, this method gives me data. Over time, I’ve used these reports to adjust include/exclude patterns, catch misbehaving applications, and even detect ransomware-like behavior early.
If you’re using restic and want to move beyond ‘it just works’ to ‘I know what’s happening,’ start with restic diff and jq. It’s lightweight, scriptable, and built into tools you already have.
Cover image: Lenharth Systems · CC0 (Openverse / kamu malı) · https://stocksnap.io/photo/computer-hard-2J3PLNMO9M
