All systems operational 8 cryptocurrencies accepted · Monero welcome No-KYC policy
KernelVPS

Backup & Recovery

How to Back Up a VPS: Encrypted, Offsite and Restorable

Most servers are backed up in a way that fails in exactly the situation that destroyed them. Here is how to build one that survives a dead host, a bad command and a stolen root password — without handing a plaintext copy of everything to whoever stores it.

Security16 min readKernelVPS team

How to Back Up a VPS: Encrypted, Offsite and Restorable

Every backup works until the day it is needed. The snapshot sits on the platform that just went down. The nightly tarball has been failing silently since a disk filled up in March. The database dump was a file copy taken mid-write and restores to nothing. Backups are the one part of a server you cannot judge by looking at them — only by restoring them. This is how to build one that survives hardware failure, your own hands and someone else holding your credentials, without giving a readable copy of the machine to whoever stores it.

Four things destroy a server, and each needs something different

Design the backup around the failure, not around the tool. Four scenarios account for essentially every real loss, and each demands something different from the copy you keep. A setup that handles one of them feels completely adequate until it meets another.

Hardware or host failure

The disk, the node or the datacenter goes. Any copy held anywhere else recovers you. This is the only failure a same-platform snapshot reliably handles, which is exactly why so many people believe snapshots are enough.

Your own hands

A wrong flag, a migration script pointed at production, a cleanup that removed more than intended. The damage replicates instantly to anything that mirrors, so what saves you is history — a version from before the mistake, not a current copy of after it.

Compromise and ransomware

An attacker with root has exactly the reach your backup job has: the same credentials, the same destination, the same schedule. If the server can delete its own backups, they will be deleted. Survival depends on the copy being append-only or out of reach entirely.

Losing the account, not the server

A billing lapse, a suspended account, a takedown in the wrong jurisdiction. The hardware is fine and you simply cannot reach it. Only a copy under a different provider, with a different payment path, helps here.

Write down which of the four you are actually defending against before you choose anything. A nightly copy into a second directory on the same disk covers exactly one of them — the least likely one — while feeling entirely like a backup. Most setups that fail in production fail because nobody ever named the scenario.

Snapshots are not backups

The words get used interchangeably and they describe different objects with different failure domains. Knowing which one you have decides whether you have anything at all.

SnapshotA point-in-time copy of a volume held by the platform, sitting next to the original. Instant to take, instant to roll back, and gone with the platform it lives on. Perfect before a risky upgrade; worthless as your only copy.
Disk imageA full block-level copy of the volume — portable, large and slow. Restores a machine exactly as it was, including whatever was already broken. Good for rebuilding, poor for retrieving one file as it looked three weeks ago.
File-level backupSelected paths, deduplicated and versioned, stored as a repository you can query. This is what people mean when they say backup, and the only thing that answers the question "what did this config look like on the 4th?"
Offsite replicaThe same repository copied to a second location under a different provider. Not a different backup — the same one, somewhere that cannot fail at the same moment as the first.

Use snapshots for what they are genuinely excellent at: a five-second undo before you touch the kernel, the bootloader or a database schema. Take one, do the risky thing, delete it when it works. What you must never do is let "there is a snapshot" become the reason there is no backup — a snapshot shares its fate with the platform holding it, and a suspended account takes both at once.

3-2-1, and the two numbers everyone drops

The old rule survives because it describes independence rather than a filing system: three copies of the data, on two different kinds of storage, one of them somewhere else. Two additions handle failures that were rare when the rule was written and are routine now.

  • Three copies. The live data plus two backups. Two copies means you are one bad restore away from none.
  • Two media, or two providers. On rented infrastructure, "media" really means administrative independence — a second copy under the same account, on the same platform, paid from the same balance, is one copy with extra steps.
  • One offsite. Different building, different network, different jurisdiction if that matters to you. /locations is the practical version of this: pick a region that fails independently of the one you are protecting.
  • One immutable or offline. A copy the server itself cannot delete, because whoever owns the server owns its credentials too.
  • Zero unverified restores. A backup you have never restored is a hypothesis. The number that counts is how many restores you have completed, not how many jobs reported success.

Back up the data, rebuild the rest

The instinct is to image everything. It is expensive, slow to restore, and it faithfully preserves the compromised binary, the broken package state and the config drift you no longer remember creating. A server holds three kinds of content, and only one of them belongs in the backup.

ReproducibleThe operating system, packages, container images, compiled artefacts. Reinstalled in minutes from a script. Backing it up costs storage and restores you into the past.
IrreplaceableDatabases, uploaded files, mail spools, wallets, keys, container volumes — anything a person or a process created that exists nowhere else. Losing this is unrecoverable at any price. This is the backup.
Reconstructible, but expensively/etc, systemd units, nginx and firewall rules, cron and timer definitions, TLS certificates and ACME account keys. Small, cheap to store, and the difference between a two-hour rebuild and a two-day one.
  • Include /etc, /home, /root, /srv, your web root, your application's state directory, named container volumes, and a directory of fresh database dumps.
  • Include the deployment recipe itself — compose files, Ansible or shell scripts, the notes you wrote at 2am. Keep it in version control too, but put a copy in the backup so recovery never depends on a second service being reachable.
  • Exclude /proc, /sys, /dev, /run and the temporary directories. They are kernel interfaces and scratch space; copying them wastes time or hangs the job outright.
  • Exclude package caches, build directories, dependency trees and virtualenvs — anything a build step regenerates. On a typical application server this is most of the disk.
  • Exclude the live database files if you are dumping the database properly. Backing up both means the larger, useless copy is the one someone restores at three in the morning.
  • Do not exclude hidden files. Half of what matters on a Linux box starts with a dot.

Databases will not survive a file copy

This is the single most common reason a restore fails. A running database keeps state in memory and writes out of order; copying its files while it runs captures a torn, half-written state that may restore, may restore silently corrupted, or may not restore at all. Take a proper dump, then back up the dump.

  • PostgreSQL: pg_dump per database, or pg_dumpall for the whole cluster including roles. Where losing a day is unacceptable, add WAL archiving so you can recover to a point in time instead of to last night.
  • MySQL or MariaDB: mysqldump with --single-transaction gives a consistent snapshot on InnoDB without blocking writes. It does not on MyISAM — one more reason not to run MyISAM. For large datasets, a physical tool such as mariabackup restores far faster than replaying a dump.
  • SQLite: never copy the file. Use the .backup command or VACUUM INTO, which take the lock correctly. Copying a database with an active write-ahead log is a coin flip you will lose eventually.
  • Redis: trigger a background save and back up the resulting snapshot file, or run with append-only mode and back up the log. Copying a live snapshot mid-write gets you a truncated file that loads as an empty dataset.
  • Containers: the volume is the data. Stop the stack for the seconds a copy takes, or run the dump tool inside the container — but do not tar a running database's volume and call it a backup.
  • Anything else with a persistent process — search indexes, message queues, ledger daemons — has its own consistent-export command. Find it now, not during the outage.

Filesystem snapshots solve this from the other direction: LVM, ZFS and btrfs freeze a consistent view of the volume in milliseconds, and you back up the frozen view while the database keeps serving. That is the right answer for datasets where a dump takes hours. It is not a reason to skip the dump for a 200 MB database, where the dump is simpler, portable across engine versions, and readable by a human when something has gone strange.

Choosing a tool

Four tools cover almost every case. The property that matters most is where encryption happens. If data is encrypted only in transit, and then at rest by the storage provider, the storage provider can read it — and the backup has quietly become the weakest point in a system you hardened everywhere else.

resticA single static binary. Deduplicating, versioned, encrypted and authenticated client-side before anything leaves the machine. Speaks SFTP, S3-compatible object storage and anything rclone can reach. The default recommendation for a VPS: the far end needs nothing but an SSH account.
BorgBackupThe same model with excellent compression and a genuinely useful append-only server mode. Needs Borg at both ends and stores the repository on a filesystem rather than object storage — fine when the destination is a second server you control, awkward when it is a bucket.
rsyncNot a backup tool but an excellent transport. With hardlinked dated trees it produces browsable versions for almost no extra space. No encryption at rest, no integrity checking, no deduplication. Use it when the destination is already encrypted and you want copies you can read with ls.
rcloneThe bridge to object storage, with a crypt layer that encrypts names and contents before upload. Pair it with restic, or use it to push an already-encrypted repository to a second provider. Sync semantics rather than versioning — a deletion propagates unless you configure it not to.

Whatever you choose, the passphrase or key must exist somewhere other than the server being backed up. This is the trap that catches careful people: the repository key stored in /root, faithfully backed up inside the repository it unlocks. Print it, or keep it in a password manager you can open from a machine that is still alive. A repository you cannot decrypt is indistinguishable from no backup at all.

Where the second copy should live

The destination is a jurisdiction and a billing relationship as much as it is disk space. Four options, in rough order of how independent they are from the server you are protecting.

A second server in another region

The straightforward answer: a cheap instance in a different country, reachable over SSH, running nothing but sshd and a repository. A 1 GB /vps plan holds a small fleet's backups, and the account can be locked to a single forced command so a stolen key opens no shell.

Storage-class disk

Once the dataset runs to hundreds of gigabytes, HDD capacity on an unmetered uplink costs far less per terabyte than NVMe, and backup writes have no need of NVMe latency. /storage is built for this: terabyte-class RAID-protected disk, full root, no content inspection.

S3-compatible object storage

Convenient, priced per gigabyte, and often with object-lock support that gives real immutability. Read the egress pricing before relying on it — pulling a terabyte back in an emergency is a poor moment to discover what retrieval costs.

Hardware you own

An external disk or a machine at home, pulled rather than pushed. Slower and manual, and the only copy on this list that no provider, court order or billing dispute can touch. Worth keeping for data you genuinely cannot recreate, even if it lags a week behind.

Match the backup's privacy properties to the server's. Encrypting a disk with LUKS and then shipping nightly plaintext backups to a bucket registered to your card undoes the entire exercise: the data is now readable, and it is filed under your name. If the server was worth paying for anonymously, so is the copy — encrypt client-side, and buy the destination the same way you bought the origin.

Building it, step by step

  1. 1

    Decide the two numbers first

    How much data you can afford to lose — the gap between runs — and how long you can afford to be down. Everything else follows from those two answers. Hourly backups of a static site are theatre; nightly backups of an order database are a decision to make deliberately rather than inherit from a tutorial.

  2. 2

    Create the destination

    A second instance in another region with its own SSH key and a dedicated unprivileged user whose home is the repository. Nothing else runs there. Restrict the key to a forced command so a stolen credential can only append backups, never open a shell.

  3. 3

    Generate the key and store it elsewhere

    A long random passphrase, recorded somewhere that survives the loss of the server. Initialise the repository, then prove you can list its contents from a third machine using only what you wrote down. If you cannot, fix that before writing a single backup.

  4. 4

    Dump the databases first

    A short script that writes consistent dumps into a staging directory and exits non-zero if any of them fails — run before the file backup, not alongside it. A job that carries on after a failed dump is how people end up with thirty days of zero-byte files.

  5. 5

    Back up the paths that matter

    Point the tool at the include list, apply the excludes, and sanity-check the first run. If a fresh repository of a 40 GB server comes to 300 MB, something is being silently skipped; if it comes to 38 GB, your excludes are not working.

  6. 6

    Schedule it and make failure loud

    A systemd timer with a randomised delay, or cron if that is the habit. Then make the job report: a heartbeat to a monitor on success, and an alert when the heartbeat stops arriving. Silent failure is the normal failure mode of backups, because nothing visibly breaks when they stop — until everything does.

  7. 7

    Set retention and actually prune

    Hourly for a day, daily for a fortnight, weekly for a couple of months, monthly for a year. Then run the prune and confirm the repository stops growing. Retention that is configured but never executed fills the destination and takes the backups down with it.

  8. 8

    Restore something today

    Not a test job — a real file, to a scratch directory, opened and checked. Then put a date in the calendar for the whole machine. The first full restore always surfaces something: a missing path, a permission, a certificate, a database user that only ever existed on the old box.

Push the backup from the server outward and you have accepted that anyone with root on it can destroy every copy. Run it the other way — the backup host connects in, pulls, and disconnects — and a compromised server cannot reach the repository at all, because it holds no credentials for it. Pull is more work to set up and it is the single largest improvement most setups can make.

Retention, and why longer is cheaper than it sounds

Retention usually gets set by whatever fits the disk, then forgotten. It deserves one deliberate thought, because it decides which mistakes are recoverable. A seven-day window catches a file deleted on Tuesday. It does not catch corruption that started six weeks ago and surfaced when a report came out wrong, or an intruder who sat quietly on the machine for a month before acting.

Hourly, kept a dayFor anything transactional. Cheap once deduplication is doing the work, and the difference between losing an hour of orders and losing a day of them.
Daily, kept two weeksThe working set. Nearly every restore you will ever perform comes from here.
Weekly, kept two monthsThe window for damage nobody noticed immediately. Slow corruption and quiet compromise both live in this range.
Monthly, kept a yearCheap insurance, and often an accounting or contractual requirement. Twelve monthly points on a mostly-static server cost a fraction of twelve full copies.

Deduplication makes this far cheaper than the table suggests: the second run against a mostly-unchanged server stores only what changed, so a year of monthly restore points on a 40 GB machine typically costs a few gigabytes rather than half a terabyte. Set the policy on what you need to recover from, then check the bill. You will usually find you can afford the generous version.

Immutability: the part that stops ransomware

Everything above assumes the adversary is entropy. If the adversary is a person with root, an ordinary backup job is an instruction manual — the credentials are on the box, the destination is in the config, and the repository gets wiped before the encryption starts. Four mechanisms break that chain, and any one of them changes the outcome.

  • Append-only repositories. Borg's server-side append-only mode, or restic's REST server in append-only mode, accept new data and refuse deletions. The server can write; only you, from somewhere else, can prune.
  • Pull-based backups. The backup host initiates the connection and holds the only credentials. The production server has no key, no destination address, and no route to the repository at all.
  • Object lock. S3-compatible storage with a retention period enforced at the bucket level, where deletion is refused by the storage layer regardless of what the credentials would otherwise permit.
  • Separate credentials per host. One compromised machine should not expose every other machine's history. Distinct keys, distinct paths, distinct restrictions.
  • One copy that is genuinely offline. A disk that is unplugged is immune to every remote attack ever written. Unfashionable, and unbeaten.

The restore drill

A restore is a procedure, and a procedure nobody has performed is fiction. Run this once now and once every six months, and write down what you learn — the notes end up as valuable as the data.

  1. 1

    Deploy a blank instance

    Same operating system version, nothing else installed. A short-lived VPS is enough, and the whole exercise costs less than lunch.

  2. 2

    Restore using only what you wrote down

    The repository address, the passphrase, the commands. If you need something that exists only on the server you are pretending is dead, you have just found the flaw — on a day when finding it costs nothing.

  3. 3

    Bring the data back before the application

    Load the database dump, put the files where they belong, then fix ownership and modes. Ownership is the usual surprise: numeric user IDs from the old box rarely line up on the new one.

  4. 4

    Start the service and actually use it

    Not a status command — log in, load a page, run a query, send a message. A service that starts is not the same thing as a service that works.

  5. 5

    Time it, and write the number down

    How long did the whole thing take? That is your real recovery time, and it is almost always several times the estimate. Keep the notes beside the passphrase and update both whenever the stack changes.

What it costs, honestly

Backup is the cheapest insurance in infrastructure, and it is routinely skipped on price. Some concrete numbers for a small server, assuming the data compresses and deduplicates the way ordinary data does.

A 40 GB web and database serverRoughly 8 to 15 GB in a deduplicated repository after compression, with a year of retention adding a few gigabytes on top. A 1 GB instance at $3.49/mo in another region holds it comfortably — less than the domain it serves.
A few hundred gigabytesMail archives, media libraries, a document store. This is where HDD capacity wins: 1 TB of /storage at $8.99/mo holds years of versions, and an unmetered uplink means the first upload does not arrive with a bandwidth bill.
TerabytesVideo, datasets, seedbox output. 4 TB at $23.99/mo, and the real decision becomes what needs versioning versus what needs one copy. Not everything deserves a year of monthly restore points.

Compare any of those to the cost of the outage they prevent. Naming the number is the point — the argument against backups is never really about money once the money has been written down.

Where the host fits in

A backup plan has the same two dependencies as the server it protects: somewhere independent to put the copy, and a way to pay for it that does not create a fresh record of who you are. Both matter more here than at the origin, because the backup is a complete copy of everything the origin was protecting.

Every /vps and /storage plan here deploys from a prepaid crypto balance with no KYC, across fifteen regions listed on /locations — so the second copy can sit under a different jurisdiction from the first without a second identity check anywhere in the chain. Instant snapshots are included on every instance for the five-second undo, unmetered bandwidth means neither the first upload nor the emergency restore is a metered event, and /storage adds terabyte-class RAID-protected disk from $8.99/mo with no content inspection. /pay-with covers the accepted coins, /offshore-hosting sets out what jurisdiction genuinely changes, and /guides has the companion pieces on disk encryption and on what a host can and cannot see about a machine.

The checklist

  • Name the failure you are defending against before choosing a tool.
  • Treat snapshots as an undo button, never as the backup.
  • Back up data and configuration; rebuild the operating system from a script.
  • Dump every database with its own consistent-export command, and back up the dump.
  • Encrypt client-side, before anything leaves the machine.
  • Keep the repository passphrase somewhere that survives the loss of the server.
  • Put at least one copy under a different provider, region and payment path.
  • Make one copy append-only, pull-based or offline so a compromised root cannot erase it.
  • Alert on the absence of a successful run — failures are silent, and silence is the symptom.
  • Restore a file today and the whole machine twice a year. Time it and write it down.
Are provider snapshots enough on their own?

No, and this is the most common gap in otherwise careful setups. A snapshot lives on the same platform as the volume it copies, so it does not survive a platform-level failure, an account suspension or a billing lapse — three of the scenarios where you most need it. It also usually keeps only a short history, so it will not recover a file deleted last month or a corruption that began six weeks ago. Snapshots are excellent as a five-second undo before a risky change: keep them, use them daily, and keep a real backup somewhere else.

restic or Borg — which should I use?

restic if the destination is object storage or a plain SSH account, because it needs nothing installed on the far end and speaks S3 natively. Borg if the destination is a Linux box you control and you want its append-only server mode and slightly tighter compression. Both deduplicate, both encrypt and authenticate client-side, both are mature and widely deployed, and either is a defensible choice. The wrong answer is spending a month comparing them while the server has no backup at all — pick one this afternoon and change your mind later if it ever matters.

How often should I back up a VPS?

The interval is simply the maximum amount of work you are willing to redo. For a static site, weekly is honest. For anything users write to, nightly is the floor and hourly is cheap once deduplication is doing the work — the second run of the day usually stores a few megabytes. Weigh the value of one day's data against the cost of storing twenty-four restore points instead of one, and the answer is normally obvious.

Should I back up the whole disk or just my data?

Data and configuration, in almost every case. A full disk image restores the machine exactly as it was, including the compromise you are recovering from and the package state you no longer understand, and it is slower to both create and restore. A file-level backup of /etc, your application data and your database dumps, paired with a script that rebuilds the operating system, restores faster and cleaner. Image the disk when you need bit-exact forensic preservation, or when the machine is a black box somebody else built.

My provider says the disks are encrypted — is my backup encrypted?

Not in any sense that helps you. Provider-side encryption protects against a drive being carried out of a rack; the provider holds the key, so the data remains readable by the provider and by anyone who can compel the provider. Client-side encryption — restic, Borg, rclone's crypt layer, or an encrypted archive — means what arrives at the destination is meaningless without a passphrase that never left your machine. For a privacy-critical stack this distinction is the whole point, because the backup is a complete copy of everything the server was protecting.

How do I stop ransomware from encrypting my backups too?

Assume that anything the server can reach, an attacker with root can destroy — the credentials, the destination and the schedule are all sitting on the box. Break that reach in one of three ways: an append-only repository that accepts writes but refuses deletions, a pull model where the backup host connects inward and the server holds no credentials at all, or object storage with a lock the storage layer itself enforces. Then add long retention, so a slow and quiet compromise does not simply age out of the window before anyone notices, and keep one copy offline where no remote attack can reach it.

Put it into practice.

Deploy an offshore server from $3.49/mo · 8 cryptocurrencies · no KYC.