VPS Snaps

File Backups

Back up any path on the box

Name the directories that matter, add a few exclude patterns, and every run streams one gzipped tar from your server to your own bucket.

Back up your first server free, forever. No credit card required.

We only use your email to create your account. See our Privacy Policy.

Your credentials are encrypted with AES-256-GCM, your backups never live on our storage, and our GDPR data processing agreement is public.

It is one tar command, and here is the whole thing

No proprietary archive format and no agent-side magic to reason about. Two comma-separated fields become one command that runs on your server.

Nothing is staged to a temporary file on the server first. tar writes to stdout, the stream is hashed and uploaded as it arrives, and the object key is recorded on the run.

What you type into the job
Paths              /etc/nginx, /var/www/uploads, /var/www/legacy
Exclude patterns   *.log, node_modules, *.tmp
What runs on your server
$ tar czf - --exclude="*.log" --exclude="node_modules" \
      --exclude="*.tmp" "/etc/nginx" "/var/www/uploads"

/var/www/legacy never reaches the command. It failed the existence check, so it was dropped and written to the run log as a warning instead of taking the backup down with it.

What lands in your bucket
acme-uploads/files/cf7q2b1x/
  file-backup-cf7q2b1x-2026-09-02T02-00-06-118Z.tar.gz
Getting it back, six months later
$ tar xzf file-backup-cf7q2b1x-*.tar.gz -C /tmp/restore

/tmp/restore/etc/nginx/...
/tmp/restore/var/www/uploads/...

Three decisions baked into that command

Small choices that only matter on the day you need the archive — which is exactly why they were made in advance.

The leading slash is stripped

We run tar without -P, so /etc/nginx is stored as etc/nginx. Extracting an archive can never silently overwrite the live path it came from — you choose where it lands with -C, every time.

A missing path is a warning, not a failure

Every path is checked with test -e before the archive is built. One stale or mistyped entry gets logged and dropped; the rest still run. Only if none of the configured paths exist does the run fail outright.

tar exit code 1 is survivable

On a live server tar exits 1 for recoverable warnings like “file changed as we read it”. We accept 0 and 1 and abort on anything else, so a busy log directory doesn’t fail an otherwise good backup.

What people actually point it at

Five patterns that come up on nearly every server, with the exclude lists that keep the archive honest.

User uploads and generated media

The part of a site a database dump never contains, and the part nobody can recreate.

Paths

/var/www/uploads, /srv/app/storage/app/public

Excludes

*.tmp, cache

Web server and TLS configuration

Kilobytes of files that take an afternoon to reconstruct correctly under pressure.

Paths

/etc/nginx, /etc/letsencrypt

Excludes

*.log

Site roots that aren’t a known platform

Static builds, bespoke PHP, anything application detection won’t recognise on its own.

Paths

/srv/www/marketing-site

Excludes

node_modules, .git, *.log

Service definitions and scheduled jobs

The wiring that makes a rebuilt box behave like the one it replaced.

Paths

/etc/systemd/system, /etc/cron.d, /var/spool/cron/crontabs

Excludes

—

Application config living outside the repo

Environment files and keys that were never committed anywhere on purpose.

Paths

/opt/app/config, /etc/app/secrets.d

Excludes

*.sock, *.pid

The archive is yours before it is ours

Backups land in an S3-compatible bucket you own — Backblaze B2, Wasabi, Cloudflare R2, plain S3, or anything that speaks the same API — or in your own Google Drive, Box, Dropbox or OneDrive.

  • Nothing passes through us. Your server uploads the archive to your bucket itself, part by part, with short-lived links we sign for it. If it can't, that run streams through our worker instead — never written to disk, never kept — and its log says so. The Agent uploads directly too, with no SSH port open.

  • Hashed on the way past. An MD5 is computed as the archive streams and stored with the run alongside the byte size, so you can check what landed against what left.

  • Ordinary objects, ordinary tar. Cancel tomorrow and every archive you already have stays exactly where it is, in a format any machine with tar can open.

Four things file backups will not do

Worth knowing before you point a job at a terabyte, rather than after.

Every run writes a full archive

There is no incremental mode, no block-level delta, no deduplication between runs. A 400 GB tree costs 400 GB of upload and 400 GB of storage on every single run. Exclude aggressively, or take a provider snapshot of the whole volume instead.

Old archives expire on the job’s window

Retention deletes archives older than the job’s window out of your bucket — only the ones we wrote, by the exact key we recorded, and never the job’s newest backup. The run history stays, so an expired archive still shows when it was taken and what it hashed to.

Restore puts the whole archive back, not selected files

You can restore a run onto any server from the dashboard, choosing the root it extracts into — but it is the whole archive, and it is a merge: files in the archive overwrite what is there, while anything added since the backup stays and anything deleted since stays deleted. There is no point-and-click browse to pull out one file. For that, download the object from your bucket and extract what you want — it is an ordinary .tar.gz that outlives your subscription.

tar reads a filesystem that is still moving

Archiving the data directory of a running MySQL or PostgreSQL server gives you files captured mid-write, not a restorable database. Use a Database job for that — pg_dump and mysqldump produce a consistent dump; tar over live table files does not. SQLite is the exception: a SQLite database under the job’s paths is copied with SQLite’s own backup API before the archive is made, so it has every committed write. That needs python3 or sqlite3 on the server, and the run’s log names any database it had to copy as a plain file.

Everything else it does

Storage, schedules, alerts, recovery and team access, in one place. Which plan each one starts on is on the pricing page.

Bring your own storage
Backups land in your own S3-compatible bucket — Backblaze B2, Wasabi, Cloudflare R2, or plain S3 — or in your own Google Drive, Box, Dropbox or OneDrive. You hold the keys and the data.
Snapshots stay with your provider
Provider snapshots are created through the provider's own API and never leave your account. We store the snapshot ID, not the image.
Eight providers, one dashboard
DigitalOcean, Hetzner, Vultr, Linode, AWS EC2, AWS Lightsail, Google Compute Engine and Microsoft Azure — scheduled and reviewed from the same place.
A replacement server on demand
Recover now builds a new server on your own DigitalOcean, Hetzner, Vultr, Linode, AWS EC2, AWS Lightsail, Azure or Google Compute Engine account, from its snapshot or from its backups, software included.
Failover on any cloud
When a server stops answering, its traffic moves to the recovery server: by reserved or floating IP where your cloud has one, or by your DNS on Cloudflare, which works on every cloud.
Know it's down, with the way back
Uptime monitors for sites, ports and scheduled jobs confirm an outage before alerting, name the server's newest backup, and publish a status page. On paid plans.
Your DNS zones, backed up
Every record in a Cloudflare zone, kept in your own storage as a BIND file too. A restore previews what differs and writes back only that.
Schedules that fit your traffic
Hourly, daily, weekly, monthly, or a fixed interval in minutes — anchored to your timezone, so a 02:00 job stays at 02:00 across a DST change.
Retention that prunes itself
Set how many days to keep. Older snapshots and archives are cleaned up after each successful run, so storage bills stay flat.
Every run on record
Status, duration, size and trigger, with each step it took in order and its warnings and errors kept in place — so a failure tells you which step broke.
Checksummed on upload
Every archive is hashed as it streams to your bucket and the checksum is stored with the run, so you can verify what landed.
Run on demand
Trigger any job by hand before a migration or a risky deploy, without touching its schedule or its retention window.
Alerts on five channels
Email plus Slack, Microsoft Teams, Google Chat, and Discord — on success, on failure, and on a job that missed its schedule entirely.
Encrypted credentials
SSH keys, database passwords, and storage secrets are sealed with AES-256-GCM before they touch the database.
Team access with roles
Invite your team into a shared workspace as owner, admin, or member, so backups outlive whoever set them up.
View all features
Daniel Kim
“The biggest advantage for us is that VPS Snaps works with the infrastructure we already have instead of forcing us into a proprietary backup environment. Provider snapshots stay inside our cloud account, while database and file archives can go directly into our own bucket.”
Daniel KimCloud Infrastructure Engineer

Point a job at your first directory.

Add a server over SSH, list the paths worth keeping, and watch the first archive land in your own bucket.

Your credentials are encrypted with AES-256-GCM, your backups never live on our storage, and our GDPR data processing agreement is public.

No credit card required. Cancel anytime.