Feature catalogue
Everything it does.
And where each thing stops.
51 capabilities across eight categories, every one of them shipped and checked against the source. Where something is bounded, the bound is written next to it rather than left for you to find at 3am.
Backup Jobs
Automated backup schedules
postgres-main nightly
Last run 6h ago
web-01 snapshots
Last run 9h ago
api-prod volumes
Last run 4m ago
staging-db weekly
Last run 3d ago
Eight categories
Skip to the part you came for. Everything below is a capability that exists in the product today; the last section is the list of things that do not.
Eight different ways to capture a system
Each one talks to a different thing — a provider's API, a shell over SSH, the Kubernetes API, an agent you run yourself, or WordPress itself. Five are job types you pick from; detection creates jobs for you, the Agent is how a job reaches a machine we cannot, and the plugin backs up a WordPress site with no SSH at all. They share a schedule engine, a storage destination and a run history, and nothing else.
- Provider snapshots
- One connection to DigitalOcean, Hetzner Cloud, Vultr, Linode, AWS EC2, AWS Lightsail, Google Compute Engine or Microsoft Azure covers every instance in that account. Each run calls the provider's own snapshot API, so the image is created inside your account and stays there whether or not you keep paying us.
- Where it stops: Crash-consistent, not application-consistent — nothing reboots or freezes the machine to image it. Linode captures a single disk per job, so you choose which one.
- Database backups
- pg_dump for PostgreSQL, mysqldump for MySQL and MariaDB, mongodump for MongoDB, executed on the server itself over SSH. The SQL dumps are piped through gzip; mongodump compresses its own archive. Either way the server uploads the compressed stream to your bucket as it is produced; it never passes through us.
- Where it stops: The dump runs as the database user you supply, and the client tool has to already be installed on the server. We do not connect to your database over the network.
- Docker volume backups
- Every named volume is archived by a throwaway alpine container — docker run --rm -v volume:/data … tar czf — so nothing has to be stopped. A volume holding SQLite databases is archived from the host instead, with each database copied by SQLite's own backup API first, so apps such as Uptime Kuma and Vaultwarden keep every committed write. Your docker-compose.yml files and docker inspect output for named containers are collected alongside the volume data.
- Where it stops: A volume that fails to archive fails the whole run, and the error names it — a successful run always contains every volume you asked for.
- File backups
- Any absolute path on the server — /etc, a web root, an uploads directory, a certificate store — tarred and gzipped over SSH with your own tar --exclude patterns applied. SQLite databases under those paths are copied with SQLite's own backup API first, so the archive has every committed write while the app keeps running. A path that has moved or been deleted is logged and skipped instead of failing the whole run.
- Application detection
- Scan a server and VPS Snaps searches /var/www, /home/*/public_html, /home/*/htdocs, /home/master/applications/*/public_html, /home/forge/* and /srv/www for wp-config.php, .env and config.production.json. A recognised install becomes a paired file job and database job, with the credentials read out of the application's own config file.
- Where it stops: WordPress, Laravel, Craft CMS, Ghost and Nextcloud are recognised by name and have their database details extracted. Anything else is still offered as a file job — you fill in the database side yourself.
- Kubernetes backups
- Connect a cluster with a service-account token; there is nothing to install. Per namespace we export ConfigMaps, Secrets, Services, Deployments, StatefulSets, DaemonSets, Ingresses, Jobs, CronJobs and PersistentVolumeClaims to your bucket, then attempt a CSI VolumeSnapshot for each PVC whose StorageClass has a matching VolumeSnapshotClass.
- Where it stops: If Velero is already running in the cluster we drive its Backup CRD instead, because it moves volume data and we do not. Volume snapshots are best-effort: a PVC with no matching snapshot class is skipped and logged.
- Agent for private infrastructure
- For machines with no inbound path at all. A small Docker container you run on the box holds an outbound WebSocket to us — no public IP, no port forward, no firewall exception — takes the job, runs it locally, and uploads directly to your bucket.
- Where it stops: Database, Docker and File jobs only. Provider snapshots and Kubernetes go through their own APIs and never needed a way in.
- WordPress plugin
- For WordPress sites with no SSH access: install the VPS Snaps plugin from wordpress.org and connect it to your workspace. It backs up the database and files from inside WordPress, whole multisite networks included, uploads straight to your own storage with short-lived signed links, and restores or moves the site from the dashboard.
- The plugin on wordpress.org
- Where it stops: It backs up the WordPress site, not the rest of the server. Every plan, Free included.
One scan, matched file and database jobs
Application detection exists because the tedious part of setting up a WordPress or Laravel backup is not the schedule — it is copying a database name, user and password out of a config file without a typo, twice, for every site on the box.
The scan reads wp-config.php with its PHP defines, .env for Laravel and Craft (including Craft’s CRAFT_DB_* prefixes), and Ghost’s config.production.json, then proposes a file job for the document root and a database job for what it found. Sensible excludes come with it — vendor, node_modules, storage/logs.
Scan server
Looks for WordPress, Laravel, Craft CMS, Ghost, and Nextcloud installs in common web-root locations. Database credentials are read automatically where the config format allows it.
Storage destination for created jobs
www/acme-blog
/var/www/acme-blog
File backupDatabase backup (acme_blog)
www/acme-app
/var/www/acme-app
File backupDatabase backup (acme_app)
sites/acme-docs
/home/deploy/sites/acme-docs
File backupDatabase backup (ghost_prod)
When the server itself is gone
A backup you cannot get running again is half a plan. These build the replacement on your own cloud account, keep one ready, and move your traffic to it — by IP where your cloud has one that moves, and by DNS on any cloud.
- Scheduled test restores
- On the schedule you choose, the newest backup is restored onto a throwaway server on your own cloud, through the same pipeline a real restore uses, checked for what came back, and the server destroyed. A backup that does not restore alerts you that day.
- How test restores work
- Where it stops: File, Docker and database jobs, with Railway and Render Postgres tested inside your own account; not provider snapshots, Kubernetes, WordPress, DNS zones or Agent jobs. Every 30, 90 or 180 days, off by default, and billed by your cloud at a few cents a test.
- Recovery servers
- Recover now builds a new server on your own DigitalOcean, Hetzner, Vultr, Linode, AWS EC2, AWS Lightsail, Azure or Google Compute Engine account: from the server's newest snapshot when it has one, or a fresh Ubuntu with its databases, files and Docker volumes restored from the newest backups — and the software it ran, from packages and repositories to its web server, PHP, TLS certificate, cron and services.
- Where it stops: Its data is as old as the backups it was built from, and the page says how old before anything is built. Standard, Pro and Agency plans.
- Warm standby
- Keeps a recovery server built and ready, rebuilt from newer backups as often as you allow. The new one is ready before the old one is destroyed, so there is always one to switch to.
- Where it stops: It runs all the time, so your cloud bills it like any server of its size. Pro and Agency plans.
- Automatic failover, on any cloud
- Checks the server every minute, and before calling an outage asks from inside your account too — from the warm standby, or a small probe machine started beside the server and removed afterwards. Then it moves the traffic: the reserved IP on DigitalOcean or Vultr, the floating IP on Hetzner, the Elastic IP on AWS EC2, the static public IP on Azure, the static external IP on Google Compute Engine, the server's own IP on Linode — or, on any of those and AWS Lightsail, your domain's A records on Cloudflare, pointed at the recovery server with nothing else in the zone touched.
- Where it stops: Traffic moves to data as old as the last backup. It never switches back on its own, and stays off until you re-arm it. Pro and Agency plans.
- DNS zone backups
- Connect Cloudflare and any zone can be a backup job: every record, kept in your own storage with the zone as a BIND file any DNS host imports. A restore previews what differs from the zone now, then writes back only those records after a safety copy — and undoes itself if Cloudflare refuses a change partway.
- How DNS backups work
- Where it stops: Cloudflare zones only. A zone has no server of yours to run on, so our worker reads it through Cloudflare's API and writes it straight on to your storage, never keeping it.
- Continuity plans
- The systems you'd need back, each with a recovery point and recovery time target, checked against what your backups actually did: the newest backup's age, the last restore that proved it, and how long recovery took. A signed-off plan document, reviewed yearly, with the evidence mapped to SOC 2, ISO 27001 and HIPAA.
- How continuity plans work
- Where it stops: It records evidence; it is not a certification. The written procedures are yours to fill in. Pro (one plan) and Agency (one per client).
Knowing it's down, and saying so
Uptime monitors that confirm an outage before they alert, put the way back in the alert, and publish a status page for your customers. On paid plans.
- Uptime monitors
- Web pages, by the status code you accept and a word that must (or must not) be on the page, and ports, by whether they open. A failure is checked again 20 seconds later, twice, and only the third in a row is an outage, after the checker has made sure the fault isn't its own. One alert when it's confirmed, one when it's back, on the channels your backup alerts use.
- How uptime monitoring works
- Where it stops: Checked from one place, New York, at most once a minute (every five minutes on Starter). No pages behind logins, no ping or DNS checks yet, no text messages or calls. Starter and above.
- Heartbeats for scheduled jobs
- A URL for a cron job or script to call when it finishes. If the call doesn't arrive within the job's period and the grace you allow, it's down, and you hear about the job that silently stopped. A ping lost to an outage of ours isn't counted against it.
- Where it stops: Your job has to make the call: we can't see inside your server. Starter and above.
- The alert comes with the way back
- A monitor linked to a server says, in its alert, how old that server's newest backups are, and whether it has a recovery plan — with Recover now beside it on the monitor's page. Every monitored https page also warns 14 and 3 days before its certificate expires.
- Where it stops: Recover now is on Standard, Pro and Agency. A monitor never moves traffic itself; automatic failover keeps its own checks.
- Status pages
- A public page at status.vpssnaps.com listing the monitors you choose under names you choose, each with 90 days of uptime bars, the outages, and the updates and planned-work notices you post. It never shows addresses, ports or error text, carries no analytics or advertising scripts of ours, and is kept for 30 seconds between readings so an outage's crowd doesn't slow it.
- Where it stops: Updates are the ones you write; no email subscriptions yet. How many pages depends on the plan, from one on Starter.
- Status pages on your own domain
- Add one CNAME and the page is also at status.yourcompany.com, with its own certificate from Cloudflare, usually live within minutes — and "Powered by VPS Snaps" can come off.
- Where it stops: Agency plan.
When it runs, and what gets thrown away
One scheduler ticks every minute for every job type. Retention is set per job, in days, and applied after a run succeeds — never speculatively, and never to something we did not create.
- Seven cadences from one dropdown
- Manual only, every 5 minutes, hourly, every 12 hours, daily, weekly, or monthly. Daily, weekly and monthly jobs also take a time of day.
- Where it stops: How fast you are allowed to go is a plan limit, checked when you save the job rather than silently ignored at run time.
- Anchored to your timezone
- Daily, weekly and monthly runs fire at a wall-clock time in an IANA timezone you choose, and the next run is recomputed against that zone each time. 02:00 stays 02:00 through a daylight-saving change instead of quietly sliding an hour.
- Intervals measured from the last run
- Every-5-minutes and every-12-hours are a plain elapsed interval, not a clock alignment. A run that takes eleven minutes pushes the next one out rather than stacking a queue behind it.
- Overlap guard
- A job that already has a pending or running execution is skipped on the next tick and the reason is logged. A backup that takes longer than its own interval cannot start on top of itself.
- Run on demand
- Trigger any job by hand before a migration or a risky deploy. It uses exactly the same code path as the scheduled run, which is what makes it a real test of the credentials, not a dry run.
- Pause without deleting
- Disable a job and the scheduler stops picking it up. Its configuration, run history and everything it has already written stay exactly where they are.
- Retention on both sides
- Choose a window between 1 and 365 days, capped by your plan. Older copies are deleted after each successful run and in a daily sweep: DigitalOcean snapshots, Hetzner images, Vultr snapshots, Linode disk images, EC2 AMIs together with their backing EBS snapshots and GCE machine images through the provider's own API; database dumps and archives out of your bucket. Kubernetes VolumeSnapshots we created are pruned the same way, and a Velero backup is handed a matching TTL so its own controller expires it.
- Where it stops: Never a job’s newest backup, never anything a restore is reading, never the safety copy of a restore that didn’t succeed — and only objects we wrote, by the exact key we recorded.
The whole schedule fits on one form
Pick a type, name the job, choose a cadence, a retention window in days, a time of day and a timezone. That is the entire schedule surface — there is no separate policy object, no schedule library, and no cron syntax to get wrong.
Retention is a property of the job rather than of the plan, which means a nightly snapshot kept for seven days and a weekly archive kept for ninety can live side by side on the same server.
Create backup job
Configure a new automated backup
Backup type
VPS Snapshot
Snapshot a server on a connected provider
Database
PostgreSQL, MySQL, or MariaDB
Docker
Volumes and compose files
File
Any file or directory over SSH
Kubernetes
Namespace manifests and volume snapshots
Job settings
Job name
Schedule
Retention (days)
Time of day
Timezone
Your bucket, your keys, your bill
There is no hosted storage tier and no plan that includes one. Every archive lands in an S3-compatible bucket, Google Drive, Box or Dropbox account you own, which is also why cancelling VPS Snaps does not take your backups with it.
- Ten storage targets
- AWS S3, Cloudflare R2, Backblaze B2, DigitalOcean Spaces, Wasabi and UpCloud Object Storage each have a preset, and a custom S3-compatible option takes any other endpoint. Path-style addressing is used automatically for custom endpoints. Or sign in with Google and back up to a folder in your own Google Drive: VPS Snaps is granted only the files it creates. Or sign in with Box and back up to a folder in your own Box account, or with Dropbox and back up to a folder in VPS Snaps' own app folder in your Dropbox, the only part of it VPS Snaps can see.
- Where it stops: Box takes each backup as one finished file: the server, agent, site or container making it writes it to its own disk first, and the Box plan sets the largest file, 250 MB on a free account. Backups that stream through VPS Snaps reach Box only up to 64 MB. Dropbox takes backups as they stream, so it needs no spare disk and has no 64 MB limit; it accepts files up to about 2 TB.
- Tested before it is trusted
- Testing a destination writes a small object with your credentials and deletes it again, then stamps the destination as verified with the time it happened. An unverified destination is visible on the list rather than a surprise at 2am.
- Object Lock respected
- Turn on S3 Object Lock with a default retention in your own bucket, and your storage keeps every backup VPS Snaps sends there for that many days: nobody, us included, can delete or change one before then. Every upload carries the checksum a locked bucket requires, and the Storage page shows how long backups stay locked.
- Object Lock
- Where it stops: VPS Snaps reads the lock and works with it; it never turns Object Lock on for you. AWS S3, Backblaze B2, Wasabi and other S3-compatible storage that supports it.
- Streamed, never staged
- Database, Docker and file jobs cut the remote command's output into parts on the server and upload each straight to your bucket as one part of an S3 multipart upload. It holds one part in memory at a time — a few megabytes — not the size of the backup, and nothing is left behind on the server or passes through us.
- Checksummed in flight
- Every archive is MD5-hashed as the bytes stream past. The digest, the exact byte count and the full object key are stored on the run, so you can verify what actually landed instead of trusting a green tick.
- Predictable object keys
- Objects always land at prefix/job-id/filename, with an ISO timestamp in the filename — for Docker, File and Kubernetes jobs that filename also carries the job type, e.g. docker-job-id-timestamp.tar.gz. Sortable, greppable, and specific enough to write a bucket lifecycle rule against.
- Credentials encrypted at rest
- Access key and secret key are sealed with AES-256-GCM before they touch the database and are never rendered back into a form after saving.
Several destinations, different jobs
Destinations are separate records, so a nightly database dump can land in cheap object storage on one provider while a weekly full archive goes somewhere else entirely — which is the only version of “off-site” that survives losing an account.
Every destination carries its bucket, region, optional prefix and — for custom endpoints — the endpoint URL, plus the timestamp of its last successful test.
Storage Destinations
S3-compatible storage for your backups
Primary backups
acme-uploads/db · us-east-1
Tested 2h ago
Offsite copy
acme-offsite · auto
Tested 1d ago
Cold archive
acme-archive/2026 · eu-central-003
Tested 6d ago
Told where you already look
Alerting is per job and per event, so a chatty five-minute job does not have to shout on every success while a nightly database dump stays silent when it breaks.
- Email on failure or success
- Set independently on each job: notify on failure (on by default), notify on success (off by default), or neither. Failure mail carries the error text the run actually recorded.
- Four chat platforms, on every plan
- Paste a Slack, Microsoft Teams, Google Chat or Discord incoming-webhook URL. The payload carries both a text and a content field, which is precisely why one message format works across all four without you telling us which is which. Free plan included.
- Custom webhook endpoint
- Any other HTTPS receiver, on the Agency plan. Same JSON body, ten-second timeout, non-2xx treated as a delivery failure.
- Owner fallback
- Configure no destinations at all and a failed run still emails the workspace owner. There is no configuration in which a failure goes nowhere.
- Public status page
- The /status page publishes component health, active and recent incidents, and daily uptime history. The scheduler writes its heartbeat only after a tick that actually finished enqueuing work, so a process that stays alive while failing cannot certify itself as healthy.
- Missed-run alert
- If an enabled job is more than 15 minutes past its scheduled time with nothing dispatched, you get an alert on the same channels as a failure — a stuck run blocking the next dispatch, a disconnected agent, and a scheduler outage all trip it, since they leave the same symptom. It re-alerts at most once a day per job while the gap stays open, and clears itself the moment the job runs again.
What holds the keys
Running backups means holding credentials for everything you own. The parts of the system that store, hash and expire those credentials are worth being specific about.
- AES-256-GCM on every secret
- Provider API tokens and OAuth refresh tokens, SSH private keys, server passwords, database passwords, storage access and secret keys, cluster CA certificates and service-account tokens, TOTP secrets. All encrypted before insert, none returned in plain text afterwards.
- SSH keys, checked both ways
- Create a keypair in the dashboard or paste an existing private key; the public key and its fingerprint are shown so you know exactly what to authorize, and password authentication is available where a key is not an option. In the other direction, each server's host key is pinned on the first connection, and a different key stops every run before a password is sent, until an owner accepts it.
- Two-factor authentication
- TOTP on a 30-second period with six digits, plus single-use backup codes stored as bcrypt hashes. The intermediate token issued after a correct password expires on its own if the second factor never arrives.
- Tokens stored as hashes
- API keys are kept as a SHA-256 digest alongside a twelve-character display prefix and an optional expiry date; agent tokens use the same scheme. The raw value is shown once, at creation, and cannot be recovered from us afterwards.
- Rate-limited authentication
- Sign-in and registration are capped at ten attempts per IP address per fifteen minutes, and password reset at five per hour.
- Administrative audit trail
- Actions taken through the admin surface — plan edits, subscription changes, incident publishing — are written to an audit log with the actor, the target, the IP address and a timestamp.
Proof it ran, and evidence when it didn't
A backup product is only worth what its failure reporting is worth. Every run keeps its own record and its own log, and both survive long after the night in question.
- Full run history
- Status, start and finish time, duration, byte size, checksum, the exact storage path, the provider's own snapshot identifier where there is one, and what triggered the run — kept per job, not rolled up into a counter.
- Step-by-step run logs
- Each run writes timestamped info, warn and error lines as it goes: the SSH connection, each volume archived, each path skipped, the byte size on completion, the retention deletions. A failure keeps the underlying error text — the provider's or the shell's — instead of replacing it with a generic message.
- Connection tests everywhere
- Servers, storage destinations, Kubernetes clusters and provider connections each have a test that performs the real operation and records the result with a timestamp. Kubernetes tests also detect whether Velero is present and remember the answer.
- Resource browser per provider
- Once a provider is connected, the instances in that account are listed for you to pick from, so a job is built by choosing a server rather than pasting an ID you looked up somewhere else.
- A job list that reads like an ops board
- Type, schedule, retention window, last run status, next scheduled run and whether the job is paused — visible on one row, for every job, without opening anything.
- Guided first setup
- A three-step checklist — connect a provider or server, add a storage destination, create a backup job — that marks itself off as each piece lands, so a half-configured account is obvious rather than dormant.
What a run actually records
Status, duration, size and MD5 checksum sit above the storage key the archive was written to, and below that is every line the worker emitted, in order, with its level intact.
The warn line in that log is the interesting one: a path that no longer exists was skipped and the run carried on. You are told, the backup still happened, and you can decide whether the missing directory matters — which is a better outcome than a red cross at 2am for a folder someone deleted last month.
web-01 site files
2h ago · triggered by scheduler
Status
Duration
1m 44s
Size
412 MB
Checksum (MD5)
9f2c4ab1e77d...
Storage path
files/cf7q2b1x/file-backup-cf7q2b1x-2026-09-02T02-00-06-118Z.tar.gz
Run logs
Where we stop
The other half of a catalogue. These are real gaps in the product today, written down so you can rule us out quickly if one of them is a dealbreaker.
Two things still restore outside the dashboard
Database, file and Docker runs, Kubernetes runs taken with Velero, WordPress sites and whole applications restore from the dashboard onto any server in your workspace — a new one without the files included, and a run taken by the agent back onto the agent’s own machine — with every restored file compared with the backup afterwards and a check-only mode that downloads and verifies the archive without changing anything. A provider snapshot is rebuilt from your provider’s console rather than here, and a Kubernetes run taken without Velero cannot be restored at all: its manifests carry cluster state that would not apply cleanly. A database restore replaces the tables the dump contains, so a table created after the backup survives it — you get the backup’s contents back rather than a byte-exact reset. Everything remains an ordinary .sql.gz or .tar.gz with the manual commands in the help centre, which is why your recovery path still does not depend on us being online.
Test restores need a cloud to build on
A scheduled test restore of a server’s backup creates its throwaway server on your own DigitalOcean, Hetzner, Vultr, Linode, AWS EC2, AWS Lightsail, Azure or Google Compute Engine account, so without one of those connected there is nowhere to run it. Railway and Render databases are tested inside your own project or workspace instead. It covers file and Docker volume backups and PostgreSQL, MySQL, MariaDB and MongoDB, and it checks that the data came back, not that your application runs on it.
The API creates, but does not edit or restore
API keys (Standard and up) can read jobs, runs and logs, start a backup, and with Full access create agents, storage destinations, servers and backup jobs, over REST or the MCP server an AI assistant connects to. Editing or deleting anything, and restoring, are dashboard-only for now.
Cron is not in the dashboard
The schedule dropdown covers seven cadences and handles the overwhelming majority of jobs. A job on a raw cron expression is displayed but cannot be edited from the schedule form, and cron is evaluated in UTC — unlike the presets, which are timezone-aware.
Snapshots also are not off-site from the provider that holds them, and are not portable between providers. The provider pages spell out what a snapshot is and is not, per provider.
Read the detail, or just start
Every backup type has its own page covering the commands it runs, the failure modes and the trade-offs. Or skip all of it and connect a server — the free plan needs no card.

“We manage a mix of VPS instances, Docker workloads, and traditional Linux servers, so backups used to be scattered across several different processes. VPS Snaps brought all of that into one dashboard and made it much easier to see what ran, what failed, and what needs attention.”
Pick the capabilities you need. Ignore the rest.
One server, backed up free, forever — no card, no trial clock. Add the second when the first one has proven itself.
No credit card required. Cancel anytime.