تمام سرویس‌ها عملیاتی هستند آمستردام · پاریس · ریکیاویک +5 پرداخت با ارز دیجیتال
امنیت و مقاوم‌سازیمتوسط27 دقیقه مطالعهبه‌روزرسانی: 2026-09-03

Encrypted off-site backups for a VPS

Your backup is a complete second copy of your server, living somewhere you chose in a hurry. This is how to make that copy encrypted before it travels, impossible for your own server to delete, and — the part everyone skips — known to restore.

Encrypted off-site backups for a VPS
در این صفحه
  1. Why the backup is usually the least protected copy
  2. 3-2-1, and the two digits added later
  3. restic or Borg: the differences that actually decide it
  4. Where the repository lives, and who is allowed to delete it
  5. گام به گام
  6. Retention: keeping enough history for a problem you have not noticed yet
  7. Monitoring, because the failure mode is silence
  8. The failure modes that actually cost people their data
  9. What backups do not do
  10. پرسش‌های متداول

Our documentation says it in one line: backups are your responsibility. That is the honest position for any host that gives you full root, and it is also where most people stop reading. The rest of the sentence is the interesting part, because backing up a server is not really a question of which command to run. It is a question of where the second copy lives, who can destroy it, and whether the thing you have been dutifully producing every night can actually be turned back into a working machine.

Most backup setups fail one of those three tests, and almost always the same three ways: the copy sits on the same provider and the same account as the original, the credential that writes it can also delete it, and nobody has ever restored from it. This guide fixes all three. It is written for a single Linux VPS running real things — a site, a database, a Nextcloud, a node — with restic or BorgBackup doing the work, encryption happening on your machine before anything leaves it, and the far end being a second cheap server in a different country that you also own.

Why the backup is usually the least protected copy

People do the hard part and then leave the easy part undone. A server gets a hardening pass, keys instead of passwords, a default-deny firewall, maybe full-disk encryption so the disk is meaningless when the machine is off. Then every night a complete, plaintext copy of everything on that disk is pushed to a storage account opened years ago with a card, in a country nobody thought about, protected by a password that is also in the browser.

The copy deserves the same attention as the original, because it is the original, minus the uptime. It is worth being specific about what you are defending against, because the answers are different and only one of them is the one people picture:

  • The machine dies. Hardware, hypervisor, a filesystem that comes back read-only. Rare, undramatic, and the case every backup handles.
  • You break it yourself. A migration that half-ran, a rm with an ambitious glob, a configuration change that was fine until the reboot. Far and away the most common reason anyone restores anything.
  • Someone else gets root. The case that decides your design. An attacker who wants leverage deletes the backups first and encrypts the server second; if your server holds a credential that can erase the repository, you have built a system that helps them.
  • The account goes away. A payment that did not clear, a dispute, a suspension. If the original and the copy are behind the same login, they have the same single point of failure and it is not technical.
  • Someone with authority arrives. Hardware can be taken or an account frozen by process rather than by attack. A copy in another jurisdiction is the only thing that helps, and only if you can still reach it.

Notice how many of those are untouched by a snapshot taken by your own provider, on your own account, in the same datacentre.

3-2-1, and the two digits added later

The rule comes from photography rather than from systems administration — Peter Krogh wrote it down for people with irreplaceable negatives — and it survived because it is short: three copies of the data, on two different systems, one of them off-site. Each digit is defending against a different item on the list above, which is what makes it more than a slogan.

The three copies answer ordinary loss: the live data, plus two backups, so that discovering a bad backup is an annoyance rather than the end. Two different systems answers correlated failure — two copies on the same host, the same array or the same account are one copy wearing a disguise. And the off-site copy answers everything that happens to a place rather than to a disk: fire, seizure, suspension, a provider that stops answering email.

The modern extension is 3-2-1-1-0, and the two extra digits are the ones that matter in 2026. The extra 1 is a copy that is immutable or offline — something an attacker with your credentials cannot delete, which is exactly what append-only mode gives you. The 0 is zero errors on verification: a backup you have checked, not merely one you have made.

For a single small VPS this reads more modestly than it sounds. The live server is copy one. A repository on a second machine in another country is copy two, off-site, on a different system, and append-only so it is also the immutable one. A monthly full restore into a scratch server is the zero. That is the whole rule, satisfied for the price of a second small server, and the rest of this guide is the mechanics of it.

restic or Borg: the differences that actually decide it

Both tools do the same four things, and both do them well: they chunk your data by content so that a moved or renamed file is not re-uploaded, they deduplicate across every snapshot so a year of dailies costs far less than a year of copies, they compress, and — the part that matters here — they encrypt and authenticate on the client, before a single byte reaches the network. In both cases the storage holds ciphertext it cannot read and cannot alter undetected. That property is the reason this guide has no opinion about who runs your storage.

The real differences are about the far end.

  • restic is a single static Go binary and asks nothing of the destination. It writes to SFTP, to S3-compatible object storage, to its own REST server, or to anything rclone can reach. Encryption is AES-256 with a Poly1305 authenticator; repository format 2 added compression. If your target is a bucket, or a box where you cannot install software, restic is the answer and there is not much to debate.
  • Borg wants borg installed on both ends and talks to itself over SSH. In exchange it offers the thing restic needs a helper for: a genuine server-enforced append-only mode, pinned by the command= option in the remote account’s authorized_keys. A client — including a compromised one — can add archives and cannot remove them. For the threat model in the previous section, that is the single most valuable feature in either project.

So the decision is short. If you control the far end, use Borg with append-only. If you do not, use restic, and get the same property back either by running rest-server --append-only on the target or by using a bucket with object lock. Both paths are shown below.

One caveat before you commit to a repository: Borg’s command surface is not stable across its major lines — the repo::archive shorthand used below belongs to the 1.x series and changes in 2.x — so check borg --version against whichever documentation you are reading rather than the other way round. restic has been steadier here, at the cost of a repository format migration of its own.

One thing not to do is run both, on the theory that two backups are safer than one. Two half-maintained systems produce two repositories you have not verified and one restore procedure you cannot remember under pressure. Pick the one that fits your far end, and spend the effort you saved on testing it.

Where the repository lives, and who is allowed to delete it

Everything above is standard advice. This is the part that is usually left out.

The ordinary way to back up a server is to give it a credential and let it push. That credential, almost always, can also delete — because pruning old snapshots requires deletion, and it was easier to grant one key that does everything. The consequence is that the attacker who owns your server owns your backups too, and the backup is worth precisely nothing in the one scenario you most wanted it for. There are exactly three ways out:

  • Append-only at the target. The far end accepts new data and refuses removal, regardless of what the client asks. borg serve --append-only and rest-server --append-only both do this, enforced on the server, and deletion becomes something you perform deliberately from the backup host.
  • Object lock. S3-compatible storage can hold objects immutable for a retention period. Effective, and it moves the trust to a provider and a billing relationship.
  • Pull instead of push. The backup host connects in and reads. Nothing on the production server can touch the repository — but now the backup host holds a key into production, so you have inverted the trust rather than removed it. Reasonable when the backup host is genuinely more locked down; not obviously better otherwise.

The append-only option is the cheapest and the least conditional, so it is the one built below.

Then the question of where. A backup is a full copy of your server, and it sits under the law of the place you put it, on an account that belongs to somebody. Choosing a jurisdiction carefully for the server and then pushing nightly copies to a bucket somewhere else entirely is a common and quiet mistake — the jurisdiction of the copy is the jurisdiction of the data. Client-side encryption blunts this considerably: a demand served on your storage provider returns ciphertext. What it does not protect is availability, and it does not hide the fact that a repository exists, how large it is, or when it last changed.

Which is why the shape that solves the most problems at once is a second small server that you also own, in a different country from the first, rented the same way as the first: with an email address, no ID, and paid in Monero. Both ends are yours, both ends are cheap, the transfer never crosses a third party, and the copy is out of reach of whatever happens to the original’s jurisdiction or account.

Sizing it is easier than sizing a real server, because a backup target is disk with a CPU attached. What it does need is enough memory to run a prune and an integrity check without thrashing, which is the one operation that is genuinely hungry — so a gigabyte is thin and two is comfortable. From the plan grid:

  • Cub — 1 vCPU / 2 GB / 40 GB NVMe, $5.00/mo. The default. A normal web or application server with 10–15 GB of live data and a year of daily retention fits here comfortably, because deduplication and compression are doing most of the work.
  • Scout — 2 vCPU / 4 GB / 70 GB, $9.00/mo. Several servers into one repository, or a Nextcloud with photographs in it.
  • Runner and Hunter — 100 GB at $14.00 and 140 GB at $19.00. Where a mail spool, a media library or several years of history end up.
  • Pup — 1 vCPU / 1 GB / 25 GB, $3.50/mo. Fine for configuration and database dumps alone. Do not point a large file tree at it and expect maintenance to stay pleasant.

A working rule for the disk: budget two to three times the size of a single full backup, and you will have a year of history with room to be wrong. Put it somewhere that is not where the original is — Amsterdam, Paris, Bucharest and Sofia all sit at base price, Reykjavik multiplies by 1.20 and Zurich by 1.35, which makes a Cub in Switzerland $6.75 a month. The first upload is the only large transfer you will ever make, and traffic is unlimited at 1 Gbps, so seeding a repository does not produce an invoice at the end of the month.

گام به گام

  1. Decide what is irreplaceable, and write down the rest

    Before any tool, spend ten minutes sorting your server into three piles. This single exercise removes most of the cost and nearly all of the confusion.

    Irreplaceable — the things that exist nowhere else: databases, uploaded files, application state, TLS material you cannot re-issue, wallet files, SSH host keys, and /etc in its entirety, because /etc is a written record of every decision you made and forgot.

    Reproducible with effort — installed packages, container images, anything you could rebuild from a script if the script itself is in the first pile.

    Free to get again — the package cache, blockchain data, distribution media, build artefacts. Never back these up. On a node this is the difference between a 3 GB repository and a 300 GB one.

    Turn the third pile into an exclude file now, so it applies from the very first run:

    cat > /etc/backup-excludes <<'EOF'
    /dev
    /proc
    /sys
    /run
    /tmp
    /var/tmp
    /var/cache
    /var/lib/apt/lists
    /var/lib/docker/overlay2
    /swapfile
    /var/lib/bitcoind/blocks
    /var/lib/bitcoind/chainstate
    **/node_modules
    **/.cache
    EOF

    Docker deserves a note. Backing up /var/lib/docker is the wrong instinct: the layers are rebuildable and enormous. Back up your compose files and your named volumes — /var/lib/docker/volumes — and let the images come back from a registry.

  2. Stand up the backup target and give it one narrow job

    Deploy the second server — Cub is the default, Debian 13, in a different country from the one you are backing up. Give it the same ten-minute hardening pass as anything else: key-only SSH, no root login, a default-deny firewall. It is a machine holding a complete copy of another machine, so it is not the place to be relaxed.

    Then create a user whose entire existence is receiving backups, with no shell and no ability to do anything else:

    adduser --disabled-password --gecos '' --home /srv/backup --shell /bin/bash backup
    install -d -m 700 -o backup -g backup /srv/backup/.ssh
    apt install -y borgbackup      # or: apt install -y restic

    The shell is deliberately a real one. A forced SSH command is executed by the account’s login shell, so setting nologin here — the instinctive move — breaks the restriction you are about to add in step seven rather than strengthening it. The confinement comes from that command= line, not from the shell field.

    Generate a key on the production server for this and nothing else, so that revoking backup access never means touching your own login:

    ssh-keygen -t ed25519 -f /root/.ssh/id_backup -C 'backup@prod' -N ''

    Copy the public half to the target, into /srv/backup/.ssh/authorized_keys, owned by backup and mode 600. Leave it as an ordinary entry for now — step seven is where it gets its restrictions, once you have confirmed the whole chain works.

  3. Make the databases safe to copy

    This step is the difference between a backup and a file that looks like one. A database engine holds state in memory and writes to disk in its own order; copying that directory from outside captures a moment the engine never intended to be seen, and the result restores into something that will not start — or worse, starts and is subtly wrong.

    Dump first, on a schedule that runs before the backup does. For MariaDB or MySQL, --single-transaction gives a consistent snapshot of InnoDB tables without locking the application out:

    install -d -m 700 /var/backups/db
    mariadb-dump --single-transaction --quick --all-databases \
      | zstd -T0 > /var/backups/db/all-$(date +%F).sql.zst

    For PostgreSQL, run it as the postgres user; pg_dumpall also captures roles, which people discover they needed on restore day:

    su - postgres -c 'pg_dumpall' | zstd -T0 > /var/backups/db/pg-$(date +%F).sql.zst

    SQLite has its own trap, since a plain copy alongside an active write-ahead log can capture a torn state. Ask the library instead:

    sqlite3 /var/lib/app/app.db ".backup '/var/backups/db/app.db'"

    Keep only a couple of days of dumps on disk — the repository is what keeps history — and remember that /var/backups/db now contains everything your database contains, so mode 700 is not decoration. If you would rather not have plaintext dumps on disk at all, both tools read from a pipe: borg create ::db-{now} - with --stdin-name, or restic backup --stdin --stdin-filename.

  4. Initialise the repository, and put the passphrase where the server cannot lose it

    Generate a passphrase with real entropy, because it is the only thing standing between the repository and anyone holding it:

    openssl rand -base64 32

    Write it into your password manager and onto paper before you use it. Everything else in this guide is recoverable from a mistake; this is not. A repository whose passphrase existed only on the server it was protecting is the most complete and least useful backup it is possible to make.

    Then initialise. With Borg, over SSH to the user from step two, using an authenticated mode with the key stored in the repository — and immediately exporting that key somewhere else:

    export BORG_REPO='ssh://backup@backup.example.net/srv/backup/prod'
    borg init --encryption=repokey-blake2
    borg key export :: /root/borg-key.txt   # then move it OFF this machine

    With restic, the equivalent over SFTP:

    export RESTIC_REPOSITORY='sftp:backup@backup.example.net:/srv/backup/prod'
    export RESTIC_PASSWORD_FILE=/root/.restic-pass
    install -m 600 /dev/null /root/.restic-pass && nano /root/.restic-pass
    restic init

    Yes, the passphrase file sits on the production server — it has to, for an unattended job to run. That is precisely why the copy in your password manager and the copy on paper are the ones that matter, and why the next steps stop that server from being able to destroy anything.

  5. Run the first backup and read what it tells you

    The first run is the slow one: everything is new, so nothing deduplicates and nothing is cached. Run it by hand, in a terminal you can watch, and expect it to take a while on a large tree.

    borg create --stats --progress --compression zstd,3 \
      --exclude-from /etc/backup-excludes ::'prod-{now}' \
      /etc /home /root /srv /var/www /var/lib/docker/volumes /var/backups/db
    restic backup --verbose --exclude-file /etc/backup-excludes \
      /etc /home /root /srv /var/www /var/lib/docker/volumes /var/backups/db

    Then do the thing almost nobody does, which takes two minutes and catches most first-attempt mistakes — look at what you actually captured:

    borg list ::prod-... | less
    restic ls latest | less

    You are checking for two failures in opposite directions. Something important that is missing, because a path was wrong or an exclude pattern was greedier than intended. And something enormous that should not be there — a cache directory, a chain, a log archive — because that is the difference between a repository that fits its disk for years and one that fills it by spring. Fix the lists now, while the repository is small and re-running costs nothing.

  6. Automate it with a systemd timer, not a cron line

    Put the whole sequence — dump, back up, prune, report — into one script, so that there is exactly one thing to read when something breaks:

    install -m 700 /dev/null /usr/local/sbin/backup-run
    nano /usr/local/sbin/backup-run   # set -eu; dumps; borg create; ping the monitor

    Then a service and a timer. systemd is worth the two extra files here: the exit status is recorded, the output lands in the journal instead of in mail nobody reads, Persistent=true catches up a run the machine slept through, and a failure can trigger an alert unit directly.

    # /etc/systemd/system/backup.service
    [Unit]
    Description=Encrypted off-site backup
    OnFailure=backup-alert.service
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/sbin/backup-run
    Nice=10
    IOSchedulingClass=idle
    # /etc/systemd/system/backup.timer
    [Unit]
    Description=Nightly encrypted backup
    
    [Timer]
    OnCalendar=daily
    RandomizedDelaySec=45m
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    systemctl daemon-reload && systemctl enable --now backup.timer
    systemctl list-timers backup.timer
    journalctl -u backup.service -n 50

    Nice and IOSchedulingClass=idle keep the nightly run from making the site slow while it works. RandomizedDelaySec matters more than it looks: without it every machine you own starts at the same second, which is unkind to the target and to yourself.

  7. Take deletion away from the production server

    Now close the loop that most setups leave open. On the backup target, edit /srv/backup/.ssh/authorized_keys and pin the production key to one command that cannot remove anything:

    command="borg serve --append-only --restrict-to-path /srv/backup/prod",restrict ssh-ed25519 AAAA...

    Two mechanisms are working together. --append-only makes the server refuse every deletion regardless of what the client asks, and --restrict-to-path confines it to its own repository so one compromised host cannot reach another’s. The restrict option turns off port forwarding, agent forwarding and the rest, so the key opens nothing but this.

    The restic equivalent runs its REST server on the target and lets it enforce the same rule:

    rest-server --path /srv/backup --append-only --private-repos

    Test it properly, from the production server, by trying to do the forbidden thing:

    borg delete ::prod-...     # must fail
    borg create ::test-{now} /etc   # must succeed

    If the delete succeeds, the command= line is not being applied — usually a second unrestricted key still sitting in the file from step two. Pruning now happens on the target, where the repository is local: a weekly timer running borg prune and borg compact there, with the production server having no say in it at all.

  8. Restore it — then put the next drill in the calendar

    Everything up to here was preparation. This is the step that turns it into a backup.

    Start with integrity, which checks the repository’s own consistency. Read a sample of the actual data rather than only the metadata, because metadata-only checks pass on repositories that cannot be restored:

    borg check --verify-data ::
    restic check --read-data-subset=10%

    Then perform a real restore, into a scratch directory or, better, onto a freshly deployed server you throw away afterwards. Mounting is the fastest way to browse; extraction is the thing you will actually do at three in the morning:

    mkdir /mnt/r && borg mount ::prod-... /mnt/r      # browse
    borg extract ::prod-... etc/nginx                  # restore one path
    
    restic mount /mnt/r
    restic restore latest --target /tmp/restore --include /etc/nginx

    Now do the part that is not about files. Restore a database dump into a running engine and open the application against it. A dump that decompresses is not a dump that imports, and the gap between those two facts has ended more than one company:

    zstd -dc /tmp/restore/var/backups/db/all-2026-09-03.sql.zst | mariadb

    Write down how long the whole thing took and what you had to look up. That number is your actual recovery time, as opposed to the one you assume, and the notes are what make the second drill quick. Then schedule the next one — a quarter is a reasonable interval, and a calendar entry is a more reliable mechanism than intending to.

Retention: keeping enough history for a problem you have not noticed yet

Retention is where people quietly lose data they still had. Keeping seven daily snapshots feels responsible and defends only against problems you spot within a week. Silent corruption, a truncated database written by a bug, a file deleted in April and needed in June, an intruder who sat quietly before doing anything visible — all of these are discovered long after the seven days have rolled over, and by then every snapshot faithfully contains the damage.

The standard answer is a tiered policy, which costs almost nothing because deduplication means a monthly snapshot of slow-moving data is a rounding error:

restic forget --keep-daily 7 --keep-weekly 5 --keep-monthly 12 --keep-yearly 2 --prune
borg prune --keep-daily=7 --keep-weekly=5 --keep-monthly=12 --keep-yearly=2 ::
borg compact

Two mechanical details are worth knowing, because both have surprised people. In restic, forget removes snapshots from the index but reclaims nothing; prune is the step that actually deletes data, which is why the flag is there. In Borg, prune removes archives but the repository does not shrink until borg compact runs — a separate command precisely so that it can be scheduled separately.

And there is a genuine tension with the previous section: pruning requires deletion, and you have just taken deletion away from the client. That is the correct trade rather than a design flaw. Resolve it by pruning from the backup host, where the repository is local and the client has no say — a weekly timer on the target, running while the production server is not involved at all. If that is more machinery than you want, the alternative is a second SSH key without --append-only, kept off the production server and used by hand every few months. What you should not do is put the unrestricted key back on the server to make a cron job simpler.

Monitoring, because the failure mode is silence

A backup job that stops running produces exactly the same output as a backup job with nothing to do: nothing. This is the defining operational property of backups and the reason most broken ones stay broken for months. Three things are worth wiring up, in increasing order of value:

  • Alert on failure. A systemd unit can trigger another unit when it fails, with OnFailure=, and that unit can send you a message. Necessary, and the weakest of the three, because it only fires when something actually runs and reports an error.
  • Alert on age. Ask the repository when it last received anything and complain if the answer is more than a day or two old. This catches the timer that was masked, the disk that filled, the host that stopped resolving — every failure that never produced an error because nothing ever ran.
  • A dead man’s switch. Invert the logic: the job pings a URL on success and something external alerts you when the pings stop. This is the only one that survives the whole server going away, which is the failure you least want to learn about from a customer.

The check that pays for itself is the age one, and it is three lines:

#!/bin/sh
# alert if the newest snapshot is older than 36 hours
last=$(restic snapshots --json --latest 1 | grep -o '"time":"[^"]*"' | head -1 | cut -d'"' -f4)
[ $(( $(date +%s) - $(date -d "$last" +%s) )) -lt 129600 ] || echo "BACKUP STALE: $last"

Watch the disk on the target too. A full backup volume fails every job from then on, and it fails at the end — after the transfer, which is the most expensive way to discover it. An alert at eighty per cent gives you weeks of warning; the alternative gives you none.

The failure modes that actually cost people their data

Roughly in order of how often they turn a backup into a souvenir:

  • The database was copied while it was running. An InnoDB data directory captured mid-write restores into a database that will not start, and it does so silently — the backup completes, the files are all there, the size looks right. Dump first. This is step three for a reason.
  • The password was only on the server. A flawless encrypted repository whose passphrase lived in /root on the machine that burned down is high-quality noise. So is a passphrase in a password manager whose only copy syncs through that same server.
  • Nobody ever restored. The exclude list was too aggressive, the database dump was empty for three months, the path was wrong. Every one of these is invisible until a restore, and obvious within ten minutes of one.
  • The backups were on the same account. Same provider, same login, same billing relationship. It works for disk failure and for nothing else.
  • The client could delete. Ransomware removes the backups before it touches the data, because that is the whole business model. Append-only, or accept that this scenario is not covered.
  • The target quietly filled up. Retention never pruned, or a new large directory was added to the include list. Every job after that fails, and if you were not monitoring age, nothing tells you.
  • The blockchain was in the backup. Backing up a Bitcoin or Monero data directory means paying to store a public ledger you can re-download for free. Back up the wallet and the configuration; exclude the chain.
  • The exclude list ate something. A pattern meant for /var/cache that also matched an application’s cache directory containing state it never rebuilt. Read the file list of your first backup once, properly.
  • The restore needed the key that was in the repository. Borg’s repokey mode keeps the key inside the repository, which is convenient until the repository is the thing you lost. borg key export to somewhere else, once, at the start.

What backups do not do

Four honest limits, because a guide that oversells this is doing the same thing as an untested backup.

A backup is not high availability. It shortens an outage; it does not prevent one. Restoring a server means provisioning, pulling, extracting and reconfiguring — comfortably an hour for something small, and considerably more if the last time you tried was never. If an hour of downtime is unacceptable, the answer is a standby machine, and the backup remains necessary for everything the standby faithfully replicates, including your mistakes.

Encryption does not make the copy invisible. It makes it unreadable, which is not the same claim. Whoever hosts the repository can still see that it exists, how big it is, and when it last changed — and the account that pays for it is an identifying detail like any other. If the reason you rented the original with no ID still applies, it applies to the second machine as well; the same checkout covers both.

Encrypted at rest is not encrypted end to end in every sense. restic and Borg protect the repository. They do not protect the running server, where the data is plaintext by definition, and they do not help if the passphrase is compromised along with the machine that held it. Full-disk encryption on the source and a passphrase kept off both machines are complementary controls, not redundant ones.

And a copy in another country is friction, not immunity. Jurisdiction changes who has to ask whom, and how long it takes — a point the offshore hosting entry makes at length. Both machines here operate under the same plainly stated acceptable-use policy, with the same hard floor under it. What the arrangement genuinely buys is that no single failure — a dead disk, a bad command, an intruder, a frozen account — takes the original and the copy at the same time. That is what a backup is for, and it is enough.

پرسش‌های متداول

Is a provider snapshot enough?

No, and it is the most common gap. A snapshot lives on the same infrastructure, inside the same account, taken by the same provider — so it covers a broken filesystem or a bad upgrade and covers none of the other cases: an attacker with your credentials, a suspended or lost account, a jurisdiction problem, a provider that stops answering. Snapshots are a fast undo button and a genuinely useful one. A backup is a copy that survives the loss of the whole account, which is why our documentation says backups are your responsibility rather than implying otherwise.

restic or Borg — which should I use?

If you control the far end, Borg, because borg serve --append-only is a server-enforced guarantee that a compromised client cannot delete your history, and that is the single most valuable property in a backup system. If the far end is a bucket or a machine where you cannot install software, restic, because it is one static binary that talks to S3, SFTP, its own REST server or anything rclone reaches. Both encrypt and authenticate on the client, both deduplicate, both compress. Choose on the destination, then stop comparing and go test a restore.

What size VPS do I need as a backup target?

Cub (1 vCPU / 2 GB / 40 GB NVMe, $5.00/mo) is the default and holds a year of daily snapshots for a normal web or application server, because deduplication and compression mean history costs far less than copies. Scout (2 vCPU / 4 GB / 70 GB, $9.00/mo) suits several servers or a Nextcloud with photographs; 100 GB and 140 GB follow at $14.00 and $19.00. Budget two to three times a single full backup for the disk, and prefer 2 GB of memory over 1 GB — prune and integrity checks are the operations that need it.

Can I just back up to a cloud drive or an S3 bucket?

Technically yes — restic writes to S3-compatible storage directly and to almost anything else through rclone, and because encryption happens before the upload, the provider stores ciphertext it cannot read. Two things change, though. The account is a card, a name and a jurisdiction attached to a complete copy of your server, which is worth noticing if the original was rented with an email address and paid in crypto. And immutability now depends on that provider’s object-lock implementation rather than on a line you control in authorized_keys. A second small server you own is usually cheaper and always more predictable.

How do I back up a database that is being written to?

Never by copying its data directory. Dump it first, then back up the dump: mariadb-dump --single-transaction for MariaDB or MySQL, which gives a consistent view of InnoDB without locking the application out; pg_dumpall as the postgres user for PostgreSQL, which also captures roles; and sqlite3 db ".backup out.db" for SQLite, where copying the file next to a live write-ahead log can capture a torn state. A file-level copy of a running engine restores into a database that will not start, and it fails silently — the backup completes and looks entirely normal.

What happens if I lose the repository passphrase?

The data is gone. That is not a policy anyone can appeal — the encryption is done on your machine with your key, and neither we nor the tool’s authors have any way in. It is the correct design and it is also why the passphrase belongs in a password manager and on paper before the first backup runs, never only on the server it protects. With Borg, note that repokey mode stores the key inside the repository, so borg key export to somewhere else at the start — otherwise losing the repository loses the means to read any copy of it you might still have.

How often should I test a restore?

Quarterly for a full drill, and once immediately after any significant change to what you back up. The full drill means a real restore onto a scratch server, a database dump imported into a running engine, and the application opened against it — not a listing of the archive, which proves only that the archive exists. Time it. That number is your real recovery time, and it is almost always longer than the one people assume. Between drills, an automated integrity check with --verify-data or --read-data-subset and an alert on snapshot age cover the rest.

در حدود یک دقیقه یک VPS آفشور راه‌اندازی کنید

بدون KYC، پرداخت کریپتو، تماماً NVMe. یک پلن انتخاب کنید، با مونرو یا هر کوین اصلی پرداخت کنید و در حدود ۶۰ ثانیه دسترسی root بگیرید.

Fenrir در حال محافظت