Every VPS provider will tell you backups are important. Fewer will tell you that a backup you've never restored from is unverified at best, and at worst is a corrupted file you'll discover is useless at the exact moment you need it. Here's a setup that's genuinely low-maintenance and gets tested on a schedule.
The 3-2-1 rule, applied to one server
Three copies of your data, on two different types of storage, with one copy off-site. For a solo-run VPS, a practical version: the live data on the server itself (copy one), a daily automated backup pushed to object storage in a different location or provider (copy two, off-site), and a weekly full snapshot through your VPS provider's own snapshot feature (copy three). This costs a few dollars a month and takes about an hour to set up once.
Database backups
A nightly logical dump is the baseline for almost any solo SaaS's data size:
pg_dump -Fc mydb > /backups/mydb_$(date +%F).dump
# or for MySQL:
mysqldump --single-transaction mydb | gzip > /backups/mydb_$(date +%F).sql.gz
Cron this nightly, and immediately push the resulting file off-server (rclone to S3-compatible object storage is the simplest reliable option). Keep at least 7 daily and 4 weekly copies with a rotation script so a corruption you don't notice for a few days doesn't overwrite every good backup you had.
File and upload backups
If you're storing user uploads on object storage already (as recommended in our single-VPS SaaS guide), most providers offer built-in versioning or cross-region replication as an add-on, which covers this category with very little extra setup. If uploads still live on local disk, include that directory in your nightly backup routine alongside the database dump.
Full server snapshots
A full disk snapshot through your provider's dashboard (or API, scheduled) captures the entire server state — OS, installed packages, configuration — not just application data. This is what saves you hours of reconfiguration after a botched update or a failed migration, as opposed to database backups, which only save your data. Weekly is usually sufficient; daily if you're actively making infrastructure changes.
Where backups should actually live
Never let "off-site" mean "a different folder on the same server." A backup that lives on the same physical machine as the data it protects doesn't protect against the most common failure modes: disk failure, accidental deletion, or the server being compromised entirely. Object storage from a different provider than your VPS host is the simplest genuinely off-site option and typically costs only a few cents per gigabyte per month.
The part everyone skips: testing restores
Put a recurring calendar reminder — monthly is reasonable — to actually restore a recent backup to a throwaway environment and verify the data comes back intact and the application boots against it. This single habit is what separates "I have backups" from "I have backups that work," and it's the difference that matters at 3am during an actual incident.
A complete example script
Rather than assembling the pieces above one at a time, here's a single cron-driven script that dumps the database, compresses it, pushes it to object storage with rclone, and prunes anything older than your retention window — the kind of thing you write once and mostly forget about:
#!/bin/bash
set -euo pipefail
DATE=$(date +%F)
DUMP_DIR=/var/backups/db
REMOTE=myS3remote:my-backup-bucket
mkdir -p "$DUMP_DIR"
pg_dump -Fc mydb > "$DUMP_DIR/mydb_$DATE.dump"
# push to off-server object storage
rclone copy "$DUMP_DIR/mydb_$DATE.dump" "$REMOTE/db/"
# keep 7 local copies, rely on the remote for longer retention
find "$DUMP_DIR" -name "mydb_*.dump" -mtime +7 -delete
# prune anything older than 90 days on the remote itself
rclone delete --min-age 90d "$REMOTE/db/"
Wire this into crontab -e to run nightly (0 2 * * * /usr/local/bin/backup.sh), and pipe its output to a log file or a simple curl ping to a dead-man's-switch service (several have free tiers) so you get alerted if the job silently stops running — a backup script that fails quietly for weeks is barely better than no backup script at all.
Choosing an off-site destination
Any S3-compatible object storage works as the destination — the specific provider matters less than actually having one that's genuinely separate from your VPS host. A few things worth comparing before picking one: whether pricing is a flat per-GB rate or has confusing egress/retrieval fees that only show up when you actually need to restore (some "cheap storage" providers make restoring expensive, which defeats the point); whether the provider supports the S3 API well enough that rclone or your language's standard S3 client works without workarounds; and whether it's operated by a genuinely different company than your VPS provider, not just a different product line from the same one, so a single account compromise or billing dispute can't take out both your server and your backups at once.
Frequently asked questions
How long should I retain old backups?
A common pattern: keep daily backups for a week, weekly backups for a month, and monthly backups for a year. This protects against both recent accidental deletions and slow-developing corruption you might not notice for weeks, without paying to store an unlimited, ever-growing history.
Should backups be encrypted?
Yes, especially since they leave your server and live on third-party storage. Most backup tools and object storage providers support encryption at rest and in transit with minimal extra configuration — enable it from the start rather than retrofitting it later.
What's the difference between a snapshot and a backup, really?
A snapshot (usually provider-specific) captures the entire disk state, including the OS and installed software, and is typically the fastest way to fully restore a server. A backup (like a database dump) captures just your data in a portable format you can restore anywhere, independent of your VPS provider. A solid strategy uses both, not one instead of the other.