backup-disaster-recovery — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited backup-disaster-recovery (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The line that defines a backup strategy: "a backup you have not restored is a wish, not a backup." Most teams have something called "backups" that have never been restored end-to-end. Sometimes they don't actually work; sometimes they work but are too slow; sometimes they work but the team forgot a critical piece of state and ends up with a half-restored system.
This skill builds a strategy that survives the first real incident — not the strategy that looks good in a slide deck.
Pairs with incident-response (where backups get used) and postgres-hardening / backend-architecture (where the data lives).
The right strategy depends on the failure class. Backups for ransomware look different from backups for "developer dropped the table accidentally."
| Failure class | What you need |
|---|---|
| Hardware failure (disk, server) | Replica or snapshot in a different physical location |
| Accidental delete (DROP TABLE, rm -rf, bad migration) | Point-in-time backup, retained N days |
| Application bug corrupting data | Point-in-time backup + ability to surgically restore subsets |
| Ransomware encrypting everything reachable from the app | Backups the ransomware cannot reach — immutable or offline |
| Cloud-account compromise | Backups in a separate account / provider, separate credentials |
| Provider going under / region outage | Backups in a different provider / region |
| Legal hold / subpoena / SAR request | Selective archive, retention policy that complies with your jurisdiction |
| Force majeure (data center fire, country-level outage) | Off-region / off-provider backups, restore plan that does not assume continuity |
A real strategy covers at least the first four. Production systems with revenue at stake should cover the first six. Regulated environments cover all eight.
RPO (Recovery Point Objective): how much data can you afford to lose? Measured in time. RPO = 1 hour means you can lose up to the last hour of writes.
RTO (Recovery Time Objective): how long can you be down during recovery? RTO = 4 hours means a full restore must complete within four hours.
These two drive every other decision. A 1-minute RPO requires continuous replication; a 1-day RPO can be daily snapshots. A 5-minute RTO requires hot standby; a 24-hour RTO can be cold storage on a different provider.
Most small-team production systems land at:
Pick yours. Write it down. Test against it.
The classic backup mantra, still correct:
In modern cloud terms:
You can extend (3-2-1-1-0: plus 1 immutable, 0 errors after restore test), but 3-2-1 is the minimum that survives realistic failures.
A leaked plaintext backup is a leaked database. Encrypt before the data leaves the production host, with a key the backup destination does not hold.
# pg_dump piped through compression + age encryption, then to off-site storage
pg_dump -Fc app_db \
| gzip \
| age -r age1q3...recipientpublickey... \
> /tmp/app_db-$(date +%F).sql.gz.age
# Upload to off-provider storage (Cloudflare R2, B2, S3) with rclone
rclone copy /tmp/app_db-$(date +%F).sql.gz.age remote:backups/Patterns:
Ransomware that compromises the production environment will look for backups to encrypt or delete next. Standard daily-rsync-to-NAS backups die in this scenario.
Defenses:
Avoid:
A backup you have not restored is not a backup. Schedule and execute drills.
Quarterly drill (every team):
Annual full DR exercise (production-critical systems):
Common findings from real drills:
pg_restore, mongorestore) that are not installed on the restore hostThe database is the most obvious. The less-obvious matters too:
.github/workflows/, deploy scripts. Live in the repo, but make sure the repo itself has off-platform backups (GitHub itself can lock you out).The "everything else" tier is often where the recovery time actually goes. The DB restore is 30 minutes; reconstructing the deploy pipeline from memory is 3 days.
Two different needs, two different policies:
Roughly: more granular for recent, less for older.
Tune to your RPO and to the cost.
Different rules. Tax data: 10 years (DE/AT). Some user data: only as long as needed under GDPR — see gdpr-technical-controls. Some data has affirmative deletion requirements (right to be forgotten, accounts closed).
These two policies conflict for personal data. The accepted approach: maintain a "delete on restore" pipeline so any restore re-applies deletion requests issued since the backup was taken. Document this in your privacy policy and DPA.
A backup process that requires manual action will silently break.
# Cron entry — daily at 03:00 UTC
0 3 * * * /usr/local/bin/backup-app.sh 2>&1 | logger -t backup-app
# In /usr/local/bin/backup-app.sh — exits non-zero on any failure,
# pings a healthcheck URL on success (so absence is itself an alert)
set -euo pipefail
TIMESTAMP=$(date +%Y-%m-%d-%H%M%S)
BACKUP_PATH=/tmp/app_db-$TIMESTAMP.sql.gz.age
pg_dump -Fc app_db | gzip | age -r "$AGE_RECIPIENT" > "$BACKUP_PATH"
rclone copy "$BACKUP_PATH" remote:backups/ --no-traverse
rm "$BACKUP_PATH"
# Healthcheck — https://healthchecks.io / Better Stack heartbeats / your monitoring
curl -fsS -m 10 --retry 3 "$HEARTBEAT_URL"Monitor:
A heartbeat-based pattern catches more failures than a "got an alert on error" pattern. If the cron job died entirely, error-alerts never fire; absence does.
In a place that exists when production is gone:
Should answer:
A good recovery doc is the result of a real drill, not theory.
pg_dumpBoth have a place. Cloud-provider snapshots are fast to restore but tied to the provider. Logical dumps (pg_dump, mongodump) are slower but portable to any environment. Run both. Cloud snapshots for fast intra-provider restore; off-provider logical dumps for the bad-day scenario.
S3 versioning + lifecycle is the easy path. With versioning on, deleted objects can be restored by removing the delete marker. Lifecycle policies move old versions to cheaper storage.
But: versioning is account-internal. A compromised account credential can still delete versions (unless Object Lock is on). For ransomware resistance, mirror to a separate account / provider.
For self-hosted single-VPS deployments, provider-level snapshots are the right complement to app-level backups. They capture everything — DB, files, config — at one moment. They're not granular for "restore one row" but they're great for "restore the whole machine."
Restore at least one VPS snapshot per quarter to verify the provider's snapshot mechanism works for your case.
For high-stakes data, yes. A weekly export from the primary backup destination to a tertiary location. Three's the magic number; rarely worth four.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.